86 lines
5.5 KiB
PHP
86 lines
5.5 KiB
PHP
<?php
|
|
|
|
// Consolidates existing synthetic fixtures; never migrates, resets or touches client data.
|
|
require __DIR__.'/../vendor/autoload.php';
|
|
$app = require __DIR__.'/../bootstrap/app.php';
|
|
$app->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;
|
|
}
|