商品成本:拆单订单有子单时只取子单,避免主单与子单重复计
聚水潭拆单后主单保留原始下单行、子单才是实际发货行;之前按「商品+数量+金额+仓库」去重, 主单 10 件与子单各 1 件键不同,会重复累加。改为:有子单时只取子单(按 o_id+oi_id 去重), 整单没有子单才用主单;再按「发货仓库 + 商品编码」汇总数量。 回归样例 5122123095012119232:31202C 计 10 件(10 个子单各 1 件)、DNZ032916N887V01 计 10 件。
This commit is contained in:
parent
c44d267902
commit
e0abc6732b
@ -166,7 +166,7 @@ class SyncStoreReceiptProductCost extends Command
|
||||
}
|
||||
$this->info('订单侧候选单号:' . count($candidates));
|
||||
|
||||
/** @var array<string,list<array{sku:string,qty:float,amount:float,warehouse:string}>> $lines */
|
||||
/** @var array<string,list<array{sku:string,qty:float,amount:float,warehouse:string,is_main:bool,row_key:string}>> $lines */
|
||||
$lines = [];
|
||||
foreach (self::SOURCES as $source) {
|
||||
try {
|
||||
@ -174,6 +174,8 @@ class SyncStoreReceiptProductCost extends Command
|
||||
"SELECT o.so_id as so_id, "
|
||||
. $source['warehouse'] . " as warehouse_code, "
|
||||
. " COALESCE(wh.name, '') as warehouse_name, "
|
||||
. " CASE WHEN o.link_o_id IS NULL OR o.link_o_id = 0 THEN 1 ELSE 0 END as is_main, "
|
||||
. " CONCAT(o.o_id, '-', i.oi_id) as row_key, "
|
||||
. " i.sku_id as sku_id, i.qty as qty, i.amount as amount
|
||||
FROM tmp_cost_order_nos t
|
||||
STRAIGHT_JOIN {$source['orders']} o ON o.so_id = t.no
|
||||
@ -221,6 +223,9 @@ class SyncStoreReceiptProductCost extends Command
|
||||
// 组合装明细金额对应整包,拆到组件后不再参与「数量×单价 vs 明细金额」校验。
|
||||
'amount' => $isComponent ? 0.0 : $amount,
|
||||
'warehouse' => $warehouse,
|
||||
// 拆单后子单(link_o_id 非空)才是实际发货行;主单只是原始下单记录。
|
||||
'is_main' => (int) $row->is_main === 1,
|
||||
'row_key' => (string) $row->row_key,
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -348,11 +353,15 @@ class SyncStoreReceiptProductCost extends Command
|
||||
}
|
||||
|
||||
/**
|
||||
* 拆单去重:聚水潭的拆单子单会把主单的商品行再列一遍,同一批商品只算一次;
|
||||
* 同一商品在同一订单里既有真实发货仓库行、又有无仓库的占位行时,丢掉占位行,
|
||||
* 这样「同一单分多仓发货」会按子单的实际仓库分行。
|
||||
* 拆单取数:聚水潭拆单后,主单(link_o_id 为空)保留的是原始下单行,
|
||||
* 子单(link_o_id 指向主单)才是实际发货行。一个订单只要出现子单,就只取子单,
|
||||
* 否则主单和子单会被各算一遍(主单的原始商品 + 子单的实际发货商品)。
|
||||
* 没有子单的订单才用主单行。
|
||||
*
|
||||
* @param list<array{sku:string,qty:float,amount:float,warehouse:string}> $rows
|
||||
* 同一订单的多条子单(不同仓库 / 分批发货)按「发货仓库 + 商品编码」汇总,数量相加,
|
||||
* 这样「一个订单有几个发货仓库、商品编码、数量」会分开列。
|
||||
*
|
||||
* @param list<array{sku:string,qty:float,amount:float,warehouse:string,is_main:bool,row_key:string}> $rows
|
||||
* @return list<array{sku:string,qty:float,amount:float,warehouse:string}>
|
||||
*/
|
||||
private function costLines(array $rows): array
|
||||
@ -361,25 +370,23 @@ class SyncStoreReceiptProductCost extends Command
|
||||
return [];
|
||||
}
|
||||
|
||||
// 1) 完全相同的行(商品 + 数量 + 金额 + 仓库)只保留一条。
|
||||
// 1) 先按订单明细主键去掉上游的完全重复行(同一 o_id + oi_id 只算一次)。
|
||||
$unique = [];
|
||||
foreach ($rows as $row) {
|
||||
$key = $row['sku'] . "\0" . $row['qty'] . "\0" . $row['amount'] . "\0" . $row['warehouse'];
|
||||
$key = $row['row_key'] . "\0" . $row['sku'];
|
||||
$unique[$key] = $row;
|
||||
}
|
||||
|
||||
// 2) 有真实仓库的同一(商品 + 数量 + 金额),优先于无仓库的占位行。
|
||||
$withWarehouse = [];
|
||||
// 2) 有子单就只取子单(实际发货行);整单没有子单才用主单行。
|
||||
$hasSubOrder = false;
|
||||
foreach ($unique as $row) {
|
||||
if ($row['warehouse'] !== '') {
|
||||
$withWarehouse[$row['sku'] . "\0" . $row['qty'] . "\0" . $row['amount']] = true;
|
||||
if (! $row['is_main']) {
|
||||
$hasSubOrder = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
foreach ($unique as $key => $row) {
|
||||
if ($row['warehouse'] === ''
|
||||
&& isset($withWarehouse[$row['sku'] . "\0" . $row['qty'] . "\0" . $row['amount']])) {
|
||||
unset($unique[$key]);
|
||||
}
|
||||
if ($hasSubOrder) {
|
||||
$unique = array_filter($unique, static fn (array $row): bool => ! $row['is_main']);
|
||||
}
|
||||
|
||||
// 3) 汇总到「发货仓库 + 商品编码」。
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user