diff --git a/app/Console/Commands/SyncStoreReceiptOrderMatches.php b/app/Console/Commands/SyncStoreReceiptOrderMatches.php index a8648cfe..fc8855bd 100644 --- a/app/Console/Commands/SyncStoreReceiptOrderMatches.php +++ b/app/Console/Commands/SyncStoreReceiptOrderMatches.php @@ -745,6 +745,9 @@ class SyncStoreReceiptOrderMatches extends Command // 差额归零、订单实付列显示实收金额。用于京东这类「账单收款=卖家实收」的平台, // 避免把口径差当成对不上的差额。 if ($basis === 'paid' && $difference !== null && abs($difference) > 0.005) { + // 原因优先:这里只登记「口径能对上」的标识,不动差额(差额与原因由页面按 + // 「先备注规则、后口径兜底」的顺序判定),避免把有明确原因的行悄悄抹平。 + { [$altStatus, $altAmount] = $this->matchOrderSide( $core, (string) $group['shop_key'], @@ -777,16 +780,11 @@ class SyncStoreReceiptOrderMatches extends Command 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) { $goodsTotal += $productAmount; diff --git a/app/Http/Controllers/Business/Pages.php b/app/Http/Controllers/Business/Pages.php index c2c7add7..27c4d148 100644 --- a/app/Http/Controllers/Business/Pages.php +++ b/app/Http/Controllers/Business/Pages.php @@ -362,6 +362,22 @@ class Pages extends Controller } /** 单行的「差额异常备注」(与筛选条件同一套口径,页面与导出共用)。 */ + /** + * 页面口径的「有效差额」SQL:口径兜底行(备注为空、但能对上实收/应付)按 0 计。 + * 合计、差额筛选、联动计数共用,保证三个地方的数字一致。 + */ + private static function receiptEffectiveDifferenceSql(): string + { + $ruleUnion = '(' . implode(' OR ', array_map( + static fn (string $condition): string => '(' . $condition . ')', + self::receiptDifferenceRemarkConditions() + )) . ')'; + + return "CASE WHEN remark IN ('订单实付按卖家实收核对','订单实付按应付/已付核对')" + . " AND NOT COALESCE({$ruleUnion}, 0) THEN 0" + . ' ELSE COALESCE(difference, COALESCE(income_amount, 0) + COALESCE(discount_amount, 0) + COALESCE(offset_amount, 0)) END'; + } + private static function receiptDifferenceRemark(object $row): ?string { $basis = self::differenceBasis(); @@ -463,6 +479,13 @@ class Pages extends Controller } } + // 原因优先:上面的规则都没命中时,如果这行的口径(卖家实收 / 应付已付)能对上账单, + // 就按口径兜底——差额按 0 展示、口径标识在「匹配原因」列,不再当异常。 + $rawRemark = trim((string) ($row->remark ?? '')); + if (in_array($rawRemark, ['订单实付按卖家实收核对', '订单实付按应付/已付核对'], true)) { + return null; + } + // 有差额但没命中任何已知原因:标「差额待核实」,页面上不再出现"有差额但备注空白"的行。 return '差额待核实'; } @@ -1036,6 +1059,8 @@ class Pages extends Controller // 计数与合计合并为一次全表扫描:重筛选项(如按备注筛选)下少一次全表重算。 $aggQuery = $base(); $applyFilters($aggQuery); + // 口径兜底行(备注为空、口径对上)的差额按 0 计——与页面行展示、差额筛选同一套判定。 + $differenceExpr = self::receiptEffectiveDifferenceSql(); $agg = $aggQuery->selectRaw(" COUNT(*) as total, SUM(payment_count) as payments, @@ -1046,7 +1071,7 @@ class Pages extends Controller SUM(planting_amount) as planting_total, SUM(product_amount) as goods_total, SUM(paid_amount) as paid_total, - SUM(COALESCE(difference, COALESCE(income_amount, 0) + COALESCE(discount_amount, 0) + COALESCE(offset_amount, 0))) as difference_total, + SUM({$differenceExpr}) as difference_total, SUM(CASE WHEN payment_count > 1 THEN 1 ELSE 0 END) as multi_pay, SUM(CASE WHEN income_amount = 0 THEN 1 ELSE 0 END) as zero_income, SUM(CASE WHEN match_status = '已匹配' THEN 1 ELSE 0 END) as matched, @@ -1148,6 +1173,12 @@ class Pages extends Controller ); } + // 口径兜底(原因优先之后):备注为空但带口径标识 → 差额按 0 展示。 + if ($row->remark === null + && in_array($rawRemark, ['订单实付按卖家实收核对', '订单实付按应付/已付核对'], true)) { + $row->difference = 0.0; + } + return $row; }); @@ -1226,7 +1257,7 @@ class Pages extends Controller if ($has === $none) { return; } - $effective = 'COALESCE(difference, COALESCE(income_amount, 0) + COALESCE(discount_amount, 0) + COALESCE(offset_amount, 0))'; + $effective = self::receiptEffectiveDifferenceSql(); $query->whereRaw($has ? 'ABS(' . $effective . ') > 0.005' : 'ABS(' . $effective . ') <= 0.005'); } @@ -1261,7 +1292,7 @@ class Pages extends Controller $query->where('online_order_no', 'like', '%' . addcslashes($orderNo, '%_\\') . '%'); } - $effective = 'COALESCE(difference, COALESCE(income_amount, 0) + COALESCE(discount_amount, 0) + COALESCE(offset_amount, 0))'; + $effective = self::receiptEffectiveDifferenceSql(); $row = $query->selectRaw('SUM(CASE WHEN ABS(' . $effective . ') > 0.005 THEN 1 ELSE 0 END) as has_diff, ' . 'SUM(CASE WHEN ABS(' . $effective . ') <= 0.005 THEN 1 ELSE 0 END) as none_diff')->first();