24 lines
7.2 KiB
PHP
24 lines
7.2 KiB
PHP
<?php
|
|
use Illuminate\Support\Facades\DB;
|
|
use App\Shared\Geography\{Catalogue,Cartography};
|
|
$s=json_decode(file_get_contents(getenv('RECEIPT_COMPOSITION_STATE')),true);if(!($s['geography']??false)||is_file($s['root'].'/geography-baseline.json'))throw new LogicException('Fresh geography composition required');require $s['app'].'/vendor/autoload.php';$app=require $s['app'].'/bootstrap/app.php';$app->make(Illuminate\Contracts\Console\Kernel::class)->bootstrap();Catalogue::guard();$f=json_decode(file_get_contents($s['root'].'/fixture.json'),true);$run=getenv('SGF_ISOLATED_REGRESSION_RUN');$private='C:/laragon/data/sgf-tempo/run/modular-regression-'.$run.'/private';$proof=json_decode(file_get_contents(dirname(__DIR__).'/docs/proofs/cartography-preparation-20261103.json'),true);$file=$private.'/cartography-prepared-20261103.json';if(hash_file('sha256',$file)!==$proof['prepared_sha256'])throw new LogicException('Prepared catalogue changed');$c=json_decode(file_get_contents($file),true,128,JSON_THROW_ON_ERROR);if($c['source']['sha256']!==config('geography.source_sha256')||$c['total']!==20407)throw new LogicException('Pinned catalogue required');
|
|
$definition=DB::selectOne("SELECT pg_get_constraintdef(oid) d FROM pg_constraint WHERE conrelid='permission_grants'::regclass AND conname='permission_grants_scope_check'")->d;if(!preg_match('/^CHECK\s*\((.*)\)$/s',$definition,$m))throw new LogicException('QA grants constraint missing');$old=$m[1];
|
|
// Official A schema, with temporary NOT VALID only to preserve this fresh fixture's procurement grants.
|
|
$migration=file_get_contents($s['app'].'/database/migrations/2026_10_25_030000_create_services_delivery_a.php');$migration=str_replace('AND unit_id IS NOT NULL))");','AND unit_id IS NOT NULL)) NOT VALID");',$migration,$replacements);if($replacements<1)throw new LogicException('Migration adaptation refused');$copy=$s['root'].'/services-qa-schema.php';file_put_contents($copy,$migration);DB::transaction(function()use($copy,$old){(require $copy)->up();$new=DB::selectOne("SELECT pg_get_constraintdef(oid) d FROM pg_constraint WHERE conrelid='permission_grants'::regclass AND conname='permission_grants_scope_check'")->d;if(!preg_match('/^CHECK\s*\((.*)\)(?: NOT VALID)?$/s',$new,$m))throw new LogicException('QA A constraint missing');DB::statement('ALTER TABLE permission_grants DROP CONSTRAINT permission_grants_scope_check');DB::statement("ALTER TABLE permission_grants ADD CONSTRAINT permission_grants_scope_check CHECK (({$m[1]}) OR ($old))");});
|
|
foreach(['actor'=>['company.edit'=>null,'unit.edit'=>$f['unit'],'clients.view'=>null,'clients.create'=>null,'clients.edit'=>null],'issuer'=>['clients.view'=>null,'company.edit'=>null]]as$role=>$rights)foreach($rights as$right=>$unit)DB::table('permission_grants')->insertOrIgnore(['tenant_id'=>$f['tenant'],'company_id'=>$f['company'],'unit_id'=>$unit,'user_id'=>$f[$role],'permission'=>$right,'created_at'=>now(),'updated_at'=>now()]);
|
|
$ctx=app(App\Shared\Context\CompanyContext::class);$ctx->selectFor($f['actor'],$f['tenant'],$f['company'],$f['unit']);auth()->setUser(App\Models\User::findOrFail($f['actor']));request()->attributes->set('sgf_module','commercial');$f['client']=app(App\Modules\Services\ServiceWorkflow::class)->save('clients',null,$f['actor'],['name'=>'Cliente cartografia QA'],(string)Illuminate\Support\Str::uuid())['id'];request()->attributes->remove('sgf_module');
|
|
$f['pending_client']=DB::table('a_clients')->insertGetId(['tenant_id'=>$f['tenant'],'company_id'=>$f['company'],'unit_id'=>null,'name'=>'Cliente sem associação de módulo QA','data'=>'{}','version'=>1,'created_at'=>now(),'updated_at'=>now()]);
|
|
DB::unprepared(<<<'SQL'
|
|
CREATE TABLE geo_versions(source_version varchar(64) PRIMARY KEY, metadata jsonb NOT NULL, created_at timestamptz NOT NULL DEFAULT now());
|
|
CREATE TABLE geo_catalogue_state(id integer PRIMARY KEY CHECK(id=1),source_version varchar(64) NOT NULL REFERENCES geo_versions);
|
|
CREATE TABLE geo_territories(territory_key varchar(100) PRIMARY KEY,source_version varchar(64) NOT NULL REFERENCES geo_versions,source_id varchar(30) NOT NULL,level smallint NOT NULL CHECK(level BETWEEN 1 AND 6),designation text,parent_key varchar(100),province varchar(20) NOT NULL,district varchar(20) NOT NULL,administrative_post varchar(20) NOT NULL,locality varchar(20) NOT NULL,urban_neighbourhood varchar(20) NOT NULL,village_quarter varchar(20) NOT NULL,issues jsonb NOT NULL,selectable boolean NOT NULL,UNIQUE(source_version,source_id));
|
|
CREATE INDEX geo_territory_parent ON geo_territories(source_version,parent_key,level,designation,source_id);
|
|
CREATE TABLE geo_locations(tenant_id bigint NOT NULL,company_id bigint NOT NULL,unit_key bigint NOT NULL,module_key varchar(30) NOT NULL,kind varchar(20) NOT NULL,entity_id bigint NOT NULL,provider varchar(64) NOT NULL,revision integer NOT NULL CHECK(revision>0),selection jsonb,actor_id bigint NOT NULL REFERENCES users,reason text NOT NULL,updated_at timestamptz NOT NULL,PRIMARY KEY(tenant_id,company_id,unit_key,module_key,kind,entity_id,provider));
|
|
CREATE TABLE geo_location_history(id bigserial PRIMARY KEY,tenant_id bigint NOT NULL,company_id bigint NOT NULL,unit_key bigint NOT NULL,module_key varchar(30) NOT NULL,kind varchar(20) NOT NULL,entity_id bigint NOT NULL,provider varchar(64) NOT NULL,actor_id bigint NOT NULL REFERENCES users,reason text NOT NULL,"before" jsonb NOT NULL,"after" jsonb NOT NULL,created_at timestamptz NOT NULL);
|
|
CREATE INDEX geo_history_scope ON geo_location_history(tenant_id,company_id,unit_key,module_key,kind,entity_id,provider,id);
|
|
CREATE TABLE geo_commands(tenant_id bigint NOT NULL,company_id bigint NOT NULL,actor_id bigint NOT NULL REFERENCES users,operation_key uuid NOT NULL,request_hash varchar(64) NOT NULL,result jsonb NOT NULL,created_at timestamptz NOT NULL,PRIMARY KEY(tenant_id,company_id,actor_id,operation_key));
|
|
SQL);
|
|
DB::transaction(function()use($c){DB::table('geo_versions')->insert(['source_version'=>$c['source']['sha256'],'metadata'=>json_encode($c['source']+['diagnostics'=>$c['diagnostics']],JSON_THROW_ON_ERROR)]);foreach(array_chunk($c['nodes'],300)as$chunk){$rows=[];foreach($chunk as$n)$rows[]=['territory_key'=>$n['key'],'source_version'=>$c['source']['sha256'],'source_id'=>$n['source_id'],'level'=>$n['level'],'designation'=>$n['designation'],'parent_key'=>count($n['parent_candidates'])===1?$n['parent_candidates'][0]:null,'issues'=>json_encode($n['issues'],JSON_THROW_ON_ERROR),'selectable'=>$n['selectable']]+$n['codes'];DB::table('geo_territories')->insert($rows);}DB::table('geo_catalogue_state')->insert(['id'=>1,'source_version'=>$c['source']['sha256']]);});
|
|
foreach(['geo_versions','geo_territories','geo_location_history','geo_commands']as$table)DB::statement("CREATE TRIGGER {$table}_immutable BEFORE UPDATE OR DELETE ON $table FOR EACH ROW EXECUTE FUNCTION sgf_append_only_audit()");
|
|
$ctx->clear();file_put_contents($s['root'].'/fixture.json',json_encode($f,JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR));file_put_contents($s['root'].'/geography-baseline.json',json_encode(['passed'=>true,'catalogue_rows'=>DB::table('geo_territories')->count(),'location_assignments'=>0,'source_version'=>$c['source']['sha256'],'synthetic_client'=>$f['client'],'pending_client_unchanged'=>true,'public_rights_changed'=>false],JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR));
|