供应商对账:退货扣减确认展示全部退货行(每页 15 行 + 页码) #372

Merged
renshen merged 1 commits from feature/sumu-return-pagination into main 2026-10-17 10:05:09 +08:00
3 changed files with 84 additions and 4 deletions

View File

@ -207,9 +207,17 @@ class SupplierReconciliationPageData
usort($rows, static fn (array $a, array $b): int => $b['deduction'] <=> $a['deduction']);
// 全部退货行按金额从高到低分页展示(每页 15 行)。
$perPage = self::PER_PAGE;
$pages = max((int) ceil(count($rows) / $perPage), 1);
$page = min(max((int) request()->query('return_page', 1), 1), $pages);
return [
'supplier' => $supplier,
'rows' => array_slice($rows, 0, 15),
'rows' => array_slice($rows, ($page - 1) * $perPage, $perPage),
'page' => $page,
'pages' => $pages,
'per_page' => $perPage,
'total_rows' => count($returnRows),
'total_amount' => round($total, 2),
'confirmed_count' => $confirmedCount,

View File

@ -136,10 +136,11 @@
$pageCount = max((int) ceil($statementTotal / $perPage), 1);
$pageStart = max(1, min($rowsPage - 4, $pageCount - 8));
$pageEnd = min($pageCount, $pageStart + 8);
$pageUrl = fn (int $number): string => route('business.pages.show', [
$pageUrl = fn (int $number): string => route('business.pages.show', array_filter([
'section' => $section['slug'], 'page' => $page['slug'],
'supplier' => $selectedSupplier, 'rows_page' => $number,
]);
'return_page' => $returnPanel['page'] > 1 ? $returnPanel['page'] : null,
], static fn (mixed $value): bool => $value !== null && $value !== ''));
@endphp
<div class="sr-pagination">
<span>共 {{ number_format($statementTotal) }} 行,每页 {{ $perPage }} 行 · 第 {{ $rowsPage }} / {{ $pageCount }} 页</span>
@ -238,9 +239,46 @@
</div>
<p class="sr-hint">
列名取自《退货明细》原始表头(标记多标签、创建人、对账人、退货单备注等内部字段不展示),左右滑动查看全部。
退货共 {{ number_format($returnPanel['total_rows']) }} 行,上表展示金额最高的 {{ count($returnPanel['rows']) }} 行。
退货共 {{ number_format($returnPanel['total_rows']) }} 行,按扣减金额从高到低排列,每页 {{ $returnPanel['per_page'] }} 行(第 {{ $returnPanel['page'] }} / {{ $returnPanel['pages'] }} 页)。
金额列为空的行以预估金额参与扣减,与采购方记账口径一致。
</p>
@if ($returnPanel['pages'] > 1)
@php
$returnPageCount = $returnPanel['pages'];
$returnPageCurrent = $returnPanel['page'];
$returnPageStart = max(1, min($returnPageCurrent - 4, $returnPageCount - 8));
$returnPageEnd = min($returnPageCount, $returnPageStart + 8);
$returnPageUrl = fn (int $number): string => route('business.pages.show', array_filter([
'section' => $section['slug'],
'page' => $page['slug'],
'supplier' => $selectedSupplier,
'rows_page' => $rowsPage > 1 ? $rowsPage : null,
'return_page' => $number,
], static fn (mixed $value): bool => $value !== null && $value !== ''));
@endphp
<div class="sr-pagination">
<span>第 {{ $returnPageCurrent }} / {{ $returnPageCount }} 页(每页 {{ $returnPanel['per_page'] }} 行)</span>
@if ($returnPageCurrent > 1)
<a class="sr-button is-small" href="{{ $returnPageUrl($returnPageCurrent - 1) }}">上一页</a>
@endif
@if ($returnPageStart > 1)
<a class="sr-button is-small" href="{{ $returnPageUrl(1) }}">1</a>
@if ($returnPageStart > 2) <span>…</span> @endif
@endif
@for ($number = $returnPageStart; $number <= $returnPageEnd; $number++)
<a class="sr-button is-small {{ $number === $returnPageCurrent ? 'is-primary' : '' }}"
@if ($number === $returnPageCurrent) aria-current="page" @endif
href="{{ $returnPageUrl($number) }}">{{ $number }}</a>
@endfor
@if ($returnPageEnd < $returnPageCount)
@if ($returnPageEnd < $returnPageCount - 1) <span>…</span> @endif
<a class="sr-button is-small" href="{{ $returnPageUrl($returnPageCount) }}">{{ $returnPageCount }}</a>
@endif
@if ($returnPageCurrent < $returnPageCount)
<a class="sr-button is-small" href="{{ $returnPageUrl($returnPageCurrent + 1) }}">下一页</a>
@endif
</div>
@endif
<div class="sr-return-actions">
<form method="POST" action="{{ $returnConfirmAllUrl }}" class="sr-inline-form">
@csrf

View File

@ -161,6 +161,40 @@ class SupplierReconciliationTest extends FeatureTestCase
->assertDontSeeText('ST-01');
}
public function test_return_rows_show_all_rows_with_pagination(): void
{
$store = app(SupplierPayableOverrideStore::class);
$companyId = (int) $this->company->id;
for ($i = 1; $i <= 20; $i++) {
$store->save('final:supplier:return-reconciliation', sprintf('return:%02d', $i), [
'summary_month' => '2026-09', 'send_time' => '2026-09-18', 'supplier' => '晨丰',
'barcode' => sprintf('RT-%02d', $i), 'qty' => '1', 'unit_price' => (string) (100 + $i),
'amount' => (string) (100 + $i), 'warehouse' => '客退临时上架仓',
], $companyId, null);
}
$this->seedStatement('晨丰', [$this->statementRow('ZSJ-1', '128.00', '2', '256.00')]);
$pageUrl = fn (int $page): string => route('business.pages.show', [
'section' => 'supplier-reconciliation',
'page' => 'supplier-data',
'supplier' => '晨丰',
'return_page' => $page,
]);
$this->loginAs()->get($pageUrl(1))
->assertOk()
->assertSeeText('每页 15 行')
->assertSeeText('第 1 / 2 页')
->assertSeeText('RT-20')
->assertDontSeeText('RT-01');
$this->loginAs()->get($pageUrl(2))
->assertOk()
->assertSeeText('第 2 / 2 页')
->assertSeeText('RT-01')
->assertDontSeeText('RT-20');
}
public function test_return_rows_can_be_confirmed_disputed_and_confirmed_all(): void
{
$store = app(SupplierPayableOverrideStore::class);