where('is_active', true) ->get(['id', 'meta']); foreach ($entities as $entity) { $locationId = (int) data_get($entity->meta, 'business_location_id', 0); if ($locationId > 0) { $map[$locationId] = (int) $entity->id; } } return $map; } public function resolveFromLocation(int $businessId, ?int $locationId): ?int { if (! $locationId) { return null; } return $this->locationEntityMap($businessId)[$locationId] ?? null; } public function assessTagging(int $businessId): array { $entityCount = HoldingEntity::where('business_id', $businessId)->where('is_active', true)->count(); if ($entityCount === 0 || ! Schema::hasColumn('accounting_accounts_transactions', 'holding_entity_id')) { return [ 'entities' => $entityCount, 'total_lines' => 0, 'untagged_lines' => 0, 'tagged_pct' => 100, 'ready' => true, ]; } $total = (int) DB::table('accounting_accounts_transactions as aat') ->join('accounting_accounts as aa', 'aa.id', '=', 'aat.accounting_account_id') ->where('aa.business_id', $businessId) ->count(); $untagged = (int) DB::table('accounting_accounts_transactions as aat') ->join('accounting_accounts as aa', 'aa.id', '=', 'aat.accounting_account_id') ->where('aa.business_id', $businessId) ->whereNull('aat.holding_entity_id') ->count(); $taggedPct = $total > 0 ? round((($total - $untagged) / $total) * 100, 1) : 100; return [ 'entities' => $entityCount, 'total_lines' => $total, 'untagged_lines' => $untagged, 'tagged_pct' => $taggedPct, 'ready' => $untagged === 0 || $taggedPct >= 80, ]; } public function backfillUntagged(int $businessId): int { if (! Schema::hasColumn('accounting_accounts_transactions', 'holding_entity_id') || ! Schema::hasTable('transactions')) { return 0; } $locationMap = $this->locationEntityMap($businessId); if (empty($locationMap)) { return 0; } $updated = 0; foreach ($locationMap as $locationId => $entityId) { $updated += DB::table('accounting_accounts_transactions as aat') ->join('transactions as t', 't.id', '=', 'aat.transaction_id') ->join('accounting_accounts as aa', 'aa.id', '=', 'aat.accounting_account_id') ->where('aa.business_id', $businessId) ->whereNull('aat.holding_entity_id') ->where('t.location_id', $locationId) ->whereNotNull('aat.transaction_id') ->update(['aat.holding_entity_id' => $entityId]); } return $updated; } public function applyEntityScope($query, int $businessId, HoldingEntity $entity): void { if (! Schema::hasColumn('accounting_accounts_transactions', 'holding_entity_id')) { return; } $locationId = (int) data_get($entity->meta, 'business_location_id', 0); $query->where(function ($scoped) use ($entity, $locationId) { $scoped->where('aat.holding_entity_id', $entity->id); if ($locationId > 0 && Schema::hasTable('transactions')) { $scoped->orWhere(function ($fallback) use ($locationId) { $fallback->whereNull('aat.holding_entity_id') ->whereNotNull('aat.transaction_id') ->whereIn('aat.transaction_id', function ($sub) use ($locationId) { $sub->select('id') ->from('transactions') ->where('location_id', $locationId); }); }); } }); } }