85 lines
2.9 KiB
PHP
85 lines
2.9 KiB
PHP
<?php
|
||
|
||
namespace App\Business;
|
||
|
||
/**
|
||
* 平台数字 SKU → 历史已拆分内部商品编码。
|
||
*
|
||
* 平台 shop_sku_id 已包含平台规格维度;仅当同一 shop_sku_id + shop_i_id
|
||
* 的历史内部编码唯一时才允许替换,多候选保持待核验。
|
||
*/
|
||
class StoreReceiptPlatformSkuMapper
|
||
{
|
||
/** @var array<string,array<string,int>> */
|
||
private array $internalSkus = [];
|
||
|
||
/** @var array<string,array<string,int>> */
|
||
private array $internalProperties = [];
|
||
|
||
/** @var array<string,int> */
|
||
private array $historyRows = [];
|
||
|
||
/** @param iterable<object|array<string,mixed>> $historyRows */
|
||
public function __construct(iterable $historyRows)
|
||
{
|
||
foreach ($historyRows as $row) {
|
||
$shopSkuId = trim((string) $this->value($row, 'shop_sku_id'));
|
||
$shopItemId = trim((string) $this->value($row, 'shop_i_id'));
|
||
$skuId = trim((string) $this->value($row, 'sku_id'));
|
||
$itemId = trim((string) $this->value($row, 'i_id'));
|
||
if ($shopSkuId === '' || $shopItemId === '' || $skuId === '') {
|
||
continue;
|
||
}
|
||
|
||
// 平台原始行的 i_id 等于 shop_i_id;内部拆分行的 i_id 是内部款式编码。
|
||
if ($itemId === '' || $itemId === $shopItemId) {
|
||
continue;
|
||
}
|
||
|
||
$key = $this->key($shopSkuId, $shopItemId);
|
||
$this->internalSkus[$key][$skuId] = ($this->internalSkus[$key][$skuId] ?? 0) + 1;
|
||
$property = trim((string) $this->value($row, 'properties_value'));
|
||
if ($property !== '') {
|
||
$this->internalProperties[$key][$property] = ($this->internalProperties[$key][$property] ?? 0) + 1;
|
||
}
|
||
$this->historyRows[$key] = ($this->historyRows[$key] ?? 0) + 1;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @return array{
|
||
* status:string,
|
||
* internal_sku:?string,
|
||
* candidates:list<string>,
|
||
* history_rows:int,
|
||
* internal_properties:list<string>
|
||
* }
|
||
*/
|
||
public function resolve(string $shopSkuId, string $shopItemId): array
|
||
{
|
||
$key = $this->key(trim($shopSkuId), trim($shopItemId));
|
||
$skus = array_keys($this->internalSkus[$key] ?? []);
|
||
sort($skus);
|
||
$properties = array_keys($this->internalProperties[$key] ?? []);
|
||
sort($properties);
|
||
|
||
return [
|
||
'status' => count($skus) === 1 ? 'unique' : ($skus === [] ? 'missing' : 'ambiguous'),
|
||
'internal_sku' => count($skus) === 1 ? $skus[0] : null,
|
||
'candidates' => $skus,
|
||
'history_rows' => (int) ($this->historyRows[$key] ?? 0),
|
||
'internal_properties' => $properties,
|
||
];
|
||
}
|
||
|
||
private function key(string $shopSkuId, string $shopItemId): string
|
||
{
|
||
return $shopSkuId . "\0" . $shopItemId;
|
||
}
|
||
|
||
private function value(object|array $row, string $key): mixed
|
||
{
|
||
return is_array($row) ? ($row[$key] ?? null) : ($row->{$key} ?? null);
|
||
}
|
||
}
|