98 lines
3.4 KiB
PHP
98 lines
3.4 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
declare(strict_types=1);
|
||
|
|
|
||
|
|
use App\Models\Project;
|
||
|
|
use App\Models\SupplierManualSyncQueue;
|
||
|
|
use App\Models\Tenant;
|
||
|
|
use Illuminate\Database\QueryException;
|
||
|
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||
|
|
use Illuminate\Support\Facades\DB;
|
||
|
|
|
||
|
|
uses(DatabaseTransactions::class);
|
||
|
|
|
||
|
|
it('table supplier_manual_sync_queue exists with required columns', function (): void {
|
||
|
|
$cols = collect(DB::select(
|
||
|
|
"SELECT column_name FROM information_schema.columns WHERE table_name = 'supplier_manual_sync_queue'"
|
||
|
|
))->pluck('column_name')->all();
|
||
|
|
|
||
|
|
expect($cols)->toContain(
|
||
|
|
'id', 'project_id', 'platform', 'operation', 'external_id',
|
||
|
|
'payload_snapshot', 'failure_reason', 'status',
|
||
|
|
'resolved_by_user_id', 'created_at', 'resolved_at',
|
||
|
|
);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('platform CHECK constraint rejects non-B1/B2/B3', function (): void {
|
||
|
|
$tenant = Tenant::factory()->create();
|
||
|
|
$project = Project::factory()->for($tenant)->create();
|
||
|
|
|
||
|
|
expect(fn () => DB::table('supplier_manual_sync_queue')->insert([
|
||
|
|
'project_id' => $project->id,
|
||
|
|
'platform' => 'B9',
|
||
|
|
'operation' => 'create',
|
||
|
|
'payload_snapshot' => json_encode([]),
|
||
|
|
'failure_reason' => 'portal_unreachable',
|
||
|
|
'status' => 'pending',
|
||
|
|
'created_at' => now(),
|
||
|
|
]))->toThrow(QueryException::class);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('operation CHECK constraint rejects non-create/update', function (): void {
|
||
|
|
$tenant = Tenant::factory()->create();
|
||
|
|
$project = Project::factory()->for($tenant)->create();
|
||
|
|
|
||
|
|
expect(fn () => DB::table('supplier_manual_sync_queue')->insert([
|
||
|
|
'project_id' => $project->id,
|
||
|
|
'platform' => 'B1',
|
||
|
|
'operation' => 'delete',
|
||
|
|
'payload_snapshot' => json_encode([]),
|
||
|
|
'failure_reason' => 'portal_unreachable',
|
||
|
|
'status' => 'pending',
|
||
|
|
'created_at' => now(),
|
||
|
|
]))->toThrow(QueryException::class);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('status CHECK constraint rejects non-pending/resolved/cancelled', function (): void {
|
||
|
|
$tenant = Tenant::factory()->create();
|
||
|
|
$project = Project::factory()->for($tenant)->create();
|
||
|
|
|
||
|
|
expect(fn () => DB::table('supplier_manual_sync_queue')->insert([
|
||
|
|
'project_id' => $project->id,
|
||
|
|
'platform' => 'B1',
|
||
|
|
'operation' => 'create',
|
||
|
|
'payload_snapshot' => json_encode([]),
|
||
|
|
'failure_reason' => 'portal_unreachable',
|
||
|
|
'status' => 'archived',
|
||
|
|
'created_at' => now(),
|
||
|
|
]))->toThrow(QueryException::class);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('FK on project_id enforces referential integrity', function (): void {
|
||
|
|
expect(fn () => DB::table('supplier_manual_sync_queue')->insert([
|
||
|
|
'project_id' => 999_999_999,
|
||
|
|
'platform' => 'B1',
|
||
|
|
'operation' => 'create',
|
||
|
|
'payload_snapshot' => json_encode([]),
|
||
|
|
'failure_reason' => 'portal_unreachable',
|
||
|
|
'status' => 'pending',
|
||
|
|
'created_at' => now(),
|
||
|
|
]))->toThrow(QueryException::class);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('Eloquent model SupplierManualSyncQueue creates row and casts payload_snapshot to array', function (): void {
|
||
|
|
$tenant = Tenant::factory()->create();
|
||
|
|
$project = Project::factory()->for($tenant)->create();
|
||
|
|
|
||
|
|
$row = SupplierManualSyncQueue::create([
|
||
|
|
'project_id' => $project->id,
|
||
|
|
'platform' => 'B1',
|
||
|
|
'operation' => 'create',
|
||
|
|
'payload_snapshot' => ['limit' => 10, 'workdays' => [1, 2, 3]],
|
||
|
|
'failure_reason' => 'contract_break',
|
||
|
|
'status' => 'pending',
|
||
|
|
]);
|
||
|
|
|
||
|
|
expect($row->fresh()->payload_snapshot)->toBe(['limit' => 10, 'workdays' => [1, 2, 3]]);
|
||
|
|
});
|