Files

79 lines
5.1 KiB
PHP

<?php
use Illuminate\Support\Facades\DB;
function budgetQaAssert(bool $condition, string $message): void
{
if (! $condition) throw new RuntimeException($message);
}
function budgetQaFixture(string $mode): array
{
if ($mode === 'compras') {
require_once base_path('tests/Support/ReceiptFixture.php');
$f = receiptFixture();
$a = \App\Models\User::factory()->create(['tenant_id'=>$f['tenant']->id,'department_id'=>$f['department']->id,'purchasing_role'=>'finance']);
$v = \App\Models\User::factory()->create(['tenant_id'=>$f['tenant']->id,'department_id'=>$f['department']->id,'purchasing_role'=>'admin']);
return ['actor'=>$a->id,'validator'=>$v->id,'tenant'=>$f['tenant']->id,'centre'=>$f['r']->cost_center_id,'origin'=>$f['r']->id,'invoice'=>$f['order']->id,'scope'=>['tenant_id'=>$f['tenant']->id]];
}
$now = now();
$tenant = DB::table('tenants')->insertGetId(['name'=>'Synthetic tenant','created_at'=>$now,'updated_at'=>$now]);
// Deliberately different tenant/company/unit identifiers, no numeric equivalence.
DB::table('companies')->insert(['tenant_id'=>$tenant,'name'=>'Unused synthetic company','created_at'=>$now,'updated_at'=>$now]);
$company = DB::table('companies')->insertGetId(['tenant_id'=>$tenant,'name'=>'Synthetic purchaser','created_at'=>$now,'updated_at'=>$now]);
DB::table('units')->insert(['tenant_id'=>$tenant,'company_id'=>$company,'name'=>'Reserved','created_at'=>$now,'updated_at'=>$now]);
$unit = DB::table('units')->insertGetId(['tenant_id'=>$tenant,'company_id'=>$company,'name'=>'Purchasing QA','created_at'=>$now,'updated_at'=>$now]);
$scope = ['tenant_id'=>$tenant,'company_id'=>$company,'unit_id'=>$unit];
$a = \App\Models\User::create(['name'=>'Synthetic preparer','email'=>'prepare-'.bin2hex(random_bytes(6)).'@example.test','password'=>bin2hex(random_bytes(20))]);
$v = \App\Models\User::create(['name'=>'Synthetic validator','email'=>'validate-'.bin2hex(random_bytes(6)).'@example.test','password'=>bin2hex(random_bytes(20))]);
foreach ([$a,$v] as $u) {
DB::table('company_memberships')->insert(['user_id'=>$u->id,'tenant_id'=>$tenant,'company_id'=>$company]);
foreach (['company.view'=>null,'unit.view'=>$unit] as $right=>$unitId) DB::table('permission_grants')->insert(['user_id'=>$u->id,'tenant_id'=>$tenant,'company_id'=>$company,'unit_id'=>$unitId,'permission'=>$right,'created_at'=>$now,'updated_at'=>$now]);
}
foreach ([$a->id=>['create','record','consume','view','reinforcement.propose'],$v->id=>['approve','view','reinforcement.review']] as $id=>$rights) foreach ($rights as $right) DB::table('permission_grants')->insert($scope+['user_id'=>$id,'permission'=>'purchasing_budget.'.$right,'created_at'=>$now,'updated_at'=>$now]);
$centre = DB::table('cb_centres')->insertGetId($scope+['code'=>'CENTRE-TEST']);
$origin = DB::table('cb_origins')->insertGetId($scope+['cost_center_id'=>$centre,'required_kind'=>'operating','reference'=>'REQ-'.bin2hex(random_bytes(6))]);
return ['actor'=>$a->id,'validator'=>$v->id,'tenant'=>$tenant,'company'=>$company,'unit'=>$unit,'centre'=>$centre,'origin'=>$origin,'invoice'=>$origin,'scope'=>$scope];
}
function budgetQaSelect(string $mode, array $f, string $role='actor'): object
{
$user = \App\Models\User::findOrFail($f[$role]);
auth()->guard()->setUser($user);
if ($mode === 'sgf') app(\App\Shared\Context\CompanyContext::class)->selectFor($user->id,$f['tenant'],$f['company'],$f['unit']);
return $user;
}
function budgetQaEngine(string $mode, array $f, string $role='actor'): \Tempo\Finance\Budget\BudgetControl
{
$user = budgetQaSelect($mode,$f,$role);
return $mode === 'compras' ? app(\App\Services\CommonBudget::class)->for($user) : app(\App\Modules\Purchasing\BudgetAdapter::class)->for($user);
}
function budgetQaRecord(string $mode, array $f, string $kind, int $amount=0): mixed
{
$user = budgetQaSelect($mode,$f);
return DB::transaction(function () use ($mode,$f,$kind,$amount,$user) {
if ($mode === 'compras') {
$request = \App\Models\Requisition::findOrFail($f['origin']);
return app(\App\Services\BudgetWorkflow::class)->record($user,$request,$kind,$amount,$amount);
}
return app(\App\Modules\Purchasing\BudgetAdapter::class)->record($user,$f['origin'],$kind,$amount,$amount);
});
}
function budgetQaCreate(string $mode, array $f, int $amount=100000, bool $tax=true): int
{
$data = ['cost_center_id'=>$f['centre'],'year'=>(int)now()->year,'kind'=>'operating','amount_minor'=>$amount,'includes_tax'=>$tax,'reason'=>'Synthetic allocation'];
$user = budgetQaSelect($mode,$f);
$id = $mode==='compras' ? budgetQaEngine($mode,$f)->create($data) : app(\App\Modules\Purchasing\BudgetAdapter::class)->create($user,$data);
budgetQaEngine($mode,$f,'validator')->approve($id);
return $id;
}
function budgetQaReject(callable $work, string $message): void
{
try { $work(); } catch (\Tempo\Finance\Budget\BudgetFailure|\Illuminate\Validation\ValidationException|\Symfony\Component\HttpKernel\Exception\HttpException $e) { return; }
throw new RuntimeException('Expected rejection: '.$message);
}