From d1ffaf773c2dfdf0a9f40e538798c66193eb1964 Mon Sep 17 00:00:00 2001 From: yueyang <2495544247@qq.com> Date: Tue, 13 Oct 2026 11:07:46 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=9A=E7=BB=A9=E6=98=8E=E7=BB=86=EF=BC=9A?= =?UTF-8?q?=E5=BE=97=E7=89=A9=E8=B4=9F=E5=B7=AE=E9=A2=9D=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E3=80=8C=E8=AE=A2=E5=8D=95=E5=AE=9E=E4=BB=98=E6=9C=AA=E5=87=8F?= =?UTF-8?q?=E8=81=94=E5=90=88=E8=90=A5=E9=94=80=E8=B4=B9=E3=80=8D=E5=A4=87?= =?UTF-8?q?=E6=B3=A8=EF=BC=9B=E6=8A=96=E9=9F=B3=E5=A4=87=E6=B3=A8=E6=94=B9?= =?UTF-8?q?=E5=90=8D=E3=80=8C=E8=AE=A2=E5=8D=95=E5=AE=9E=E4=BB=98=E5=90=AB?= =?UTF-8?q?=E5=B7=B2=E9=80=80=E6=AC=BE=E9=83=A8=E5=88=86=E3=80=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 得物:负差额 = 联合营销费未让利尾数(该单营销费支出 + 差额恰为整数)时标注;规则排在通用「未减冲减/优惠」之前,避免被笼统备注抢先;证据子查询仅在得物负差额行计算。抖音:备注名统一加「订单」前缀。导航说明同步更新。 --- app/Http/Controllers/Business/Pages.php | 60 +++++++++++++++++++++---- config/business_navigation.php | 2 +- 2 files changed, 53 insertions(+), 9 deletions(-) diff --git a/app/Http/Controllers/Business/Pages.php b/app/Http/Controllers/Business/Pages.php index a765dd60..d878f2a5 100644 --- a/app/Http/Controllers/Business/Pages.php +++ b/app/Http/Controllers/Business/Pages.php @@ -154,7 +154,7 @@ class Pages extends Controller } /** - * 「实付含已退款部分」的聚水潭证据 SQL(仅抖音负差额行计算,CASE 守卫保证其它行不触发子查询)。 + * 「订单实付含已退款部分」的聚水潭证据 SQL(仅抖音负差额行计算,CASE 守卫保证其它行不触发子查询)。 * * 退款单:经订单 o_id 关联(so_id 列没有索引,订单侧走 so_id 索引、退款单侧走 o_id 索引), * 只统计 SUCCESS 且非 Split 父单的叶子退款;分别取合计与单笔最大值。 @@ -182,6 +182,28 @@ class Pages extends Controller ]; } + /** + * 得物「联合营销费未让利」证据 SQL(仅得物负差额行计算,CASE 守卫保证其它行不触发子查询)。 + * + * 得物联合营销费 = 让利买家部分(整数)+ 商家自担尾数;订单实付只扣了让利部分, + * 未让利尾数 = 营销费支出 − 让利,即「营销费支出 + 差额」恰为整数; + * 对不上(差值非整)时不标注,避免误标。 + * + * @return array{guard:string, marketing_expense:string} + */ + private static function receiptDewuMarketingEvidenceSql(): array + { + $guard = "platform = '得物' AND COALESCE(difference, COALESCE(income_amount, 0) + COALESCE(discount_amount, 0) + COALESCE(offset_amount, 0)) < -0.005"; + + return [ + 'guard' => $guard, + 'marketing_expense' => "(SELECT COALESCE(SUM(b.expense_amount), 0) + FROM dewu_settlement_bill_rows b + WHERE b.online_order_no = store_receipt_order_match_rows.online_order_no + AND b.bill_item = '联合营销费')", + ]; + } + /** * 「差额异常备注」原因(不落库):说明差额为什么产生,一行最多一个,按顺序取第一条命中。 * 未匹配行 → 订单实付未匹配(细分原因见「未匹配原因」列);已匹配但基准金额=0 → 订单实付取数为0; @@ -196,19 +218,26 @@ class Pages extends Controller $label = $basis['label']; $rules = []; + $effective = 'COALESCE(difference, COALESCE(income_amount, 0) + COALESCE(discount_amount, 0) + COALESCE(offset_amount, 0))'; $rules[$label . '未匹配'] = "match_status = '未匹配'"; $rules[$label . '取数为0(种菜)'] = "match_status = '已匹配' AND planting_amount IS NOT NULL AND ABS(COALESCE($column, 0)) < 0.005"; $rules[$label . '取数为0'] = "match_status = '已匹配' AND planting_amount IS NULL AND ABS(COALESCE($column, 0)) < 0.005"; + // 得物「订单实付未减联合营销费」:负差额 = 联合营销费未让利尾数(营销费支出 + 差额恰为整数)才标注。 + // 放在通用「未减冲减/优惠」等式之前:得物这类行的差额常恰好等于冲减(营销费)金额,需优先给出具体项备注。 + $dewuEvidence = self::receiptDewuMarketingEvidenceSql(); + $dewuNeat = '(' . $dewuEvidence['marketing_expense'] . ' + ' . $effective . ')'; + $rules['订单实付未减联合营销费'] = 'CASE WHEN (' . $dewuEvidence['guard'] + . ' AND (' . $dewuEvidence['marketing_expense'] . ') > 0.005' + . ' AND ABS(' . $dewuNeat . ' - ROUND(' . $dewuNeat . ', 0)) < 0.005) THEN 1 ELSE 0 END = 1'; $rules[$label . '未减冲减'] = "match_status = '已匹配' AND ABS(COALESCE($column, 0) - (COALESCE(income_amount, 0) + COALESCE(discount_amount, 0))) < 0.005"; $rules[$label . '未减优惠'] = "match_status = '已匹配' AND ABS(COALESCE($column, 0) - (COALESCE(income_amount, 0) + COALESCE(offset_amount, 0))) < 0.005"; $rules[$label . '未减优惠和冲减'] = "match_status = '已匹配' AND ABS(COALESCE($column, 0) - COALESCE(income_amount, 0)) < 0.005"; - $effective = 'COALESCE(difference, COALESCE(income_amount, 0) + COALESCE(discount_amount, 0) + COALESCE(offset_amount, 0))'; - // 抖音「实付含已退款部分」:负差额能在聚水潭退款单/取消子单金额里对上(≈差额)才标注。 + // 抖音「订单实付含已退款部分」:负差额能在聚水潭退款单/取消子单金额里对上(≈差额)才标注。 $refundEvidence = self::receiptRefundEvidenceSql(); $differenceAbs = 'ABS(' . $effective . ')'; $refundHit = static fn (string $amount): string => 'CASE WHEN ' . $amount . ' > 0.005 THEN ABS(' . $amount . ' - ' . $differenceAbs . ') < 0.02 ELSE 0 END'; - $rules['实付含已退款部分'] = 'CASE WHEN (' . $refundEvidence['guard'] . ') THEN (' + $rules['订单实付含已退款部分'] = 'CASE WHEN (' . $refundEvidence['guard'] . ') THEN (' . $refundHit($refundEvidence['refund_sum']) . ' OR ' . $refundHit($refundEvidence['refund_max']) . ' OR ' . $refundHit($refundEvidence['cancelled_sum']) @@ -252,6 +281,17 @@ class Pages extends Controller if (abs($product) < 0.005) { return ($row->planting_amount ?? null) !== null ? $label . '取数为0(种菜)' : $label . '取数为0'; } + // 得物负差额:差额与联合营销费未让利尾数吻合(营销费支出 + 差额恰为整数)→「订单实付未减联合营销费」。 + // 放在通用「未减冲减/优惠」等式之前:得物这类行的差额常恰好等于冲减(营销费)金额,需优先给出具体项备注。 + if (($row->platform ?? '') === '得物' && $difference < -0.005) { + $marketingExpense = (float) ($row->order_dewu_marketing_expense ?? 0); + if ($marketingExpense > 0.005) { + $neat = $marketingExpense + $difference; + if (abs($neat - round($neat)) < 0.005) { + return '订单实付未减联合营销费'; + } + } + } if (abs($product - ($income + $discount)) < 0.005) { return $label . '未减冲减'; } @@ -262,12 +302,12 @@ class Pages extends Controller return $label . '未减优惠和冲减'; } - // 抖音负差额:实付多出来的部分能在聚水潭退款单/取消子单金额里对上(≈差额)→「实付含已退款部分」。 + // 抖音负差额:实付多出来的部分能在聚水潭退款单/取消子单金额里对上(≈差额)→「订单实付含已退款部分」。 if (($row->platform ?? '') === '抖音' && $difference < 0) { $refunds = [$row->order_refund_sum ?? null, $row->order_refund_max ?? null, $row->order_cancelled_sum ?? null]; foreach ($refunds as $refund) { if ($refund !== null && (float) $refund > 0.005 && abs((float) $refund - abs($difference)) < 0.02) { - return '实付含已退款部分'; + return '订单实付含已退款部分'; } } } @@ -927,11 +967,13 @@ class Pages extends Controller $itemsQuery = $base(); $applyFilters($itemsQuery); $refundEvidence = self::receiptRefundEvidenceSql(); + $dewuEvidence = self::receiptDewuMarketingEvidenceSql(); $items = $itemsQuery ->selectRaw('*') ->selectRaw('CASE WHEN (' . $refundEvidence['guard'] . ') THEN ' . $refundEvidence['refund_sum'] . ' END AS order_refund_sum') ->selectRaw('CASE WHEN (' . $refundEvidence['guard'] . ') THEN ' . $refundEvidence['refund_max'] . ' END AS order_refund_max') ->selectRaw('CASE WHEN (' . $refundEvidence['guard'] . ') THEN ' . $refundEvidence['cancelled_sum'] . ' END AS order_cancelled_sum') + ->selectRaw('CASE WHEN (' . $dewuEvidence['guard'] . ') THEN ' . $dewuEvidence['marketing_expense'] . ' END AS order_dewu_marketing_expense') ->orderBy('occurred_date') ->orderBy('store_name') ->orderBy('online_order_no') @@ -1303,13 +1345,15 @@ class Pages extends Controller $this->applyReceiptRemarkFilter($query, $remarkValues); } - // 「实付含已退款部分」判定所需证据列(与页面同一口径;仅抖音负差额行会真正计算子查询)。 + // 「订单实付含已退款部分」「订单实付未减联合营销费」判定所需证据列(与页面同一口径;仅对应平台负差额行会真正计算子查询)。 $refundEvidence = self::receiptRefundEvidenceSql(); + $dewuEvidence = self::receiptDewuMarketingEvidenceSql(); $query ->selectRaw('*') ->selectRaw('CASE WHEN (' . $refundEvidence['guard'] . ') THEN ' . $refundEvidence['refund_sum'] . ' END AS order_refund_sum') ->selectRaw('CASE WHEN (' . $refundEvidence['guard'] . ') THEN ' . $refundEvidence['refund_max'] . ' END AS order_refund_max') - ->selectRaw('CASE WHEN (' . $refundEvidence['guard'] . ') THEN ' . $refundEvidence['cancelled_sum'] . ' END AS order_cancelled_sum'); + ->selectRaw('CASE WHEN (' . $refundEvidence['guard'] . ') THEN ' . $refundEvidence['cancelled_sum'] . ' END AS order_cancelled_sum') + ->selectRaw('CASE WHEN (' . $dewuEvidence['guard'] . ') THEN ' . $dewuEvidence['marketing_expense'] . ' END AS order_dewu_marketing_expense'); $selected = array_values(array_intersect( array_filter(explode(',', (string) $request->query('columns', ''))), diff --git a/config/business_navigation.php b/config/business_navigation.php index 03661324..33125b63 100644 --- a/config/business_navigation.php +++ b/config/business_navigation.php @@ -806,7 +806,7 @@ $navigation = [ 'directory' => [ 'icon' => 'receipt_long', 'status' => '共享镜像', - 'description' => '覆盖店铺收款账户账单各平台页签(总账备注=订单收入),按「店铺 + 订单号」匹配订单侧商品金额与订单实付金额;一行 = 一个店铺的一个订单,商品金额只挂一次。「商品金额」只取主单(拆单子单不参与,整单没有主单时退化为取全部行),并排除虚拟条码(X0000x:信誉订单 / 虚拟订单)明细行;「订单实付金额」取订单级实付(拆单取主单)再减去虚拟条码行实付。「优惠金额」「冲减金额」另取总账备注=优惠收入 / 冲减收入的账单金额,不计入收入金额;「退款金额」另取总账备注=退款的账单金额,只单独列示,不计入收入金额、也不参与差额;「种菜金额」是订单号在种菜明细表或聚水潭订单标签明细(是否种菜订单=是)任意一边出现过时,该订单的收入金额(两个条件是或的关系),只是收入金额里的一部分,不参与差额;差额=(收入金额+优惠金额+冲减金额)−订单实付金额,匹配状态与差额异常备注同样按订单实付金额判定,未匹配到订单实付金额的行按订单实付金额=0 计入差额,只反映真正对不上的部分。挂不到订单行的优惠/冲减会补成一行(收入/商品留空)。「差额异常备注」只说明差额为什么产生,按顺序自动判定:订单实付未匹配(未匹配到订单实付金额,具体原因看「未匹配原因」列);订单实付取数为0(种菜)(订单实付=0 且是种菜单)、订单实付取数为0(订单实付=0 但不是种菜单)、订单实付未减冲减(订单实付=收入+优惠 → 差额=冲减金额)、订单实付未减优惠(订单实付=收入+冲减 → 差额=优惠金额)、订单实付未减优惠和冲减(订单实付=收入 → 差额=优惠+冲减)、实付含已退款部分(仅抖音负差额:聚水潭退款单/取消子单金额≈差额对上才标注);都不满足则留空。「未匹配原因」单独一列,取值:账单无单号 / 单号格式异常 / 订单表无此单 / 订单无实付金额 / 无收款账单。', + 'description' => '覆盖店铺收款账户账单各平台页签(总账备注=订单收入),按「店铺 + 订单号」匹配订单侧商品金额与订单实付金额;一行 = 一个店铺的一个订单,商品金额只挂一次。「商品金额」只取主单(拆单子单不参与,整单没有主单时退化为取全部行),并排除虚拟条码(X0000x:信誉订单 / 虚拟订单)明细行;「订单实付金额」取订单级实付(拆单取主单)再减去虚拟条码行实付。「优惠金额」「冲减金额」另取总账备注=优惠收入 / 冲减收入的账单金额,不计入收入金额;「退款金额」另取总账备注=退款的账单金额,只单独列示,不计入收入金额、也不参与差额;「种菜金额」是订单号在种菜明细表或聚水潭订单标签明细(是否种菜订单=是)任意一边出现过时,该订单的收入金额(两个条件是或的关系),只是收入金额里的一部分,不参与差额;差额=(收入金额+优惠金额+冲减金额)−订单实付金额,匹配状态与差额异常备注同样按订单实付金额判定,未匹配到订单实付金额的行按订单实付金额=0 计入差额,只反映真正对不上的部分。挂不到订单行的优惠/冲减会补成一行(收入/商品留空)。「差额异常备注」只说明差额为什么产生,按顺序自动判定:订单实付未匹配(未匹配到订单实付金额,具体原因看「未匹配原因」列);订单实付取数为0(种菜)(订单实付=0 且是种菜单)、订单实付取数为0(订单实付=0 但不是种菜单)、订单实付未减冲减(订单实付=收入+优惠 → 差额=冲减金额)、订单实付未减优惠(订单实付=收入+冲减 → 差额=优惠金额)、订单实付未减优惠和冲减(订单实付=收入 → 差额=优惠+冲减)、订单实付含已退款部分(仅抖音负差额:聚水潭退款单/取消子单金额≈差额对上才标注)、订单实付未减联合营销费(仅得物负差额:联合营销费未让利尾数对上才标注);都不满足则留空。「未匹配原因」单独一列,取值:账单无单号 / 单号格式异常 / 订单表无此单 / 订单无实付金额 / 无收款账单。', 'empty' => '店铺收款匹配订单明细尚未同步,请先执行 store-receipt:order-match:sync。', 'fields' => [ ['name' => 'platform', 'label' => '平台'],