51 lines
5.9 KiB
PHP
51 lines
5.9 KiB
PHP
<?php
|
|
|
|
use App\Enums\PurchasingRole;
|
|
use App\Models\CostCenter;
|
|
use App\Models\Department;
|
|
use App\Models\PurchaseAward;
|
|
use App\Models\PurchaseOrder;
|
|
use App\Models\Quotation;
|
|
use App\Models\Requisition;
|
|
use App\Models\StockItem;
|
|
use App\Models\Supplier;
|
|
use App\Models\Tenant;
|
|
use App\Models\User;
|
|
use App\Models\Warehouse;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Str;
|
|
|
|
/** Synthetic fixture: callable only on in-memory SQLite or the dedicated PostgreSQL test database. */
|
|
function payableReceiptFixture(string $quantity = '1.000', string $purchaseType = 'consumable'): array
|
|
{
|
|
$connection = DB::connection();
|
|
$allowed = ($connection->getDriverName() === 'sqlite' && $connection->getDatabaseName() === ':memory:') ||
|
|
($connection->getDriverName() === 'pgsql' && preg_match('/^compras_receipts_test_[a-f0-9]{12}$/', $connection->getDatabaseName()));
|
|
if (! app()->environment('testing') || ! $allowed) {
|
|
throw new LogicException('Fixtures de recepção proibidas fora de uma base de testes isolada.');
|
|
}
|
|
$tenant = Tenant::query()->create(['name' => 'Horizonte Sintética — Obrigações']);
|
|
$department = Department::query()->create(['tenant_id' => $tenant->id, 'name' => 'Operações']);
|
|
$center = CostCenter::query()->create(['tenant_id' => $tenant->id, 'department_id' => $department->id, 'code' => 'OPS', 'name' => 'Operações']);
|
|
$issuer = User::factory()->create(['tenant_id' => $tenant->id, 'department_id' => $department->id, 'purchasing_role' => PurchasingRole::Procurement]);
|
|
$receiver = User::factory()->create(['tenant_id' => $tenant->id, 'department_id' => $department->id, 'purchasing_role' => PurchasingRole::Warehouse]);
|
|
$otherReceiver = User::factory()->create(['tenant_id' => $tenant->id, 'department_id' => $department->id, 'purchasing_role' => PurchasingRole::Warehouse]);
|
|
auth()->guard()->setUser($receiver);
|
|
$r = Requisition::query()->create(['tenant_id' => $tenant->id, 'requester_id' => $issuer->id, 'department_id' => $department->id, 'cost_center_id' => $center->id, 'number' => 'REQ-TEST-'.Str::random(10), 'priority' => 'normal', 'needed_by' => now()->addWeek(), 'justification' => 'Fixture de ordem já emitida para testes de recepção.', 'status' => 'approved', 'subtotal_minor' => 1000000, 'tax_minor' => 160000, 'total_minor' => 1160000]);
|
|
$requested = $r->items()->create(['tenant_id' => $tenant->id, 'description' => 'Artigo fictício', 'category' => 'Material', 'purchase_type' => $purchaseType, 'quantity' => $quantity, 'unit' => 'cx', 'unit_price_minor' => 1000000, 'tax_rate' => '16', 'subtotal_minor' => 1000000, 'tax_minor' => 160000, 'total_minor' => 1160000]);
|
|
$supplier = Supplier::query()->create(['tenant_id' => $tenant->id, 'created_by' => $issuer->id, 'name' => 'Fornecedor Alfa Sintético', 'nuit' => '123456789', 'contact' => 'Contacto de teste', 'email' => 'fixture@example.invalid', 'phone' => '000000000', 'address' => 'Morada fictícia', 'category' => 'Material', 'beneficiaries' => 'Beneficiário fictício', 'document_references' => 'Documento fictício', 'diligence_notes' => 'Somente para a base de testes.', 'status' => 'active', 'next_review' => now()->addYear()]);
|
|
$quote = Quotation::query()->create(['tenant_id' => $tenant->id, 'requisition_id' => $r->id, 'supplier_id' => $supplier->id, 'created_by' => $issuer->id, 'reference' => 'PROP-TEST', 'delivery_days' => 5, 'valid_until' => now()->addWeek(), 'payment_terms' => '30 dias', 'subtotal_minor' => 1000000, 'tax_minor' => 160000, 'total_minor' => 1160000, 'weights' => ['price' => 40, 'quality' => 20, 'delivery' => 15, 'history' => 15, 'payment' => 10]]);
|
|
$award = PurchaseAward::query()->create(['tenant_id' => $tenant->id, 'requisition_id' => $r->id, 'quotation_id' => $quote->id, 'created_by' => $issuer->id, 'justification' => 'Adjudicação de fixture, não repetir o fluxo anterior.', 'delivery_date' => now()->addWeek(), 'delivery_location' => 'Armazém fictício', 'status' => 'approved', 'subtotal_minor' => 1000000, 'tax_minor' => 160000, 'total_minor' => 1160000, 'approval_snapshot' => [], 'decision_matrix' => [], 'comparison_hash' => str_repeat('0', 64)]);
|
|
$order = PurchaseOrder::query()->create(['tenant_id' => $tenant->id, 'requisition_id' => $r->id, 'purchase_award_id' => $award->id, 'supplier_id' => $supplier->id, 'issued_by' => $issuer->id, 'number' => 'OC-TEST-'.Str::random(10), 'status' => 'issued', 'currency' => 'MZN', 'subtotal_minor' => 1000000, 'tax_minor' => 160000, 'total_minor' => 1160000, 'issued_at' => now(), 'snapshot' => ['supplier' => $supplier->only(['name', 'nuit']), 'company' => ['name' => $tenant->name], 'development_only' => true, 'budget_checked' => false]]);
|
|
$line = $order->items()->create(['tenant_id' => $tenant->id, 'requisition_item_id' => $requested->id, 'description' => 'Artigo fictício', 'category' => 'Material', 'purchase_type' => $purchaseType, 'unit' => 'cx', 'quantity' => $quantity, 'unit_price_minor' => 1000000, 'tax_rate' => '16', 'subtotal_minor' => 1000000, 'tax_minor' => 160000, 'total_minor' => 1160000]);
|
|
$warehouse = Warehouse::query()->create(['tenant_id' => $tenant->id, 'created_by' => $receiver->id, 'code' => 'ARM-TEST', 'name' => 'Armazém fictício']);
|
|
$stock = StockItem::query()->create(['tenant_id' => $tenant->id, 'created_by' => $receiver->id, 'code' => 'ART-TEST', 'name' => 'Artigo de stock fictício', 'unit' => 'cx']);
|
|
|
|
return compact('tenant', 'department', 'issuer', 'receiver', 'otherReceiver', 'r', 'order', 'line', 'warehouse', 'stock');
|
|
}
|
|
|
|
function payableReceiptPayload(array $fixture, string $quantity = '0.600'): array
|
|
{
|
|
return ['idempotency_key' => (string) Str::uuid(), 'delivery_note' => 'GR-'.Str::random(10), 'received_on' => now()->format('Y-m-d'), 'warehouse_id' => $fixture['warehouse']->id, 'items' => [['purchase_order_item_id' => $fixture['line']->id, 'received_quantity' => $quantity, 'accepted_quantity' => $quantity, 'quality_status' => 'compliant', 'stock_item_id' => $fixture['stock']->id, 'notes' => null]]];
|
|
}
|