make(\Illuminate\Contracts\Console\Kernel::class)->bootstrap(); use App\Models\User; use App\Modules\Identity\Services\Permissions; use App\Shared\Testing\TestingDatabaseGuard; use Illuminate\Support\Facades\DB; use Tests\Support\{DocumentPreviewFixture, WorkshopCorrectionFixture, IndustrialBudgetFixture, ReceivablesFixture}; TestingDatabaseGuard::assertSafe(); \App\Modules\Services\ServiceInvoicing::guard(); $file = 'C:/laragon/data/sgf-tempo/secrets/browser-fixture.json'; $verify = in_array('--verify', $argv, true); $manifest = is_file($file) ? json_decode(file_get_contents($file), true, 64, JSON_THROW_ON_ERROR) : null; if (isset($manifest['product_demo'])) { foreach ($manifest['product_demo']['actors'] as $role => $id) User::findOrFail($id); echo json_encode(['demo' => $manifest['product_demo'], 'changed' => false], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR).PHP_EOL; exit; } // A missing manifest must never silently adopt unrelated test records. if (!$manifest && DB::table('users')->exists()) throw new RuntimeException('Existing test data has no manifest. Nothing reset; recover its manifest first.'); if ($manifest && empty($manifest['password'])) throw new RuntimeException('Synthetic credential manifest required; no passwords changed.'); foreach (['ic_lots', 'si_invoices'] as $table) { if (DB::table($table)->exists()) throw new RuntimeException('Existing isolated scenario requires reconciliation: '.$table.'. Nothing deleted.'); } DB::beginTransaction(); try { if ($manifest) { $base = array_intersect_key($manifest, array_flip(['tenant', 'otherTenant', 'company', 'sibling', 'foreign', 'unit', 'hidden', 'siblingUnit', 'password'])); $base['manager'] = User::findOrFail($manifest['manager_id']); $base['reader'] = User::findOrFail($manifest['reader_id']); } else { $base = DocumentPreviewFixture::create(); $manifest = array_intersect_key($base, array_flip(['tenant', 'otherTenant', 'company', 'sibling', 'foreign', 'unit', 'hidden', 'siblingUnit', 'password'])); $manifest['manager_id'] = $base['manager']->id; $manifest['reader_id'] = $base['reader']->id; } if (isset($manifest['workshop_corrections'])) { $workshop = $manifest['workshop_corrections']; $tech = User::where('email', 'tecnico-oficina@example.test')->firstOrFail(); $reviewer = User::where('email', 'verificador-oficina@example.test')->firstOrFail(); if (!DB::table('wo_orders')->where(['id' => $workshop['order'], 'company_id' => $base['company'], 'unit_id' => $base['unit']])->exists()) throw new RuntimeException('Workshop manifest differs.'); } else { if (DB::table('wo_orders')->exists()) throw new RuntimeException('Existing workshop has no reconciled manifest. Nothing overwritten.'); $w = WorkshopCorrectionFixture::create($base); $workshop = array_intersect_key($w, array_flip(['order', 'time', 'material', 'service', 'client', 'generation', 'service_draft', 'billing_draft'])); $tech = $w['technician']; $reviewer = $w['reviewer']; $manifest['workshop_corrections'] = $workshop; } $industry = IndustrialBudgetFixture::create($base); $receivables = ReceivablesFixture::create($base); $actors = ['preparador' => $base['manager']->id, 'validador' => $base['reader']->id, 'tecnico' => $tech->id, 'verificador' => $reviewer->id]; if (count(array_unique($actors)) !== 4) throw new RuntimeException('Four distinct synthetic actors required.'); $permissions = app(Permissions::class); foreach (['preparador' => ['workshop.verify', 'industrial_costs.validate'], 'validador' => ['workshop.record', 'industrial_costs.prepare'], 'tecnico' => ['workshop.verify'], 'verificador' => ['workshop.record']] as $role => $forbidden) { foreach ($forbidden as $right) if ($permissions->has($actors[$role], $base['tenant'], $base['company'], $right, $base['unit'])) throw new RuntimeException('Role separation differs: '.$role); } $demo = ['version' => 'SGF-PRODUCT-DEMO-v1', 'synthetic_only' => true, 'actors' => $actors, 'workshop' => $workshop, 'industry' => array_intersect_key($industry, array_flip(['lot', 'refs', 'result'])), 'receivables' => array_intersect_key($receivables, array_flip(['source', 'draft', 'invoice', 'series', 'rule'])), 'prepared_at' => now()->toIso8601String()]; if ($verify) { DB::rollBack(); } else { // Manifest and data are committed together as far as possible; retain old file on write failure. $encoded = json_encode($manifest + ['product_demo' => $demo], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR); if (file_put_contents($file, $encoded, LOCK_EX) === false) throw new RuntimeException('Cannot save protected manifest.'); try { DB::commit(); } catch (\Throwable $e) { file_put_contents($file, json_encode($manifest, JSON_THROW_ON_ERROR), LOCK_EX); throw $e; } } echo json_encode(['demo' => $demo, 'rolled_back' => $verify, 'client_database_changed' => false, 'credentials' => 'existing protected local manifest only', 'real_grants_created' => false], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR).PHP_EOL; } catch (\Throwable $e) { if (DB::transactionLevel()) DB::rollBack(); throw $e; }