From 0974c551d49988f724a1def152743c52d921a8e1 Mon Sep 17 00:00:00 2001 From: yueyang <2495544247@qq.com> Date: Sat, 24 Oct 2026 19:57:16 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E4=B8=9A=E7=BB=A9=E6=98=8E?= =?UTF-8?q?=E7=BB=86=E8=AE=A2=E5=8D=95=E6=A0=B8=E5=AF=B9=E9=87=91=E9=A2=9D?= =?UTF-8?q?=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Http/Controllers/Business/Pages.php | 57 +++++++++++++++++-- config/business_navigation.php | 2 +- .../pages/partials/directory-table.blade.php | 3 +- .../PerformanceDetailsMetricDetailsTest.php | 48 ++++++++++++++++ .../PerformanceDifferenceRemarkTest.php | 34 +++++++++++ 5 files changed, 138 insertions(+), 6 deletions(-) diff --git a/app/Http/Controllers/Business/Pages.php b/app/Http/Controllers/Business/Pages.php index e0606948..ba073ebb 100644 --- a/app/Http/Controllers/Business/Pages.php +++ b/app/Http/Controllers/Business/Pages.php @@ -115,7 +115,7 @@ class Pages extends Controller /** 业绩明细可点击指标 → 主表金额列、账单项目明细桶、页面名称。 */ private const RECEIPT_METRIC_MAP = [ 'income_amount' => ['label' => '账单收入', 'metric' => 'income'], - 'paid_amount' => ['label' => '订单实付', 'metric' => null], + 'paid_amount' => ['label' => '订单核对金额', 'metric' => null], 'discount_amount' => ['label' => '优惠收入', 'metric' => 'discount'], 'offset_amount' => ['label' => '冲减收入', 'metric' => 'offset'], 'default_compensation_amount' => ['label' => '违约赔付', 'metric' => 'default_compensation'], @@ -324,6 +324,35 @@ class Pages extends Controller return "COALESCE(remark, '') NOT IN ('订单实付按卖家实收核对', '订单实付按应付/已付核对')"; } + /** + * 页面展示的订单核对金额。 + * + * 命中卖家实收/应付口径时,原 buyer_paid_amount 可能远大于本次账单核对值; + * 页面改为展示实际参与比对的金额,避免“收入 10、订单实付 13,079.80、差额 0”的视觉冲突。 + */ + private static function receiptComparablePaidSql(): string + { + return "CASE WHEN COALESCE(remark, '') IN (" . self::receiptBasisFallbackSqlList() . ')' + . ' THEN (' . self::receiptNetSql() . ')' + . ' ELSE COALESCE(paid_amount, 0) END'; + } + + private static function receiptComparablePaidAmount(object $row): float + { + $remark = trim((string) ($row->remark ?? '')); + if (! in_array($remark, self::RECEIPT_BASIS_FALLBACK_REMARKS, true)) { + return round((float) ($row->paid_amount ?? 0), 2); + } + + return round( + (float) ($row->income_amount ?? 0) + + (float) ($row->discount_amount ?? 0) + + (float) ($row->offset_amount ?? 0) + + (float) ($row->default_compensation_amount ?? 0), + 2 + ); + } + /** * 「差额异常备注」基础原因(不落库),按页面优先级排列。 * @@ -1510,7 +1539,7 @@ class Pages extends Controller SUM(default_compensation_amount) as default_compensation_total, SUM(refund_amount) as refund_total, SUM(planting_amount) as planting_total, - SUM(paid_amount) as paid_total, + SUM(" . self::receiptComparablePaidSql() . ") as paid_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, @@ -1615,6 +1644,7 @@ class Pages extends Controller // 未匹配行(差额为空)按比对基准金额=0 计入差额。 $items = $items->map(static function (object $row): object { $rawRemark = trim((string) ($row->remark ?? '')); + $comparablePaid = self::receiptComparablePaidAmount($row); // 未匹配原因列:未匹配行照旧;「订单实付按卖家实收核对」这类口径标识在已匹配行同样展示。 $row->unmatched_reason = $rawRemark === '' ? null @@ -1637,6 +1667,7 @@ class Pages extends Controller && in_array($rawRemark, ['订单实付按卖家实收核对', '订单实付按应付/已付核对'], true)) { $row->difference = 0.0; } + $row->paid_amount = $comparablePaid; return $row; }); @@ -1767,7 +1798,9 @@ class Pages extends Controller }) ->values(); } else { - $amountSql = 'COALESCE(' . $metric . ', 0)'; + $amountSql = $metric === 'paid_amount' + ? self::receiptComparablePaidSql() + : 'COALESCE(' . $metric . ', 0)'; $rows = (clone $query) ->select(['platform', 'store_name']) ->selectRaw('SUM(' . $amountSql . ') as amount') @@ -1859,6 +1892,14 @@ class Pages extends Controller private function receiptOrderMatchMetricTotal($query, string $metric, bool $crossMonthOnly = false): float { if ($metric !== 'difference') { + if ($metric === 'paid_amount') { + $total = (clone $query) + ->selectRaw('SUM(' . self::receiptComparablePaidSql() . ') as aggregate') + ->value('aggregate'); + + return round((float) $total, 2); + } + return round((float) (clone $query)->sum($metric), 2); } @@ -2488,7 +2529,7 @@ class Pages extends Controller 'default_compensation_amount' => ['default_compensation_amount', '违约赔付(冲减收入)', 'money'], 'refund_amount' => ['refund_amount', '退款金额', 'money'], 'planting_amount' => ['planting_amount', '种菜金额', 'money'], - 'paid_amount' => ['paid_amount', '订单实付金额', 'money'], + 'paid_amount' => ['paid_amount', '订单核对金额', 'money'], 'difference' => ['difference', '差额', 'money'], 'match_status' => ['match_status', '匹配状态', 'text'], 'remark' => ['remark', '差额异常备注', 'text'], @@ -2577,6 +2618,9 @@ class Pages extends Controller foreach ($selected as $key) { $format = $map[$key][2]; $value = $row->{$map[$key][0]} ?? ''; + if ($key === 'paid_amount') { + $value = self::receiptComparablePaidAmount($row); + } // 「差额异常备注」列与页面一致:只写差额产生的原因 if ($key === 'remark') { $value = self::receiptDifferenceRemark($row) ?? ''; @@ -2592,6 +2636,11 @@ class Pages extends Controller 2 ); } + $rawRemark = trim((string) ($row->remark ?? '')); + if ($key === 'difference' + && in_array($rawRemark, self::RECEIPT_BASIS_FALLBACK_REMARKS, true)) { + $value = 0; + } if ($format === 'money') { // 金额列空值导出成 0.00:Excel 里直接求和、做差额核对不用再补空。 $line[] = number_format((float) ($value === null || $value === '' ? 0 : $value), 2, '.', ''); diff --git a/config/business_navigation.php b/config/business_navigation.php index 9f6f5e11..cb07dea3 100644 --- a/config/business_navigation.php +++ b/config/business_navigation.php @@ -835,7 +835,7 @@ $navigation = [ ['name' => 'default_compensation_amount', 'label' => '违约赔付(冲减收入)', 'kind' => 'number'], ['name' => 'refund_amount', 'label' => '退款金额', 'kind' => 'number'], ['name' => 'planting_amount', 'label' => '种菜金额', 'kind' => 'number'], - ['name' => 'paid_amount', 'label' => '订单实付/实收金额', 'kind' => 'number'], + ['name' => 'paid_amount', 'label' => '订单核对金额', 'kind' => 'number'], ['name' => 'difference', 'label' => '差额', 'kind' => 'number'], ['name' => 'remark', 'label' => '差额异常备注'], ['name' => 'match_status', 'label' => '匹配状态'], diff --git a/resources/views/business/pages/partials/directory-table.blade.php b/resources/views/business/pages/partials/directory-table.blade.php index 70504a60..fabced28 100644 --- a/resources/views/business/pages/partials/directory-table.blade.php +++ b/resources/views/business/pages/partials/directory-table.blade.php @@ -1454,7 +1454,7 @@ @php $receiptMetricCards = [ ['metric' => 'income_amount', 'label' => '账单收入', 'value' => $receiptStats['income_total']], - ['metric' => 'paid_amount', 'label' => '订单实付', 'value' => $receiptStats['paid_total'] ?? 0], + ['metric' => 'paid_amount', 'label' => '订单核对金额', 'value' => $receiptStats['paid_total'] ?? 0], ['metric' => 'discount_amount', 'label' => '优惠收入', 'value' => $receiptStats['discount_total'] ?? 0], ['metric' => 'offset_amount', 'label' => '冲减收入', 'value' => $receiptStats['offset_total'] ?? 0], ['metric' => 'default_compensation_amount', 'label' => '违约赔付', 'value' => $receiptStats['default_compensation_total'] ?? 0], @@ -1607,6 +1607,7 @@

金额关系

diff --git a/tests/Feature/Business/PerformanceDetailsMetricDetailsTest.php b/tests/Feature/Business/PerformanceDetailsMetricDetailsTest.php index ebd5bb38..18140e46 100644 --- a/tests/Feature/Business/PerformanceDetailsMetricDetailsTest.php +++ b/tests/Feature/Business/PerformanceDetailsMetricDetailsTest.php @@ -117,6 +117,54 @@ class PerformanceDetailsMetricDetailsTest extends FeatureTestCase ], $response->json('rows')); } + public function test_paid_metric_uses_the_amount_used_by_the_matching_basis(): void + { + $mirror = DB::connection('business_mirror'); + $mirror->table('store_receipt_order_match_rows')->insert([ + array_merge($this->row('row-basis', '店铺A', 0), [ + 'income_amount' => 10.00, + 'paid_amount' => 13079.80, + 'difference' => -13069.80, + 'remark' => '订单实付按应付/已付核对', + ]), + array_merge($this->row('row-normal', '店铺B', 0), [ + 'income_amount' => 80.00, + 'paid_amount' => 100.00, + 'difference' => -20.00, + ]), + ]); + + $response = $this->loginAs()->getJson(route( + 'business.financial-operations.performance-details.metric-details', + [ + 'metric' => 'paid_amount', + 'month' => '2026-09', + ], + )); + + $response + ->assertOk() + ->assertJsonPath('label', '订单核对金额') + ->assertJsonPath('total', 110) + ->assertJsonPath('detail_total', 110) + ->assertJsonPath('balanced', true); + + $this->assertContains([ + 'platform' => '京东账单', + 'store_name' => '店铺A', + 'bill_item' => '订单核对金额', + 'amount' => 10, + 'line_count' => 1, + ], $response->json('rows')); + $this->assertContains([ + 'platform' => '京东账单', + 'store_name' => '店铺B', + 'bill_item' => '订单核对金额', + 'amount' => 100, + 'line_count' => 1, + ], $response->json('rows')); + } + private function row(string $rowKey, string $storeName, float $offset, string $platform = '京东账单'): array { return [ diff --git a/tests/Unit/EcommerceFinance/PerformanceDifferenceRemarkTest.php b/tests/Unit/EcommerceFinance/PerformanceDifferenceRemarkTest.php index bc5048aa..7827ac2d 100644 --- a/tests/Unit/EcommerceFinance/PerformanceDifferenceRemarkTest.php +++ b/tests/Unit/EcommerceFinance/PerformanceDifferenceRemarkTest.php @@ -40,6 +40,20 @@ class PerformanceDifferenceRemarkTest extends TestCase return (new ReflectionMethod(Pages::class, 'receiptDifferenceRemark'))->invoke(null, $row); } + private function comparablePaid(array $attributes): float + { + $row = (object) array_merge([ + 'income_amount' => 0, + 'discount_amount' => 0, + 'offset_amount' => 0, + 'default_compensation_amount' => 0, + 'paid_amount' => 0, + 'remark' => null, + ], $attributes); + + return (new ReflectionMethod(Pages::class, 'receiptComparablePaidAmount'))->invoke(null, $row); + } + public function test_pinduoduo_full_refund_wins_before_other_difference_rules(): void { $this->assertSame('订单实付含已退款部分', $this->remark([ @@ -158,6 +172,26 @@ class PerformanceDifferenceRemarkTest extends TestCase ])); } + public function test_basis_matched_rows_display_the_amount_used_for_comparison(): void + { + $this->assertSame(10.0, $this->comparablePaid([ + 'income_amount' => 10.00, + 'paid_amount' => 13079.80, + 'remark' => '订单实付按应付/已付核对', + ])); + $this->assertSame(90.0, $this->comparablePaid([ + 'income_amount' => 100.00, + 'discount_amount' => -10.00, + 'paid_amount' => 150.00, + 'remark' => '订单实付按卖家实收核对', + ])); + $this->assertSame(123.45, $this->comparablePaid([ + 'income_amount' => 100.00, + 'paid_amount' => 123.45, + 'remark' => null, + ])); + } + public function test_refund_difference_requires_the_refund_amount_to_reconcile(): void { $this->assertSame('订单实付含已退款部分', $this->remark([ -- 2.47.2