connection(); $shopAccounts = $connection->table('fin_shops') ->whereNotNull('account_short') ->where('account_short', '<>', '') ->where('account_short', '<>', '/') ->pluck('account_short', 'shop_name'); $masterAccounts = array_fill_keys( $connection->table('fin_accounts')->distinct()->pluck('account_short')->all(), true, ); $rows = $connection->table('fin_account_map') ->where('source', 'shop') ->where(function ($query): void { $query->whereNull('account_short')->orWhere('account_short', ''); }) ->orderBy('source_value') ->get(['id', 'source_value']); $candidates = []; $unmatched = []; foreach ($rows as $row) { $sourceValue = trim((string) $row->source_value); $accountShort = trim((string) ($shopAccounts[$sourceValue] ?? '')); if ($accountShort === '' || ! isset($masterAccounts[$accountShort])) { $unmatched[] = $sourceValue; continue; } $candidates[] = [ 'id' => (int) $row->id, 'source_value' => $sourceValue, 'account_short' => $accountShort, ]; } return [ 'total' => $rows->count(), 'matched' => count($candidates), 'unmatched' => count($unmatched), 'candidates' => $candidates, 'unmatched_values' => $unmatched, ]; } public function apply(?User $user = null): array { $preview = $this->preview(); $connection = $this->connection(); $userName = (string) ($user?->name ?? ''); $userId = (int) ($user?->id ?? 0); $now = now(); $mapped = 0; if ($preview['candidates'] !== []) { $connection->transaction(function () use ($connection, $preview, $userName, $userId, $now, &$mapped): void { foreach ($preview['candidates'] as $candidate) { $updated = $connection->table('fin_account_map') ->where('id', $candidate['id']) ->where(function ($query): void { $query->whereNull('account_short')->orWhere('account_short', ''); }) ->update([ 'account_short' => $candidate['account_short'], 'updated_by' => $userName, 'updated_at' => $now, ]); if ($updated !== 1) { continue; } $connection->table('fin_account_map_events')->insert([ 'source' => 'shop', 'source_value' => $candidate['source_value'], 'old_account_short' => null, 'new_account_short' => $candidate['account_short'], 'user_id' => $userId, 'user_name' => $userName, 'created_at' => $now, ]); $mapped++; } }); } if ($mapped > 0) { app(FinanceLedgerCalculator::class)->recalculate(); } return [ 'total' => $preview['total'], 'mapped' => $mapped, 'unmatched' => $preview['unmatched'], ]; } private function connection() { return DB::connection((string) config('upstream_mirrors.connection', 'business_mirror')); } }