transaction(function()use($native,$input,$scope){ $meta=['created_by'=>4,'reason'=>'Recorte QA de lotes aprovado expressamente em10/11/2026.','created_at'=>now()]; $book=$native->table('gl_stock_books')->where($scope)->where(['stock_item_id'=>$input['stock_item'],'warehouse_id'=>$input['warehouse']])->first(); if(!$book)$native->table('gl_stock_books')->insert($scope+$meta+['stock_item_id'=>$input['stock_item'],'warehouse_id'=>$input['warehouse'],'unit_code'=>'UN','period_key'=>'QA-2026-INTEGRADO']); $expense=$native->table('gl_accounts')->where($scope)->where('code','QA-DIFERENCA-INVENTARIO')->value('id');if(!$expense)$expense=$native->table('gl_accounts')->insertGetId($scope+['code'=>'QA-DIFERENCA-INVENTARIO','label'=>'Diferença de inventário exclusivamente QA','currency'=>'MZN','is_movement'=>true]); if(!$native->table('gl_rules')->where($scope)->where('rule_key','stock.adjustment')->exists())$native->table('gl_rules')->insert($scope+$meta+['rule_key'=>'stock.adjustment','effect_type'=>'stock.adjustment','version'=>1,'policy'=>'QA-STOCK-VALUATION-v1','currency'=>'MZN','valid_from'=>'2026-01-01','valid_to'=>'2026-12-31','debit_account_id'=>$expense,'credit_account_id'=>$native->table('gl_accounts')->where($scope)->where('code','QA-STOCK')->value('id')]); $definition=$native->selectOne("SELECT pg_get_functiondef('gl_stock_journal_assert()'::regprocedure) body")->body; if(!str_contains($definition,"WHEN 'stock.adjustment'")){ $pairs=["WHEN 'stock.return' THEN ARRAY['QA-STOCK','QA-CONSUMO-STOCK']"=>"WHEN 'stock.return' THEN ARRAY['QA-STOCK','QA-CONSUMO-STOCK'] WHEN 'stock.adjustment' THEN ARRAY['QA-DIFERENCA-INVENTARIO','QA-STOCK']", "WHEN 'stock.return' THEN 'workshop_return_in'"=>"WHEN 'stock.return' THEN 'workshop_return_in' WHEN 'stock.adjustment' THEN 'adjustment_out'"]; foreach($pairs as $from=>$to){if(substr_count($definition,$from)!==1)throw new LogicException('Preserve unfamiliar stock journal guard');$definition=str_replace($from,$to,$definition);}$native->unprepared($definition); } $native->statement("CREATE UNIQUE INDEX IF NOT EXISTS gl_stock_movement_once_final ON gl_journals(tenant_id,(snapshot->'source'->>'stock_movement_id')) WHERE snapshot->'source'->>'effect_type' IN('stock.receipt','stock.issue','stock.return','stock.adjustment')"); }); $path=$s['root'].'/single-material-perimeter.json';$p=json_decode(file_get_contents($path),true);copy($path,$work.'/material-perimeter-before.json'); $p['valued_stock']=$native->table('gl_stock_books')->where($scope)->orderBy('id')->get(['stock_item_id','warehouse_id'])->map(fn($r)=>(array)$r)->all();$p['extension_reason']='Novo artigo de lotes aprovado individualmente, distinto de materiais directos e industriais.';file_put_contents($path,json_encode($p,JSON_PRETTY_PRINT)); echo json_encode(['passed'=>true,'book'=>$book,'new_qa_account'=>'QA-DIFERENCA-INVENTARIO','new_qa_rule'=>'stock.adjustment','journal_count'=>$native->table('gl_journals')->count(),'existing_journals_not_rewritten'=>true]).PHP_EOL;