CaiWuXiTong/app/Business/StoreReceivingAccountSynchronizer.php

151 lines
5.4 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Business;
use App\Models\Business\StoreReceivingAccount;
use Modules\EcommerceFinance\Repositories\BusinessInformationMirrorRepository;
class StoreReceivingAccountSynchronizer
{
public function __construct(
private readonly BusinessInformationMirrorRepository $mirror,
) {
}
/**
* Seed account rows from the read-only store-information mirror while
* preserving any credentials already entered by the user.
*
* @return array{created:int,updated:int,skipped:int,by_platform:array<string,int>}
*/
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 = [];
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 ($this->mirror->receivingAccountStores() 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' => 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,
};
}
}