attributes->get('sgf_module'); } public static function query(string $table) { $query=DB::table($table); $module=self::active(); if (!$module) return $query; // CLI domain proofs have no HTTP module selection. if (str_starts_with($table,'a_') && in_array(substr($table,2),self::AREAS,true)) { self::constrain($query,$table,substr($table,2),$module); } elseif ($table==='si_invoices') { $query->whereIn('draft_id',self::query('a_billing_drafts')->select('id')); } return $query; } public static function constrain($query,string $table,string $area,string $module): void { $query->whereExists(function($q)use($table,$area,$module){ $q->selectRaw('1')->from('identity_audit as ma')->where('ma.action','module.record.associated') ->whereColumn('ma.tenant_id',$table.'.tenant_id')->whereColumn('ma.company_id',$table.'.company_id') ->whereRaw("ma.details::jsonb->>'area' = ?",[$area]) ->whereRaw("ma.details::jsonb->>'record_id' = {$table}.id::text") ->whereRaw("ma.details::jsonb->>'module_id' = ?",[$module]) ->whereNotExists(function($revoked){ $revoked->selectRaw('1')->from('identity_audit as mr')->where('mr.action','module.record.disassociated') ->whereColumn('mr.tenant_id','ma.tenant_id')->whereColumn('mr.company_id','ma.company_id')->whereColumn('mr.id','>','ma.id') ->whereRaw("mr.details::jsonb->>'area' = ma.details::jsonb->>'area'") ->whereRaw("mr.details::jsonb->>'record_id' = ma.details::jsonb->>'record_id'") ->whereRaw("mr.details::jsonb->>'module_id' = ma.details::jsonb->>'module_id'"); }); }); } public static function associate(string $area,int $id,int $actor,array $scope,string $module,string $reason,bool $remove=false,?int $version=null): void { Audit::record($remove?'module.record.disassociated':'module.record.associated',$actor,$scope['tenant_id'],$scope['company_id'],$scope['unit_id']??null, details:['area'=>$area,'record_id'=>$id,'module_id'=>$module,'reason'=>$reason,'version'=>$version]); } }