diff --git a/app/Http/Controllers/Business/Pages.php b/app/Http/Controllers/Business/Pages.php index d4ab1ca3..8ff64855 100644 --- a/app/Http/Controllers/Business/Pages.php +++ b/app/Http/Controllers/Business/Pages.php @@ -136,6 +136,12 @@ class Pages extends Controller '未匹配', ]; + /** 差额按实收/应付口径兜底时使用的备注;这部分行才需要判断复杂差额原因。 */ + private const RECEIPT_BASIS_FALLBACK_REMARKS = [ + '订单实付按卖家实收核对', + '订单实付按应付/已付核对', + ]; + /** 业绩明细「异常标注」筛选项,取值与同步命令写入的标注一致。 */ private const RECEIPT_REMARK_OPTIONS = [ '账单无单号', @@ -502,9 +508,41 @@ class Pages extends Controller $rules )) . ')'; - return "CASE WHEN remark IN ('订单实付按卖家实收核对','订单实付按应付/已付核对')" + return "CASE WHEN remark IN (" . self::receiptBasisFallbackSqlList() . ')' . " AND NOT COALESCE({$ruleUnion}, 0) THEN 0" - . ' ELSE COALESCE(difference, COALESCE(income_amount, 0) + COALESCE(discount_amount, 0) + COALESCE(offset_amount, 0)) END'; + . ' ELSE ' . self::receiptDefaultDifferenceSql() . ' END'; + } + + /** 未命中复杂原因时,差额的默认口径。 */ + private static function receiptDefaultDifferenceSql(): string + { + return 'COALESCE(difference, COALESCE(income_amount, 0) + COALESCE(discount_amount, 0) + COALESCE(offset_amount, 0))'; + } + + /** + * 口径兜底行的差额修正量:只对「实收/应付核对」行计算复杂规则, + * 避免把京东、京喜、得物、淘系退款等关联子查询放进整月汇总的每一行。 + */ + private static function receiptFallbackDifferenceAdjustmentSql(): string + { + $rules = self::receiptDifferenceRemarkConditions(); + unset($rules['差额待核实']); + $ruleUnion = '(' . implode(' OR ', array_map( + static fn (string $condition): string => '(' . $condition . ')', + $rules + )) . ')'; + + return 'CASE WHEN NOT COALESCE(' . $ruleUnion . ', 0) THEN -(' + . self::receiptDefaultDifferenceSql() . ') ELSE 0 END'; + } + + /** @return string SQL 的字符串字面量列表 */ + private static function receiptBasisFallbackSqlList(): string + { + return implode(', ', array_map( + static fn (string $remark): string => "'" . str_replace("'", "''", $remark) . "'", + self::RECEIPT_BASIS_FALLBACK_REMARKS + )); } private static function receiptDifferenceRemark(object $row): ?string @@ -1219,7 +1257,8 @@ class Pages extends Controller $aggQuery = $base(); $applyFilters($aggQuery); // 口径兜底行(备注为空、口径对上)的差额按 0 计——与页面行展示、差额筛选同一套判定。 - $differenceExpr = self::receiptEffectiveDifferenceSql(); + $differenceBaseExpr = self::receiptDefaultDifferenceSql(); + $fallbackSql = self::receiptBasisFallbackSqlList(); $agg = $aggQuery->selectRaw(" COUNT(*) as total, SUM(payment_count) as payments, @@ -1230,13 +1269,24 @@ class Pages extends Controller SUM(planting_amount) as planting_total, SUM(product_amount) as goods_total, SUM(paid_amount) as paid_total, - SUM({$differenceExpr}) as difference_total, + SUM({$differenceBaseExpr}) as difference_base, + SUM(CASE WHEN remark IN ({$fallbackSql}) THEN 1 ELSE 0 END) as basis_fallback_rows, 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, SUM(CASE WHEN match_status = '未匹配' THEN 1 ELSE 0 END) as unmatched ")->first(); $total = (int) ($agg->total ?? 0); + $differenceTotal = (float) ($agg->difference_base ?? 0); + if ((int) ($agg->basis_fallback_rows ?? 0) > 0) { + $adjustmentQuery = $base(); + $applyFilters($adjustmentQuery); + $adjustment = $adjustmentQuery + ->whereIn('remark', self::RECEIPT_BASIS_FALLBACK_REMARKS) + ->selectRaw('SUM(' . self::receiptFallbackDifferenceAdjustmentSql() . ') as adjustment') + ->first(); + $differenceTotal += (float) ($adjustment->adjustment ?? 0); + } $stats = [ 'month' => $month, @@ -1255,7 +1305,7 @@ class Pages extends Controller 'planting_total' => round((float) ($agg->planting_total ?? 0), 2), 'goods_total' => round((float) ($agg->goods_total ?? 0), 2), 'paid_total' => round((float) ($agg->paid_total ?? 0), 2), - 'difference_total' => round((float) ($agg->difference_total ?? 0), 2), + 'difference_total' => round($differenceTotal, 2), 'per_page' => $limit, ];