CaiWuXiTong/app/Business/StoreReceiptPlatformSkuMapper.php
chenxi e15b6b9901 商品成本:按历史唯一规格映射平台数字SKU (#482)
平台数字 SKU 仅按唯一历史内部编码自动映射;多候选保持待核验。
2026-10-24 10:18:21 +08:00

85 lines
2.9 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;
/**
* 平台数字 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);
}
}