CaiWuXiTong/tests/Unit/EcommerceFinance/ProcessDetailsPageDataTest.php
yueyang 26c86df915 fix: 修正OA拒绝状态并支持打款日期范围 (#704)
审批拒绝优先于流程完成;打款时间改为开始至结算日期范围。
2026-10-27 19:23:46 +08:00

229 lines
8.9 KiB
PHP

<?php
namespace Tests\Unit\EcommerceFinance;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
use Modules\EcommerceFinance\Repositories\DingProcessDetailMirrorRepository;
use Modules\EcommerceFinance\View\ProcessDetailsPageData;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
class ProcessDetailsPageDataTest extends TestCase
{
public function test_embedded_process_page_uses_content_only_without_nested_admin_layout(): void
{
$root = dirname(__DIR__, 3);
$page = (string) file_get_contents(
$root . '/resources/views/business/pages/financial-operations/process-details.blade.php',
);
$content = (string) file_get_contents(
$root . '/resources/views/business/pages/financial-operations/process-details-content.blade.php',
);
$this->assertStringContainsString('$processDetailsEmbedded', $page);
$this->assertStringContainsString(
"@include('business.pages.financial-operations.process-details-content')",
$page,
);
$this->assertStringNotContainsString('<x-layouts.admin>', $content);
$this->assertStringContainsString('class="process-details-page"', $content);
$this->assertStringContainsString('class="process-details-table-card"', $content);
$this->assertStringContainsString('class="process-details-pagination"', $content);
$this->assertStringContainsString('class="process-details-page-jump"', $content);
$this->assertStringContainsString('$pageUrl ??=', $content);
$this->assertStringContainsString('$exportUrl ??=', $content);
$this->assertStringContainsString('$statusClass ??=', $content);
$this->assertStringNotContainsString('$processRows->links()', $content);
}
public function test_page_data_contains_real_paginator_filters_and_summary(): void
{
$row = (object) [
'business_id' => '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['paid_start'] === '2026-10-20'
&& $filters['paid_end'] === '2026-10-24'
&& $filters['payment_state'] === '已付款'
), 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',
'sync_stale' => true,
'sync_stale_after_minutes' => 15,
'scope' => 'personal_permission',
]);
$repository->expects($this->once())
->method('filterOptions')
->willReturn([
'document_types' => ['种菜核销/种菜报销'],
'statuses' => ['审批中'],
'payment_states' => [
'待付款',
'已付款',
'付款待核实',
'不涉及付款',
],
]);
$data = (new ProcessDetailsPageData($repository))->page(Request::create(
'/1/workspace/process-data/oa-process',
'GET',
[
'paid_start' => '2026-10-20',
'paid_end' => '2026-10-24',
'payment_state' => '出纳已打款',
'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-20', $data['filters']['paid_start']);
$this->assertSame('2026-10-24', $data['filters']['paid_end']);
$this->assertSame('已付款', $data['filters']['payment_state']);
$this->assertSame(
[
'待付款',
'已付款',
'付款待核实',
'不涉及付款',
],
$data['paymentStates'],
);
$this->assertTrue($data['mirrorStale']);
$this->assertSame(15, $data['mirrorStaleAfterMinutes']);
$this->assertArrayNotHasKey('months', $data);
$this->assertNull($data['error']);
}
public function test_paid_date_range_accepts_legacy_date_and_normalizes_reversed_range(): void
{
$this->assertSame(
['2026-10-24', '2026-10-24'],
ProcessDetailsPageData::normalizePaidDateRange('', '', '2026-10-24'),
);
$this->assertSame(
['2026-10-20', '2026-10-24'],
ProcessDetailsPageData::normalizePaidDateRange('2026-10-24', '2026-10-20'),
);
$this->assertSame(
['', ''],
ProcessDetailsPageData::normalizePaidDateRange('2026-02-30', 'invalid'),
);
}
public function test_unavailable_payment_state_filter_is_cleared_before_querying(): void
{
$repository = $this->createMock(DingProcessDetailMirrorRepository::class);
$repository->expects($this->once())
->method('filterOptions')
->with($this->callback(static fn (array $filters): bool =>
$filters['status'] === '已完成'
&& $filters['payment_state'] === '付款待核实'
))
->willReturn([
'document_types' => ['公摊日常报销'],
'statuses' => ['已完成'],
'payment_states' => ['已付款'],
]);
$repository->expects($this->once())
->method('paginate')
->with($this->callback(static fn (array $filters): bool =>
$filters['status'] === '已完成'
&& $filters['payment_state'] === ''
), 1, 50)
->willReturn([
'data' => [],
'total' => 51,
'summary' => [
'rows' => 51,
'approvals' => 0,
'amount_total' => 0,
'bank_amount_total' => 0,
],
'status' => 'succeeded',
'last_synced_at' => null,
'scope' => 'personal_permission',
]);
$data = (new ProcessDetailsPageData($repository))->page(Request::create(
'/1/workspace/process-data/oa-process',
'GET',
['status' => '已完成', 'payment_state' => '付款待核实'],
));
$this->assertSame('', $data['filters']['payment_state']);
$this->assertSame(['已付款'], $data['paymentStates']);
$this->assertStringNotContainsString('payment_state', $data['processRows']->url(2));
}
#[DataProvider('perPageProvider')]
public function test_page_size_only_accepts_supported_options(mixed $requested, int $expected): void
{
$repository = $this->createMock(DingProcessDetailMirrorRepository::class);
$repository->expects($this->once())
->method('paginate')
->with($this->isType('array'), 1, $expected)
->willReturn([
'data' => [],
'total' => 0,
'summary' => [
'rows' => 0,
'approvals' => 0,
'amount_total' => 0,
'bank_amount_total' => 0,
],
'status' => 'succeeded',
'last_synced_at' => null,
'scope' => 'personal_permission',
]);
$repository->expects($this->once())
->method('filterOptions')
->willReturn([
'document_types' => [],
'statuses' => [],
'payment_states' => [],
]);
$data = (new ProcessDetailsPageData($repository))->page(Request::create(
'/1/workspace/process-data/oa-process',
'GET',
['per_page' => $requested],
));
$this->assertSame($expected, $data['processRows']->perPage());
}
/** @return array<string,array{mixed,int}> */
public static function perPageProvider(): array
{
return [
'50 条' => ['50', 50],
'100 条' => ['100', 100],
'200 条' => ['200', 200],
'非法值回退' => ['500', 50],
];
}
}