} */ public function sync(?int $companyId = null): array { $companyId ??= (int) (company_id() ?: 1); $created = 0; $updated = 0; $skipped = 0; $byPlatform = []; // Load the local directory once; avoid one SQL lookup per upstream // shop every time a tab is opened. $existing = StoreReceivingAccount::withoutGlobalScopes() ->withTrashed() ->where('company_id', $companyId) ->get(); $byWallet = []; $byPlatformAndName = []; $byName = []; $sourceStores = $this->mirror->receivingAccountStores(); // 店铺主体跟随店铺维度报表的“存续中”期间,不再直接取店铺档案当前主体。 $currentCompanies = $this->storeReportPeriods->currentCompanies(array_map( static fn (array $row): array => [ 'erp_store_name' => trim((string) ($row['erp_store_name'] ?? '')), 'system_company_name' => trim((string) ($row['company_name'] ?? '')), ], $sourceStores, )); foreach ($existing as $account) { $platform = (string) $account->store_platform; $wallet = trim((string) $account->wallet_number); $name = trim((string) $account->store_name); if ($wallet !== '') { $byWallet[$platform . "\0" . $wallet] ??= $account; } if ($name !== '') { $byPlatformAndName[$platform . "\0" . $name] ??= $account; $byName[$name] ??= $account; } } foreach ($sourceStores as $row) { $erpStoreName = trim((string) ($row['erp_store_name'] ?? '')); $platform = $this->classify($erpStoreName, (string) ($row['source_platform'] ?? '')); if ($erpStoreName === '' || $platform === null) { $skipped++; continue; } $storeId = trim((string) ($row['store_id'] ?? $row['id'] ?? '')); $account = $storeId !== '' ? ($byWallet[$platform . "\0" . $storeId] ?? null) : null; // Older rows created before wallet_number was populated may have // been classified by the upstream platform. Reuse them by ERP // name so a corrected prefix classification does not duplicate a // store row. $account ??= $byPlatformAndName[$platform . "\0" . $erpStoreName] ?? $byName[$erpStoreName] ?? null; $attributes = [ 'company_id' => $companyId, 'store_platform' => $platform, 'store_name' => $erpStoreName, 'store_entity_name' => $currentCompanies[$erpStoreName] ?? trim((string) ($row['company_name'] ?? '')), 'shop_name' => trim((string) ($row['shop_name'] ?? '')) ?: $erpStoreName, 'store_status' => $this->status($row['store_status'] ?? null), 'wallet_number' => $storeId, 'store_id' => $storeId, 'source_platform' => trim((string) ($row['source_platform'] ?? '')), ]; if ($account === null) { $account = new StoreReceivingAccount(); $account->fill($attributes); $account->save(); $created++; if ($storeId !== '') { $byWallet[$platform . "\0" . $storeId] = $account; } $byPlatformAndName[$platform . "\0" . $erpStoreName] = $account; $byName[$erpStoreName] ??= $account; } else { if ($account->trashed()) { $account->restore(); } $account->fill($attributes); if ($account->isDirty()) { $account->save(); $updated++; } if ($storeId !== '') { $byWallet[$platform . "\0" . $storeId] = $account; } $byPlatformAndName[$platform . "\0" . $erpStoreName] = $account; $byName[$erpStoreName] ??= $account; } $byPlatform[$platform] = ($byPlatform[$platform] ?? 0) + 1; } return compact('created', 'updated', 'skipped', 'byPlatform'); } public function classify(string $erpStoreName, string $sourcePlatform = ''): ?string { $prefix = preg_split('/[-—_-|丨\/\\()()【】\[\]·::]+/u', trim($erpStoreName), 2)[0] ?? ''; $prefix = trim((string) $prefix); $sourcePlatform = trim($sourcePlatform); $platforms = ['淘宝分销', '阿里巴巴', '天猫', '唯品会', '淘宝', '京喜', '京东', '抖音', '拼多多']; foreach ($platforms as $platform) { if (str_starts_with($prefix, $platform)) { return $platform; } } foreach ($platforms as $platform) { if (str_starts_with($sourcePlatform, $platform)) { return $platform; } } return null; } private function status(mixed $value): ?string { return match ((string) $value) { '0', '正常' => '正常', '3', '关闭中', '关店中' => '关店中', '6', '已关闭', '已关店' => '已关店', default => trim((string) $value) ?: null, }; } }