diff --git a/modules/EcommerceFinance/View/ProcessDetailsPageData.php b/modules/EcommerceFinance/View/ProcessDetailsPageData.php new file mode 100644 index 00000000..4e644d5e --- /dev/null +++ b/modules/EcommerceFinance/View/ProcessDetailsPageData.php @@ -0,0 +1,86 @@ + */ + public function page(Request $request): array + { + $filters = $this->filters($request); + $page = max((int) $request->query('page', 1), 1); + $perPage = 50; + + try { + $result = $this->repository->paginate($filters, $page, $perPage); + $options = $this->repository->filterOptions(); + + return [ + 'processRows' => new LengthAwarePaginator( + $result['data'], + $result['total'], + $perPage, + $page, + ['path' => $request->url(), 'query' => $request->except('page')], + ), + 'filters' => $filters, + 'summary' => $result['summary'], + 'months' => $options['months'], + 'documentTypes' => $options['document_types'], + 'statuses' => $options['statuses'], + 'mirrorStatus' => $result['status'], + 'mirrorSyncedAt' => $result['last_synced_at'], + 'scope' => $result['scope'], + 'error' => null, + ]; + } catch (Throwable $exception) { + report($exception); + + return [ + 'processRows' => new LengthAwarePaginator([], 0, $perPage, $page, [ + 'path' => $request->url(), + 'query' => $request->except('page'), + ]), + 'filters' => $filters, + 'summary' => [ + 'rows' => 0, + 'approvals' => 0, + 'amount_total' => 0.0, + 'bank_amount_total' => 0.0, + ], + 'months' => [], + 'documentTypes' => [], + 'statuses' => [], + 'mirrorStatus' => 'unavailable', + 'mirrorSyncedAt' => null, + 'scope' => $this->repository->scope(), + 'error' => '流程明细镜像尚未完成导入,请稍后重试。', + ]; + } + } + + /** @return array */ + private function filters(Request $request): array + { + $month = trim((string) $request->query('month', '')); + $status = trim((string) $request->query('status', '')); + + return [ + 'month' => preg_match('/^\d{4}-\d{2}$/', $month) === 1 ? $month : '', + 'document_type' => mb_substr(trim((string) $request->query('document_type', '')), 0, 100), + 'status' => mb_substr($status, 0, 20), + 'business_id' => mb_substr(trim((string) $request->query('business_id', '')), 0, 32), + 'originator_name' => mb_substr(trim((string) $request->query('originator_name', '')), 0, 100), + 'keyword' => mb_substr(trim((string) $request->query('keyword', '')), 0, 100), + ]; + } +} diff --git a/resources/views/business/pages/financial-operations/process-details.blade.php b/resources/views/business/pages/financial-operations/process-details.blade.php index 2064d35f..7fda65f4 100644 --- a/resources/views/business/pages/financial-operations/process-details.blade.php +++ b/resources/views/business/pages/financial-operations/process-details.blade.php @@ -1,10 +1,17 @@ @php $processRows = $processRows ?? null; if (! $processRows instanceof \Illuminate\Contracts\Pagination\LengthAwarePaginator) { - $fallbackRows = $rows ?? null; - $processRows = $fallbackRows instanceof \Illuminate\Contracts\Pagination\LengthAwarePaginator - ? $fallbackRows - : new \Illuminate\Pagination\LengthAwarePaginator([], 0, 50); + $pageData = app(\Modules\EcommerceFinance\View\ProcessDetailsPageData::class)->page(request()); + $processRows = $pageData['processRows']; + $filters = $pageData['filters']; + $summary = $pageData['summary']; + $months = $pageData['months']; + $documentTypes = $pageData['documentTypes']; + $statuses = $pageData['statuses']; + $mirrorStatus = $pageData['mirrorStatus']; + $mirrorSyncedAt = $pageData['mirrorSyncedAt']; + $scope = $pageData['scope']; + $error = $pageData['error']; } $filters = $filters ?? []; $summary = $summary ?? []; diff --git a/tests/Unit/EcommerceFinance/ProcessDetailsPageDataTest.php b/tests/Unit/EcommerceFinance/ProcessDetailsPageDataTest.php new file mode 100644 index 00000000..c5adf0a6 --- /dev/null +++ b/tests/Unit/EcommerceFinance/ProcessDetailsPageDataTest.php @@ -0,0 +1,62 @@ + '202610241052000241951', + 'line_no' => 1, + 'status' => '审批中', + ]; + + $repository = $this->createMock(DingProcessDetailMirrorRepository::class); + $repository->expects($this->once()) + ->method('paginate') + ->with($this->callback(static fn (array $filters): bool => $filters['month'] === '2026-10'), 2, 50) + ->willReturn([ + 'data' => [$row], + 'total' => 11331, + 'summary' => [ + 'rows' => 11331, + 'approvals' => 4775, + 'amount_total' => 225953332.98, + 'bank_amount_total' => 225862410.66, + ], + 'status' => 'succeeded', + 'last_synced_at' => '2026-10-26 16:55:11', + 'scope' => 'personal_permission', + ]); + $repository->expects($this->once()) + ->method('filterOptions') + ->willReturn([ + 'months' => ['2026-10'], + 'document_types' => ['种菜核销/种菜报销'], + 'statuses' => ['审批中'], + ]); + + $data = (new ProcessDetailsPageData($repository))->page(Request::create( + '/1/workspace/financial-operations/process-details', + 'GET', + ['month' => '2026-10', 'page' => 2], + )); + + $this->assertInstanceOf(LengthAwarePaginator::class, $data['processRows']); + $this->assertSame(11331, $data['processRows']->total()); + $this->assertSame(50, $data['processRows']->perPage()); + $this->assertSame(2, $data['processRows']->currentPage()); + $this->assertSame($row, $data['processRows']->items()[0]); + $this->assertSame('succeeded', $data['mirrorStatus']); + $this->assertSame(11331, $data['summary']['rows']); + $this->assertSame(['2026-10'], $data['months']); + $this->assertNull($data['error']); + } +}