This commit is contained in:
2026-11-03 11:51:44 +02:00
parent badaada043
commit e753f7a0a4
309 changed files with 14537 additions and 529 deletions
@@ -2,10 +2,14 @@
use App\Models\Requisition;
use App\Services\AutomaticPurchases;
use App\Services\ReplenishmentHeartbeat;
use App\Services\ReplenishmentQueue;
use App\Services\SupplyPlanning;
use App\Services\WarehousePilotReadiness;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Str;
use Inertia\Testing\AssertableInertia as Assert;
@@ -19,6 +23,15 @@ beforeEach(function () {
$this->actingAs($this->f['receiver']);
$this->f['policy'] = app(SupplyPlanning::class)->save($this->f['receiver'], 'policy', supplyInput([], 'approve', $policy));
supplyGrant($this->f['otherReceiver'], ['admin']);
$this->readinessOriginalStorage = app()->storagePath();
$this->readinessStorage = $this->readinessOriginalStorage.'/framework/testing/readiness-'.Str::uuid();
File::ensureDirectoryExists($this->readinessStorage.'/framework');
app()->useStoragePath($this->readinessStorage);
});
afterEach(function () {
app()->useStoragePath($this->readinessOriginalStorage);
File::deleteDirectory($this->readinessStorage);
});
function pilotReadinessRule($test): void
@@ -118,6 +131,31 @@ test('optional scheduler telemetry is isolated and a stale or damaged file does
}
});
test('native scheduler observation is available outside evaluation and takes precedence over helper telemetry', function () {
$originalStorage = app()->storagePath();
$originalEnv = app()->environment();
$temporary = $originalStorage.'/framework/testing/native-status-'.Str::uuid();
mkdir($temporary.'/framework', 0755, true);
app()->useStoragePath($temporary);
app()->instance('env', 'production');
$this->actingAs($this->f['otherReceiver']);
try {
app(ReplenishmentHeartbeat::class)->record(now()->toIso8601String(), 0);
$status = app(ReplenishmentQueue::class)->status($this->f['otherReceiver']);
expect($status['schedulerRecent'])->toBeTrue()->and($status['schedulerStatus']['result'])->toBe('passed');
app(ReplenishmentHeartbeat::class)->record(now()->toIso8601String(), 1);
file_put_contents($temporary.'/framework/replenishment-status.json', json_encode(['result' => 'passed', 'finished_at' => now()->toIso8601String()], JSON_THROW_ON_ERROR));
app()->instance('env', 'payable-testing');
expect(app(ReplenishmentQueue::class)->status($this->f['otherReceiver'])['schedulerStatus']['result'])->toBe('retry_pending');
file_put_contents($temporary.'/framework/replenishment-command-status.json', '{broken');
expect(app(ReplenishmentQueue::class)->status($this->f['otherReceiver'])['schedulerStatus'])->toBeNull();
} finally {
app()->useStoragePath($originalStorage);
app()->instance('env', $originalEnv);
File::deleteDirectory($temporary);
}
});
test('a recent successful scheduler does not hide durable work still awaiting recovery', function () {
pilotReadinessRule($this);
$this->actingAs($this->f['otherReceiver']);
@@ -143,3 +181,21 @@ test('a recent successful scheduler does not hide durable work still awaiting re
rmdir($temporary);
}
});
test('command readiness does not certify a pilot missing receipt storage or the requisition version', function (string $missing) {
supplyGrant($this->f['issuer'], ['warehouse_request_prepare']);
supplyGrant($this->f['receiver'], ['warehouse_request_review']);
supplyGrant($this->f['otherReceiver'], ['warehouse', 'warehouse_request_deliver']);
pilotReadinessRule($this);
$this->actingAs($this->f['otherReceiver']);
expect(app(WarehousePilotReadiness::class)->inspect($this->f['otherReceiver'])['warehouse_scenario_ready'])->toBeTrue();
$counts = [DB::table('requisitions')->count(), DB::table('stock_movements')->count(), DB::table('audit_logs')->count()];
if ($missing === 'receipts') {
Schema::drop('requisition_commands');
} else {
Schema::table('requisitions', fn (Blueprint $table) => $table->dropColumn('process_version'));
}
$report = app(WarehousePilotReadiness::class)->inspect($this->f['otherReceiver']);
expect($report['checks'][0]['ok'])->toBeFalse()->and($report['warehouse_scenario_ready'])->toBeFalse()->and($report['replenishment_scenario_ready'])->toBeFalse()
->and($report['tables'][$missing === 'receipts' ? 'requisition_commands' : 'requisition_process_version'])->toBeFalse()
->and([DB::table('requisitions')->count(), DB::table('stock_movements')->count(), DB::table('audit_logs')->count()])->toBe($counts);
})->with(['receipts', 'version']);