业绩明细:实收缺失时退回按应付/已付核对;同步命令新增 --dry-run 开关
This commit is contained in:
parent
c314209705
commit
72b3f43da5
@ -36,7 +36,8 @@ class SyncStoreReceiptOrderMatches extends Command
|
||||
{--chunk=1200 : 单次向上游查询的订单号数量}
|
||||
{--limit=0 : 仅处理前 N 笔账单(调试用,0 表示全量)}
|
||||
{--amounts-only : 只回填「优惠金额 / 冲减金额 / 种菜金额」三列,不重跑订单侧匹配}
|
||||
{--planting-only : 只回填「种菜金额」一列(不读账单,直接按该月已有明细行的订单号刷,一次覆盖全平台)}';
|
||||
{--planting-only : 只回填「种菜金额」一列(不读账单,直接按该月已有明细行的订单号刷,一次覆盖全平台)}
|
||||
{--dry-run : 只计算并打印统计,不写库(用于评估口径调整的影响)}';
|
||||
|
||||
protected $description = '按店铺收款账户账单匹配订单侧商品金额,生成「业绩明细」核对镜像';
|
||||
|
||||
@ -176,6 +177,9 @@ class SyncStoreReceiptOrderMatches extends Command
|
||||
/** 双口径兜底命中「卖家实收」时写入的标识(页面「未匹配原因」列展示)。 */
|
||||
private const REMARK_SELLER_INCOME_BASIS = '订单实付按卖家实收核对';
|
||||
|
||||
/** 实收缺失时退回「应付/已付」核对命中的标识。 */
|
||||
private const REMARK_PAYABLE_BASIS = '订单实付按应付/已付核对';
|
||||
|
||||
public function handle(): int
|
||||
{
|
||||
// 全量重建时账单与订单侧映射都在内存里:拼多多 / 淘系支付宝这类大平台需要 1G 以上,
|
||||
@ -594,9 +598,13 @@ class SyncStoreReceiptOrderMatches extends Command
|
||||
MAX(CASE WHEN link_o_id IS NULL OR link_o_id = 0 THEN paid_alt END),
|
||||
MAX(paid_alt)
|
||||
) as paid_alt
|
||||
, COALESCE(
|
||||
MAX(CASE WHEN link_o_id IS NULL OR link_o_id = 0 THEN paid_pay END),
|
||||
MAX(paid_pay)
|
||||
) as paid_pay
|
||||
FROM (
|
||||
SELECT o.so_id as so_id, o.shop_name as shop_name, o.link_o_id as link_o_id,
|
||||
o.{$paidColumn} as paid, o.{$paidAltColumn} as paid_alt
|
||||
o.{$paidColumn} as paid, o.{$paidAltColumn} as paid_alt, o.pay_amount as paid_pay
|
||||
FROM tmp_receipt_order_nos t
|
||||
STRAIGHT_JOIN {$ordersTable} o ON o.so_id = t.no
|
||||
) x
|
||||
@ -620,6 +628,8 @@ class SyncStoreReceiptOrderMatches extends Command
|
||||
$orderPaid = [];
|
||||
/** @var array<string,float> $orderPaidAlt 订单侧「卖家实收」金额(双口径兜底用) */
|
||||
$orderPaidAlt = [];
|
||||
/** @var array<string,float> $orderPaidPay 订单侧「应付」金额(实收缺失时的退化口径) */
|
||||
$orderPaidPay = [];
|
||||
foreach ($paidRows as $row) {
|
||||
$core = self::cleanOrderNo((string) $row['so_id']);
|
||||
if ($core === '') {
|
||||
@ -629,6 +639,7 @@ class SyncStoreReceiptOrderMatches extends Command
|
||||
$key = $shopKey . '|' . $core;
|
||||
$orderPaid[$key] = ($orderPaid[$key] ?? 0.0) + (float) $row['paid'];
|
||||
$orderPaidAlt[$key] = ($orderPaidAlt[$key] ?? 0.0) + (float) ($row['paid_alt'] ?? 0.0);
|
||||
$orderPaidPay[$key] = ($orderPaidPay[$key] ?? 0.0) + (float) ($row['paid_pay'] ?? 0.0);
|
||||
// 订单实付命中同样算「订单侧存在」:部分订单(退款流程 / 拆单 / 商品明细未同步)没有商品明细行,
|
||||
// 若只按商品明细判断存在性,这些单会被误判「订单表无此单」(实付明明在)。
|
||||
// 商品金额数组仍只由商品明细构建:无明细时商品金额保持为空、按口径标「订单无商品金额」。
|
||||
@ -658,10 +669,13 @@ class SyncStoreReceiptOrderMatches extends Command
|
||||
}
|
||||
|
||||
// 只重建「本账期 + 本平台」的数据,避免把同月其它平台的结果一起清掉。
|
||||
DB::connection($connection)->table(self::TARGET_TABLE)
|
||||
->where('report_month', $reportMonth)
|
||||
->where('platform', (string) $source['label'])
|
||||
->delete();
|
||||
$dryRun = (bool) $this->option('dry-run');
|
||||
if (! $dryRun) {
|
||||
DB::connection($connection)->table(self::TARGET_TABLE)
|
||||
->where('report_month', $reportMonth)
|
||||
->where('platform', (string) $source['label'])
|
||||
->delete();
|
||||
}
|
||||
|
||||
$target = DB::connection($connection)->table(self::TARGET_TABLE);
|
||||
$now = now();
|
||||
@ -740,12 +754,36 @@ class SyncStoreReceiptOrderMatches extends Command
|
||||
$coresByCore,
|
||||
self::REMARK_NO_PAID,
|
||||
);
|
||||
if ($altStatus === self::STATUS_MATCHED && $altAmount !== null
|
||||
&& abs($income + $promoAmount - (float) $altAmount) <= 0.02) {
|
||||
$altMatched = $altStatus === self::STATUS_MATCHED && $altAmount !== null;
|
||||
$altValue = $altMatched ? (float) $altAmount : 0.0;
|
||||
// 实收有值且能对上 → 按实收核对;实收缺失(0/空)时退回「应付/已付」核对(拆单主单实收常为空)。
|
||||
$payAmount = null;
|
||||
if (! ($altMatched && $altValue > 0.005)) {
|
||||
[$payStatus, $payValue] = $this->matchOrderSide(
|
||||
$core,
|
||||
(string) $group['shop_key'],
|
||||
$orderPaidPay,
|
||||
$orderSeen,
|
||||
$coreSeen,
|
||||
$coresByCore,
|
||||
self::REMARK_NO_PAID,
|
||||
);
|
||||
if ($payStatus === self::STATUS_MATCHED && $payValue !== null) {
|
||||
$payAmount = (float) $payValue;
|
||||
}
|
||||
}
|
||||
|
||||
if ($altMatched && $altValue > 0.005
|
||||
&& abs($income + $promoAmount - $altValue) <= 0.02) {
|
||||
$paidAmount = round((float) $altAmount, 2);
|
||||
$basisAmount = $paidAmount;
|
||||
$difference = 0.0;
|
||||
$remark = self::REMARK_SELLER_INCOME_BASIS;
|
||||
} elseif ($payAmount !== null && abs($income + $promoAmount - $payAmount) <= 0.02) {
|
||||
$paidAmount = round($payAmount, 2);
|
||||
$basisAmount = $paidAmount;
|
||||
$difference = 0.0;
|
||||
$remark = self::REMARK_PAYABLE_BASIS;
|
||||
}
|
||||
}
|
||||
if ($productAmount !== null) {
|
||||
@ -789,7 +827,9 @@ class SyncStoreReceiptOrderMatches extends Command
|
||||
];
|
||||
|
||||
if (count($buffer) >= 500) {
|
||||
$target->insertOrIgnore($buffer);
|
||||
if (! $dryRun) {
|
||||
$target->insertOrIgnore($buffer);
|
||||
}
|
||||
$imported += count($buffer);
|
||||
$buffer = [];
|
||||
}
|
||||
@ -799,14 +839,18 @@ class SyncStoreReceiptOrderMatches extends Command
|
||||
foreach ($promoOnlyGroups as $promoGroup) {
|
||||
$buffer[] = self::promoOnlyRow($reportMonth, (string) $source['label'], $promoGroup, $now);
|
||||
if (count($buffer) >= 500) {
|
||||
$target->insertOrIgnore($buffer);
|
||||
if (! $dryRun) {
|
||||
$target->insertOrIgnore($buffer);
|
||||
}
|
||||
$imported += count($buffer);
|
||||
$buffer = [];
|
||||
}
|
||||
}
|
||||
|
||||
if ($buffer !== []) {
|
||||
$target->insertOrIgnore($buffer);
|
||||
if (! $dryRun) {
|
||||
$target->insertOrIgnore($buffer);
|
||||
}
|
||||
$imported += count($buffer);
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user