From f2e839600709d875781a3211c069d4437795b700 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8B=8F=E6=9C=A8?= <594326199@qq.com> Date: Tue, 8 Sep 2026 16:19:14 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E8=B4=A6=E5=8D=95=E5=86=B2=E5=87=8F?= =?UTF-8?q?=E5=AD=90=E9=A1=B5=E9=9D=A2=E6=94=B9=E4=B8=BA=E5=A4=8D=E7=94=A8?= =?UTF-8?q?=E8=AE=A2=E5=8D=95=E5=94=AE=E5=90=8E=E8=B4=B9=E7=94=A8=E6=98=8E?= =?UTF-8?q?=E7=BB=86=E5=90=8C=E6=BA=90=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - BillOffsetPageData 注入 OrderDataPageData,page() 改为调用 afterSales(),使账单冲减子页面与订单售后费用明细页同源取数。 - 子页面按 账单冲减.xlsx 表头展示 9 列:内部订单号、线上订单号、店铺名称、店铺编码、商品编码、款式编码、店铺商品编码、店铺款式编码、500112冲减收入。 - 新增查询、重置与“导出当前页”按钮(沿用售后页前端 CSV 导出逻辑),并展示本页 500112 冲减收入合计。 - 500112 列本地镜像暂为 null,接入真实科目来源后自动填充,无需改模板。 --- .../View/BillOffsetPageData.php | 61 +++++++------ .../pages/order-data/bill-offset.blade.php | 88 ++++++++++++++----- 2 files changed, 98 insertions(+), 51 deletions(-) diff --git a/modules/EcommerceFinance/View/BillOffsetPageData.php b/modules/EcommerceFinance/View/BillOffsetPageData.php index befdaeb2..295598fd 100644 --- a/modules/EcommerceFinance/View/BillOffsetPageData.php +++ b/modules/EcommerceFinance/View/BillOffsetPageData.php @@ -2,14 +2,13 @@ namespace Modules\EcommerceFinance\View; -use Illuminate\Pagination\LengthAwarePaginator; -use Illuminate\Support\Collection; -use Modules\EcommerceFinance\Repositories\BillOffsetMirrorRepository; +use Illuminate\Pagination\Paginator; +use Modules\EcommerceFinance\View\OrderDataPageData; use Throwable; class BillOffsetPageData { - public function __construct(private readonly BillOffsetMirrorRepository $bills) + public function __construct(private readonly OrderDataPageData $orderData) { } @@ -23,41 +22,39 @@ class BillOffsetPageData 'shop_name' => $this->text(request('shop_name')), 'sku_id' => $this->text(request('sku_id')), ]; - $page = max((int) request('page', 1), 1); - $limit = min(max((int) setting('default.list_limit', 25), 1), 100); - $rows = new LengthAwarePaginator([], 0, $limit, $page, [ - 'path' => request()->url(), - 'query' => request()->except('page'), - ]); - $summary = ['amount' => 0.0, 'count' => 0]; - $sync = ['status' => 'unavailable', 'last_succeeded_at' => null]; - $error = null; try { - $result = $this->bills->paginate($filters, $page, $limit); - $rows = new LengthAwarePaginator( - Collection::make($result['data'] ?? []), - (int) ($result['total'] ?? 0), - $limit, - $page, - ['path' => request()->url(), 'query' => request()->except('page')], - ); - $summary = $result['summary'] ?? $summary; - $sync = $result['sync'] ?? $sync; + $data = $this->orderData->afterSales(); } catch (Throwable $exception) { - if (! str_contains($exception->getMessage(), 'bill_offset_mirror_not_ready')) { - report($exception); - } - $error = '账单冲减镜像尚未完成首次同步,当前不把空镜像解释为没有数据。'; + report($exception); + $rows = new Paginator([], 25, 1, [ + 'path' => request()->url(), + 'query' => request()->except('page'), + ]); + + return [ + 'view' => 'business.pages.order-data.bill-offset', + 'billOffsetRows' => $rows, + 'billOffsetFilters' => $filters, + 'billOffsetError' => '订单售后费用数据暂时无法读取,请稍后重试。', + 'billOffsetStatus' => null, + 'billOffsetPageAmount' => 0.0, + ]; + } + + $rows = $data['orderDataRows']; + $pageAmount = 0.0; + foreach (($rows->items() ?? []) as $item) { + $pageAmount += (float) (data_get($item, 'account_500112') ?? 0); } return [ 'view' => 'business.pages.order-data.bill-offset', 'billOffsetRows' => $rows, - 'billOffsetFilters' => $filters, - 'billOffsetSummary' => $summary, - 'billOffsetSync' => $sync, - 'billOffsetError' => $error, + 'billOffsetFilters' => $data['orderDataFilters'] ?? $filters, + 'billOffsetError' => $data['orderDataError'] ?? null, + 'billOffsetStatus' => data_get($data, 'orderDataStatus.X-Caiwu-Data-Status'), + 'billOffsetPageAmount' => $pageAmount, ]; } @@ -69,9 +66,11 @@ class BillOffsetPageData private function date(mixed $value): string { $value = trim((string) $value); + if (preg_match('/^(\d{4})-(\d{2})-(\d{2})$/', $value, $matches) !== 1) { return ''; } + return checkdate((int) $matches[2], (int) $matches[3], (int) $matches[1]) ? $value : ''; } } diff --git a/resources/views/business/pages/order-data/bill-offset.blade.php b/resources/views/business/pages/order-data/bill-offset.blade.php index 6fe889cd..f5bd45c3 100644 --- a/resources/views/business/pages/order-data/bill-offset.blade.php +++ b/resources/views/business/pages/order-data/bill-offset.blade.php @@ -1,19 +1,21 @@ @php $rows = $billOffsetRows ?? null; $filters = $billOffsetFilters ?? []; - $summary = $billOffsetSummary ?? ['amount' => 0, 'count' => 0]; - $sync = $billOffsetSync ?? ['status' => 'unavailable', 'last_succeeded_at' => null]; + $error = $billOffsetError ?? null; + $status = $billOffsetStatus ?? null; + $pageAmount = (float) ($billOffsetPageAmount ?? 0); $columns = [ 'internal_order_no' => '内部订单号', 'online_order_no' => '线上订单号', 'shop_name' => '店铺名称', 'shop_code' => '店铺编码', 'product_code' => '商品编码', - 'style_code' => '款式编码(参考)', + 'style_code' => '款式编码', 'shop_product_code' => '店铺商品编码', 'shop_style_code' => '店铺款式编码', - 'amount' => '500112冲减收入', + 'account_500112' => '500112冲减收入', ]; + $numberFields = ['account_500112' => true]; @endphp
@@ -31,14 +33,14 @@
- +
- +
@@ -59,33 +61,46 @@
重置 - total() === 0) aria-disabled="true" tabindex="-1" @endif> - 导出全部 - +
- @if ($billOffsetError ?? null) -
{{ $billOffsetError }}
+ @if ($error) +
{{ $error }}
@endif
-
记录数{{ number_format((int) ($summary['count'] ?? 0)) }}
-
冲减收入合计{{ number_format((float) ($summary['amount'] ?? 0), 2) }}
+
本页 500112 冲减收入合计{{ number_format($pageAmount, 2) }}
- @if (!empty($sync['last_succeeded_at'])) -
数据状态:{{ strtoupper((string) ($sync['status'] ?? 'mirror')) }} · 最近同步 {{ $sync['last_succeeded_at'] }}
+ @if ($status) +
数据状态:{{ strtoupper((string) $status) }}
@endif
- @foreach ($columns as $field => $header)@endforeach + @foreach ($columns as $field => $header)@endforeach @forelse ($rows ?? [] as $row) @foreach ($columns as $field => $header) @php $value = data_get($row, $field); @endphp - + @endforeach @empty @@ -95,10 +110,10 @@
$field === 'amount'])>{{ $header }}
isset($numberFields[$field])])>{{ $header }}
$field === 'amount'])>{{ $field === 'amount' ? number_format((float) ($value ?? 0), 2) : (($value === null || $value === '') ? '-' : $value) }} isset($numberFields[$field])]) + >{{ isset($numberFields[$field]) ? (($value === null || $value === '') ? '-' : number_format((float) $value, 2)) : (($value === null || $value === '') ? '-' : $value) }}
- 当前页 {{ $rows?->count() ?? 0 }} 条 · 共 {{ $rows?->total() ?? 0 }} 条 + 当前页 {{ $rows?->count() ?? 0 }} 条 @if ($status) · {{ strtoupper((string) $status) }} @endif
!$rows || $rows->onFirstPage()]) aria-label="上一页"> - 第 {{ $rows?->currentPage() ?? 1 }} / {{ $rows?->lastPage() ?? 1 }} 页 + 第 {{ $rows?->currentPage() ?? 1 }} 页 !$rows?->hasMorePages()]) aria-label="下一页">
@@ -108,10 +123,43 @@ -- 2.47.2 From 398c80f5a8c98364d19747311c799f05e454767f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8B=8F=E6=9C=A8?= <594326199@qq.com> Date: Tue, 8 Sep 2026 16:41:24 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E8=B4=A6=E5=8D=95=E5=86=B2=E5=87=8F/?= =?UTF-8?q?=E5=94=AE=E5=90=8E=E6=98=8E=E7=BB=86=EF=BC=9A=E6=8E=A5=E5=85=A5?= =?UTF-8?q?=20500112=20=E5=86=B2=E5=87=8F=E6=94=B6=E5=85=A5=E5=8F=96?= =?UTF-8?q?=E6=95=B0=EF=BC=88=E6=9A=82=E7=94=A8=E9=80=80=E8=B4=A7=E7=BA=A2?= =?UTF-8?q?=E5=86=B2=E9=87=91=E9=A2=9D=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - OrderDataRepository 与 OrderDataMirrorRepository 的 afterSales() 现对 account_500112 取数:\n 暂以「退货红冲金额(reversal_order_amount,即负值商品金额的绝对值)」作为收入冲减口径。\n- 该字段此前在 expenseFields() 中仅被列示、从未取值,故本地恒为 null;\n 其余 account_* 科目字段仍为空,待科目归集(金蝶/外部科目源)整体接入。\n- 取数口径为临时占位,待财务确认最终规则后替换(集中在一处,易于调整)。\n- 账单冲减子页面本页 500112 合计已可正常汇总。 --- .../Repositories/OrderDataMirrorRepository.php | 3 +++ modules/EcommerceFinance/Repositories/OrderDataRepository.php | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/modules/EcommerceFinance/Repositories/OrderDataMirrorRepository.php b/modules/EcommerceFinance/Repositories/OrderDataMirrorRepository.php index b3b0abdc..08d99ac1 100644 --- a/modules/EcommerceFinance/Repositories/OrderDataMirrorRepository.php +++ b/modules/EcommerceFinance/Repositories/OrderDataMirrorRepository.php @@ -251,6 +251,9 @@ class OrderDataMirrorRepository foreach ($this->expenseFields() as $field) { $row[$field] = null; } + // 500112 冲减收入:暂以「退货红冲金额(reversal_order_amount)」作为收入冲减口径, + // 待财务确认最终取数规则后替换。其余 account_* 科目字段仍为空(科目归集未接入)。 + $row['account_500112'] = round((float) ($row['reversal_order_amount'] ?? 0), 2); unset($row['shop_site'], $row['unit_cost'], $row['sku_name'], $row['seller_income_amount'], $row['src_combine_sku_id'], $row['send_warehouse'], $row['wms_co_id']); return $row; diff --git a/modules/EcommerceFinance/Repositories/OrderDataRepository.php b/modules/EcommerceFinance/Repositories/OrderDataRepository.php index 70ba60f5..e22e3a6b 100644 --- a/modules/EcommerceFinance/Repositories/OrderDataRepository.php +++ b/modules/EcommerceFinance/Repositories/OrderDataRepository.php @@ -271,6 +271,10 @@ class OrderDataRepository $row[$field] = $this->decimal($row[$field] ?? null); } + // 500112 冲减收入:暂以「退货红冲金额(reversal_order_amount)」作为收入冲减口径, + // 待财务确认最终取数规则后替换。其余 account_* 科目字段仍为空(科目归集未接入)。 + $row['account_500112'] = $this->decimal($row['reversal_order_amount'] ?? null); + foreach ($this->amountFields() as $field) { if (array_key_exists($field, $row)) { $row[$field] = $this->decimal($row[$field]) ?? 0.0; -- 2.47.2 From 3d14eb3b7e9e3e61f9be314f160585edca18f863 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8B=8F=E6=9C=A8?= <594326199@qq.com> Date: Wed, 9 Sep 2026 12:18:06 +0800 Subject: [PATCH 3/3] fix: use original bill amount for 500112 offset --- .../OrderDataMirrorRepository.php | 3 - .../Repositories/OrderDataRepository.php | 4 - .../View/BillOffsetPageData.php | 64 +++++++------- .../pages/order-data/bill-offset.blade.php | 84 +++++-------------- tests/Feature/Business/PagesTest.php | 52 ++++++++++++ .../BillOffsetMirrorRepositoryTest.php | 7 ++ .../OrderDataMirrorRepositoryTest.php | 1 + .../OrderDataRepositoryTest.php | 1 + 8 files changed, 114 insertions(+), 102 deletions(-) diff --git a/modules/EcommerceFinance/Repositories/OrderDataMirrorRepository.php b/modules/EcommerceFinance/Repositories/OrderDataMirrorRepository.php index 08d99ac1..b3b0abdc 100644 --- a/modules/EcommerceFinance/Repositories/OrderDataMirrorRepository.php +++ b/modules/EcommerceFinance/Repositories/OrderDataMirrorRepository.php @@ -251,9 +251,6 @@ class OrderDataMirrorRepository foreach ($this->expenseFields() as $field) { $row[$field] = null; } - // 500112 冲减收入:暂以「退货红冲金额(reversal_order_amount)」作为收入冲减口径, - // 待财务确认最终取数规则后替换。其余 account_* 科目字段仍为空(科目归集未接入)。 - $row['account_500112'] = round((float) ($row['reversal_order_amount'] ?? 0), 2); unset($row['shop_site'], $row['unit_cost'], $row['sku_name'], $row['seller_income_amount'], $row['src_combine_sku_id'], $row['send_warehouse'], $row['wms_co_id']); return $row; diff --git a/modules/EcommerceFinance/Repositories/OrderDataRepository.php b/modules/EcommerceFinance/Repositories/OrderDataRepository.php index e22e3a6b..70ba60f5 100644 --- a/modules/EcommerceFinance/Repositories/OrderDataRepository.php +++ b/modules/EcommerceFinance/Repositories/OrderDataRepository.php @@ -271,10 +271,6 @@ class OrderDataRepository $row[$field] = $this->decimal($row[$field] ?? null); } - // 500112 冲减收入:暂以「退货红冲金额(reversal_order_amount)」作为收入冲减口径, - // 待财务确认最终取数规则后替换。其余 account_* 科目字段仍为空(科目归集未接入)。 - $row['account_500112'] = $this->decimal($row['reversal_order_amount'] ?? null); - foreach ($this->amountFields() as $field) { if (array_key_exists($field, $row)) { $row[$field] = $this->decimal($row[$field]) ?? 0.0; diff --git a/modules/EcommerceFinance/View/BillOffsetPageData.php b/modules/EcommerceFinance/View/BillOffsetPageData.php index 295598fd..68ebb8d1 100644 --- a/modules/EcommerceFinance/View/BillOffsetPageData.php +++ b/modules/EcommerceFinance/View/BillOffsetPageData.php @@ -2,13 +2,14 @@ namespace Modules\EcommerceFinance\View; -use Illuminate\Pagination\Paginator; -use Modules\EcommerceFinance\View\OrderDataPageData; +use Illuminate\Pagination\LengthAwarePaginator; +use Illuminate\Support\Collection; +use Modules\EcommerceFinance\Repositories\BillOffsetMirrorRepository; use Throwable; class BillOffsetPageData { - public function __construct(private readonly OrderDataPageData $orderData) + public function __construct(private readonly BillOffsetMirrorRepository $bills) { } @@ -22,39 +23,44 @@ class BillOffsetPageData 'shop_name' => $this->text(request('shop_name')), 'sku_id' => $this->text(request('sku_id')), ]; + $page = max((int) request('page', 1), 1); + $limit = min(max((int) setting('default.list_limit', 25), 1), 100); + $rows = new LengthAwarePaginator([], 0, $limit, $page, [ + 'path' => request()->url(), + 'query' => request()->except('page'), + ]); + $summary = ['amount' => 0.0, 'count' => 0]; + $sync = ['status' => 'unavailable', 'last_succeeded_at' => null]; + $error = null; try { - $data = $this->orderData->afterSales(); + $result = $this->bills->paginate($filters, $page, $limit); + $rows = new LengthAwarePaginator( + Collection::make($result['data'] ?? []), + (int) ($result['total'] ?? 0), + $limit, + $page, + ['path' => request()->url(), 'query' => request()->except('page')], + ); + $summary = $result['summary'] ?? $summary; + $sync = $result['sync'] ?? $sync; } catch (Throwable $exception) { - report($exception); - $rows = new Paginator([], 25, 1, [ - 'path' => request()->url(), - 'query' => request()->except('page'), - ]); - - return [ - 'view' => 'business.pages.order-data.bill-offset', - 'billOffsetRows' => $rows, - 'billOffsetFilters' => $filters, - 'billOffsetError' => '订单售后费用数据暂时无法读取,请稍后重试。', - 'billOffsetStatus' => null, - 'billOffsetPageAmount' => 0.0, - ]; - } - - $rows = $data['orderDataRows']; - $pageAmount = 0.0; - foreach (($rows->items() ?? []) as $item) { - $pageAmount += (float) (data_get($item, 'account_500112') ?? 0); + $mirrorNotReady = str_contains($exception->getMessage(), 'bill_offset_mirror_not_ready'); + if (! $mirrorNotReady) { + report($exception); + } + $error = $mirrorNotReady + ? '账单冲减镜像尚未完成首次同步,当前不把空镜像解释为没有数据。' + : '账单冲减数据暂时无法读取,请稍后重试。'; } return [ 'view' => 'business.pages.order-data.bill-offset', 'billOffsetRows' => $rows, - 'billOffsetFilters' => $data['orderDataFilters'] ?? $filters, - 'billOffsetError' => $data['orderDataError'] ?? null, - 'billOffsetStatus' => data_get($data, 'orderDataStatus.X-Caiwu-Data-Status'), - 'billOffsetPageAmount' => $pageAmount, + 'billOffsetFilters' => $filters, + 'billOffsetSummary' => $summary, + 'billOffsetSync' => $sync, + 'billOffsetError' => $error, ]; } @@ -66,11 +72,9 @@ class BillOffsetPageData private function date(mixed $value): string { $value = trim((string) $value); - if (preg_match('/^(\d{4})-(\d{2})-(\d{2})$/', $value, $matches) !== 1) { return ''; } - return checkdate((int) $matches[2], (int) $matches[3], (int) $matches[1]) ? $value : ''; } } diff --git a/resources/views/business/pages/order-data/bill-offset.blade.php b/resources/views/business/pages/order-data/bill-offset.blade.php index f5bd45c3..9bb8df8a 100644 --- a/resources/views/business/pages/order-data/bill-offset.blade.php +++ b/resources/views/business/pages/order-data/bill-offset.blade.php @@ -1,21 +1,19 @@ @php $rows = $billOffsetRows ?? null; $filters = $billOffsetFilters ?? []; - $error = $billOffsetError ?? null; - $status = $billOffsetStatus ?? null; - $pageAmount = (float) ($billOffsetPageAmount ?? 0); + $summary = $billOffsetSummary ?? ['amount' => 0, 'count' => 0]; + $sync = $billOffsetSync ?? ['status' => 'unavailable', 'last_succeeded_at' => null]; $columns = [ 'internal_order_no' => '内部订单号', 'online_order_no' => '线上订单号', 'shop_name' => '店铺名称', 'shop_code' => '店铺编码', 'product_code' => '商品编码', - 'style_code' => '款式编码', + 'style_code' => '款式编码(参考)', 'shop_product_code' => '店铺商品编码', 'shop_style_code' => '店铺款式编码', - 'account_500112' => '500112冲减收入', + 'amount' => '500112冲减收入', ]; - $numberFields = ['account_500112' => true]; @endphp
@@ -33,14 +31,14 @@
- +
- +
@@ -61,46 +59,33 @@
重置 - + total() === 0) aria-disabled="true" tabindex="-1" @endif> + 导出全部 +
- @if ($error) -
{{ $error }}
+ @if ($billOffsetError ?? null) +
{{ $billOffsetError }}
@endif
-
本页 500112 冲减收入合计{{ number_format($pageAmount, 2) }}
+
记录数{{ number_format((int) ($summary['count'] ?? 0)) }}
+
冲减收入合计{{ number_format((float) ($summary['amount'] ?? 0), 2) }}
- @if ($status) -
数据状态:{{ strtoupper((string) $status) }}
+ @if (!empty($sync['last_succeeded_at'])) +
数据状态:{{ strtoupper((string) ($sync['status'] ?? 'mirror')) }} · 最近同步 {{ $sync['last_succeeded_at'] }}
@endif
- @foreach ($columns as $field => $header)@endforeach + @foreach ($columns as $field => $header)@endforeach @forelse ($rows ?? [] as $row) @foreach ($columns as $field => $header) @php $value = data_get($row, $field); @endphp - + @endforeach @empty @@ -110,10 +95,10 @@
isset($numberFields[$field])])>{{ $header }}
$field === 'amount'])>{{ $header }}
isset($numberFields[$field])]) - >{{ isset($numberFields[$field]) ? (($value === null || $value === '') ? '-' : number_format((float) $value, 2)) : (($value === null || $value === '') ? '-' : $value) }} $field === 'amount'])>{{ $field === 'amount' ? number_format((float) ($value ?? 0), 2) : (($value === null || $value === '') ? '-' : $value) }}
- 当前页 {{ $rows?->count() ?? 0 }} 条 @if ($status) · {{ strtoupper((string) $status) }} @endif + 当前页 {{ $rows?->count() ?? 0 }} 条 · 共 {{ $rows?->total() ?? 0 }} 条
!$rows || $rows->onFirstPage()]) aria-label="上一页"> - 第 {{ $rows?->currentPage() ?? 1 }} 页 + 第 {{ $rows?->currentPage() ?? 1 }} / {{ $rows?->lastPage() ?? 1 }} 页 !$rows?->hasMorePages()]) aria-label="下一页">
@@ -130,36 +115,5 @@ trigger.addEventListener('click', () => { input.focus(); if (typeof input.showPicker === 'function') input.showPicker(); else input.click(); }); }); - const button = document.getElementById('bill-offset-export-button'); - if (!button || button.dataset.exportBound === 'true') return; - button.dataset.exportBound = 'true'; - button.addEventListener('click', () => { - const table = document.getElementById(button.dataset.exportTable || ''); - const bodyRows = table ? Array.from(table.querySelectorAll('tbody tr:not(.is-empty)')) : []; - if (!table || bodyRows.length === 0) return; - - const protectSpreadsheetFormula = (value) => /^[=+\-@\t\r]/.test(value) ? `'${value}` : value; - const csvCell = (value, isNumber = false) => { - const raw = String(value ?? '').replace(/\r\n?/g, '\n'); - const normalized = isNumber ? raw : protectSpreadsheetFormula(raw); - return `"${normalized.replace(/"/g, '""')}"`; - }; - const header = Array.from(table.querySelectorAll('thead th')) - .map((cell) => csvCell(cell.textContent.trim())); - const rows = bodyRows.map((row) => Array.from(row.querySelectorAll('td')) - .map((cell) => csvCell( - cell.dataset.exportValue ?? cell.textContent.trim(), - cell.dataset.exportNumber === 'true', - ))); - const csv = [header, ...rows].map((row) => row.join(',')).join('\r\n'); - const blob = new Blob(['', csv], { type: 'text/csv;charset=utf-8' }); - const url = URL.createObjectURL(blob); - const link = document.createElement('a'); - link.href = url; - link.download = button.dataset.exportFilename || '账单冲减.csv'; - document.body.appendChild(link); - link.click(); - window.setTimeout(() => { link.remove(); URL.revokeObjectURL(url); }, 1000); - }); })(); diff --git a/tests/Feature/Business/PagesTest.php b/tests/Feature/Business/PagesTest.php index d8d037ca..5c09a8da 100644 --- a/tests/Feature/Business/PagesTest.php +++ b/tests/Feature/Business/PagesTest.php @@ -306,6 +306,22 @@ class PagesTest extends FeatureTestCase ->assertSeeText('数据状态:SUCCEEDED'); } + public function testBillOffsetPageShowsReadFailureSeparatelyFromAnUnreadyMirror(): void + { + $this->user->attachPermission( + Permission::where('name', 'read-admin-panel')->firstOrFail() + ); + $repository = Mockery::mock(BillOffsetMirrorRepository::class); + $repository->shouldReceive('paginate')->once()->andThrow(new \RuntimeException('database unavailable')); + $this->app->instance(BillOffsetMirrorRepository::class, $repository); + + $this->loginAs()->get(route('business.pages.show', [ + 'section' => 'order-data', 'page' => 'bill-offset', + ]))->assertOk() + ->assertSeeText('账单冲减数据暂时无法读取,请稍后重试。') + ->assertDontSeeText('账单冲减镜像尚未完成首次同步,当前不把空镜像解释为没有数据。'); + } + public function testBillOffsetExportReturnsCsvForTheFilteredRows(): void { $this->user->attachPermission( @@ -338,6 +354,42 @@ class PagesTest extends FeatureTestCase $this->assertStringContainsString('-20', $csv); } + public function testBillOffsetExportIncludesAllPagesForTheSameFilters(): void + { + $this->user->attachPermission( + Permission::where('name', 'read-admin-panel')->firstOrFail() + ); + $repository = Mockery::mock(BillOffsetMirrorRepository::class); + $filters = [ + 'from' => '2026-08-01', 'to' => '2026-08-31', 'order_no' => '', 'shop_name' => '', 'sku_id' => '', + ]; + $repository->shouldReceive('paginate')->once()->with($filters, 1, 100)->andReturn([ + 'data' => [[ + 'internal_order_no' => 'ORDER-1', 'online_order_no' => 'ONLINE-1', 'shop_name' => '店铺一', + 'shop_code' => 'SHOP-1', 'product_code' => 'SKU-1', 'style_code' => 'STYLE-1', + 'shop_product_code' => 'SP-1', 'shop_style_code' => 'SI-1', 'amount' => -20, + ]], + 'total' => 101, 'sync' => ['status' => 'succeeded'], + ]); + $repository->shouldReceive('paginate')->once()->with($filters, 2, 100)->andReturn([ + 'data' => [[ + 'internal_order_no' => 'ORDER-101', 'online_order_no' => 'ONLINE-101', 'shop_name' => '店铺一', + 'shop_code' => 'SHOP-1', 'product_code' => 'SKU-101', 'style_code' => 'STYLE-101', + 'shop_product_code' => 'SP-101', 'shop_style_code' => 'SI-101', 'amount' => 18.25, + ]], + 'total' => 101, 'sync' => ['status' => 'succeeded'], + ]); + $this->app->instance(BillOffsetMirrorRepository::class, $repository); + + $csv = $this->loginAs()->get(route('business.bill-offset.export', [ + 'from' => '2026-08-01', 'to' => '2026-08-31', + ]))->streamedContent(); + + $this->assertStringContainsString('ORDER-1', $csv); + $this->assertStringContainsString('ORDER-101', $csv); + $this->assertSame(3, substr_count($csv, "\n")); + } + public function testFinancialAfterSalesPageRendersMirroredJushuitanRefunds(): void { $this->user->attachPermission( diff --git a/tests/Unit/EcommerceFinance/BillOffsetMirrorRepositoryTest.php b/tests/Unit/EcommerceFinance/BillOffsetMirrorRepositoryTest.php index 7e82c470..569f9739 100644 --- a/tests/Unit/EcommerceFinance/BillOffsetMirrorRepositoryTest.php +++ b/tests/Unit/EcommerceFinance/BillOffsetMirrorRepositoryTest.php @@ -64,11 +64,13 @@ class BillOffsetMirrorRepositoryTest extends TestCase DB::connection('business_mirror')->table('ops_jst_original_bill_info')->insert([ ['Id' => 1, 'fee_time' => '2026-08-01 10:00:00', 'fee_name' => '500112冲减收入', 'inout_type' => '收入', 'so_id' => 'SO-1', 'sku_id' => 'SKU-1', 'amount' => -20], ['Id' => 2, 'fee_time' => '2026-08-02 10:00:00', 'fee_name' => '500112冲减收入', 'inout_type' => '收入', 'so_id' => 'SO-2', 'sku_id' => 'SKU-2', 'amount' => 18.25], + ['Id' => 3, 'fee_time' => '2026-08-03 10:00:00', 'fee_name' => '冲减收入', 'inout_type' => '收入', 'so_id' => 'SO-3', 'sku_id' => 'SKU-3', 'amount' => 7], ['Id' => 4, 'fee_time' => '2026-08-01 10:00:00', 'fee_name' => '订单收入', 'inout_type' => '收入', 'so_id' => 'SO-1', 'sku_id' => 'SKU-1', 'amount' => 100], ]); DB::connection('business_mirror')->table('ops_jst_orders')->insert([ ['o_id' => 1001, 'so_id' => 'SO-1', 'shop_name' => '测试店铺', 'shop_id' => 'SHOP-1'], ['o_id' => 1002, 'so_id' => 'SO-2', 'shop_name' => '其他店铺', 'shop_id' => 'SHOP-2'], + ['o_id' => 1003, 'so_id' => 'SO-3', 'shop_name' => '历史店铺', 'shop_id' => 'SHOP-3'], ]); DB::connection('business_mirror')->table('ops_jst_order_item')->insert([ ['o_id' => 1001, 'sku_id' => 'SKU-1', 'i_id' => 'STYLE-1', 'shop_sku_id' => 'SP-1', 'shop_i_id' => 'SI-1'], @@ -82,6 +84,11 @@ class BillOffsetMirrorRepositoryTest extends TestCase $this->assertSame('STYLE-1', $result['data'][0]['style_code']); $this->assertSame(-20.0, $result['summary']['amount']); $this->assertSame('succeeded', $result['sync']['status']); + + $all = $this->repository->paginate([], 1, 10); + $this->assertSame(3, $all['total']); + $this->assertSame(5.25, $all['summary']['amount']); + $this->assertSame('SO-3', $all['data'][0]['online_order_no']); } public function test_it_rejects_unready_mirror(): void diff --git a/tests/Unit/EcommerceFinance/OrderDataMirrorRepositoryTest.php b/tests/Unit/EcommerceFinance/OrderDataMirrorRepositoryTest.php index f602b41e..fed58fee 100644 --- a/tests/Unit/EcommerceFinance/OrderDataMirrorRepositoryTest.php +++ b/tests/Unit/EcommerceFinance/OrderDataMirrorRepositoryTest.php @@ -76,6 +76,7 @@ class OrderDataMirrorRepositoryTest extends TestCase $this->assertSame(40.0, $row['product_cost']); $this->assertSame(1.0, $row['post_return_quantity']); $this->assertSame('https://item.jd.com/1001.html', $row['product_link']); + $this->assertNull($row['account_500112']); $this->assertNull($row['account_8001201']); } diff --git a/tests/Unit/EcommerceFinance/OrderDataRepositoryTest.php b/tests/Unit/EcommerceFinance/OrderDataRepositoryTest.php index 2e061c04..de6f9c2a 100644 --- a/tests/Unit/EcommerceFinance/OrderDataRepositoryTest.php +++ b/tests/Unit/EcommerceFinance/OrderDataRepositoryTest.php @@ -101,6 +101,7 @@ class OrderDataRepositoryTest extends TestCase $this->assertSame('https://item.jd.com/1001.html', $result['rows'][0]['product_link']); $this->assertSame('AF-1', $result['rows'][0]['after_sales_no']); $this->assertSame(1.0, $result['rows'][0]['post_return_quantity']); + $this->assertNull($result['rows'][0]['account_500112']); $this->assertNull($result['rows'][0]['account_8001201']); } -- 2.47.2