diff --git a/app/Http/Controllers/Business/PlantingWorkOrders.php b/app/Http/Controllers/Business/PlantingWorkOrders.php index 58ce9f73..70db1345 100644 --- a/app/Http/Controllers/Business/PlantingWorkOrders.php +++ b/app/Http/Controllers/Business/PlantingWorkOrders.php @@ -32,6 +32,15 @@ class PlantingWorkOrders extends Controller default => '-扣款', }; + // 发运营的拍A发B 名单直接按「种菜报销」的字段导出。 + if (request()->query('format') === 'reimbursement') { + return $this->csv( + '拍A发B发运营-' . $filters['month'], + PlantingReimbursementPageData::COLUMNS, + static fn () => $data->rows($filters), + ); + } + return $this->csv( PlantingLossPageData::TITLE . '-' . $filters['month'] . $suffix, $data->exportColumns(), diff --git a/modules/EcommerceFinance/Services/PlantingLossCalculator.php b/modules/EcommerceFinance/Services/PlantingLossCalculator.php index 5dbdfb63..4eb94ad1 100644 --- a/modules/EcommerceFinance/Services/PlantingLossCalculator.php +++ b/modules/EcommerceFinance/Services/PlantingLossCalculator.php @@ -14,7 +14,7 @@ use Modules\EcommerceFinance\Repositories\ShippingOrderRepository; * 种菜损耗(2026-10-19 财务确认的口径): * 1. 取 M 月种菜报销明细(完成时间 [M-02, M+1-02)); * 2. 用线上订单号去匹配发货数据(jst_oms_shipping)中 M-1、M 两个月发货的交易单号,匹配到的保留; - * 3. 匹配到的单里,任务备注或卖家备注写了“拍A发B”或“拍A发A”的不扣款,单独列出发给运营; + * 3. 任务备注或卖家备注写了“拍A发B”或“拍A发A”的不扣款,不论是否匹配到发货都单独列出发给运营; * 4. 实际只发了「信誉订单虚拟条码」「透明挂钩」这类商品的不扣款; * 5. 其余匹配到的作为扣款项,扣款金额 = Σ 发货商品成本价 × 数量 + 该订单在发货数据中的运费(2026-10-19 更正), * 成本价按发货条形码(=商品编码)取普通商品资料。未匹配到发货的不计入种菜损耗。 @@ -37,8 +37,9 @@ class PlantingLossCalculator /** * 信誉订单虚拟条码(种菜单自身的虚拟商品)。发货数据里同一交易单号下若出现它,说明这单本身是按虚拟条码走的, * 同单号下的其它商品是合并发货的别的订单,整单不扣款(2026-10-19 财务确认:信誉订单虚拟条码不扣款)。 + * 透明挂钩同理:同单号下出现透明挂钩即整单不扣款(2026-10-20 财务确认)。 */ - public const VIRTUAL_ORDER_KEYWORDS = ['信誉订单虚拟条码', '虚拟条码']; + public const VIRTUAL_ORDER_KEYWORDS = ['信誉订单虚拟条码', '虚拟条码', '透明挂钩']; public const VIRTUAL_ORDER_BARCODES = ['X00006', 'X00002']; @@ -111,7 +112,9 @@ class PlantingLossCalculator public static function isVirtualOrderItem(string $barcode, string $productName): bool { - if (in_array(strtoupper(trim($barcode)), self::VIRTUAL_ORDER_BARCODES, true)) { + $code = strtoupper(trim($barcode)); + // 透明挂钩条形码以 GG 开头(如 GG003-SZ / GG-xxx),2026-10-20 财务确认。 + if (in_array($code, self::VIRTUAL_ORDER_BARCODES, true) || str_starts_with($code, 'GG')) { return true; } foreach (self::VIRTUAL_ORDER_KEYWORDS as $keyword) { @@ -210,11 +213,12 @@ class PlantingLossCalculator $deductLines !== [] && $freight === null ? '运费缺失' : '', ])); - $keyword = $shipment === null ? null : self::exemptionKeyword((string) $row['task_remark'], (string) $row['seller_remark']); + // 拍A发B/拍A发A 不论是否匹配到发货都单独列出发给运营(2026-10-20 财务确认);匹配发货只用于挑出真实发货的单。 + $keyword = self::exemptionKeyword((string) $row['task_remark'], (string) $row['seller_remark']); [$result, $basis] = match (true) { + $keyword !== null => [self::RESULT_EXEMPT, '备注含“' . $keyword . '”' . ($shipment === null ? '(未匹配到发货)' : '')], $shipment === null => [self::RESULT_UNMATCHED, self::shippingLabel($month) . ' 发货数据中无此交易单号'], - $keyword !== null => [self::RESULT_EXEMPT, '备注含“' . $keyword . '”'], - $virtualOrder => [self::RESULT_FREE_GOODS, '发货含信誉订单虚拟条码(同单号其它商品为合并发货的别的订单)'], + $virtualOrder => [self::RESULT_FREE_GOODS, '发货含信誉订单虚拟条码/透明挂钩,整单不扣款'], $deductLines === [] => [self::RESULT_FREE_GOODS, '只发了虚拟条码/透明挂钩/无实物商品'], $missingText !== '' => [self::RESULT_DEDUCT, $missingText . ',扣款金额未含缺失部分'], default => [self::RESULT_DEDUCT, '已匹配发货,按成本价×数量+运费扣款'], diff --git a/modules/EcommerceFinance/View/PlantingLossPageData.php b/modules/EcommerceFinance/View/PlantingLossPageData.php index f2fbaf17..b5625ea8 100644 --- a/modules/EcommerceFinance/View/PlantingLossPageData.php +++ b/modules/EcommerceFinance/View/PlantingLossPageData.php @@ -80,7 +80,7 @@ class PlantingLossPageData $sync = $this->repository->syncStatus(); $shippingSync = $this->calculator->shippingStatus(); $empty = ['count' => 0, 'cost_missing' => 0] + array_fill_keys(self::SUM_KEYS, 0); - $summary = ['total' => 0, 'filtered' => $empty] + array_fill_keys(Calculator::RESULTS, $empty); + $summary = ['total' => 0, 'matched' => 0, 'filtered' => $empty] + array_fill_keys(Calculator::RESULTS, $empty); $items = []; $error = $this->syncError($sync); @@ -89,6 +89,7 @@ class PlantingLossPageData $all = $this->calculator->rows($filters['month']); foreach ($all as $row) { $summary['total']++; + $summary['matched'] += ($row['shipped_at'] ?? '') !== '' ? 1 : 0; $this->add($summary[$row['loss_result']], $row); } foreach ($this->rows($filters, $all) as $row) { @@ -100,7 +101,7 @@ class PlantingLossPageData } catch (\Throwable $exception) { report($exception); $error = '种菜损耗暂时无法计算(工单镜像或发货数据读取失败),请稍后重试。'; - $summary = ['total' => 0, 'filtered' => $empty] + array_fill_keys(Calculator::RESULTS, $empty); + $summary = ['total' => 0, 'matched' => 0, 'filtered' => $empty] + array_fill_keys(Calculator::RESULTS, $empty); $items = []; } } diff --git a/resources/views/business/pages/billing-transactions/planting-loss.blade.php b/resources/views/business/pages/billing-transactions/planting-loss.blade.php index d4b753e2..5eaaf4ac 100644 --- a/resources/views/business/pages/billing-transactions/planting-loss.blade.php +++ b/resources/views/business/pages/billing-transactions/planting-loss.blade.php @@ -13,7 +13,7 @@ @endphp
{{ $plantingFilters['month'] }} 月种菜报销明细(完成时间 {{ substr($plantingWindow['from'], 0, 10) }} 至 {{ \Illuminate\Support\Carbon::parse($plantingWindow['to'])->subDay()->format('Y-m-d') }})的线上订单号,匹配 {{ $shippingLabel }} 发货数据(发货时间 {{ substr($plantingShippingWindow['from'], 0, 10) }} 至 {{ \Illuminate\Support\Carbon::parse($plantingShippingWindow['to'])->subDay()->format('Y-m-d') }})中的交易单号。匹配到的单中,任务备注或卖家备注写了“拍A发B / 拍A发A”的、以及只发了信誉订单虚拟条码/透明挂钩的不扣款,其余按发货商品成本价×数量+该单运费扣款。
+{{ $plantingFilters['month'] }} 月种菜报销明细(完成时间 {{ substr($plantingWindow['from'], 0, 10) }} 至 {{ \Illuminate\Support\Carbon::parse($plantingWindow['to'])->subDay()->format('Y-m-d') }})的线上订单号,匹配 {{ $shippingLabel }} 发货数据(发货时间 {{ substr($plantingShippingWindow['from'], 0, 10) }} 至 {{ \Illuminate\Support\Carbon::parse($plantingShippingWindow['to'])->subDay()->format('Y-m-d') }})中的交易单号。任务备注或卖家备注写了“拍A发B / 拍A发A”的(不论是否匹配到发货)、以及匹配到的单中只发了信誉订单虚拟条码/透明挂钩的不扣款,其余按发货商品成本价×数量+该单运费扣款。