CaiWuXiTong/tests/Feature/Business/SupplierBookkeepingPageTest.php
limeng 13d54d0c76 fix(厂家记账): 配置表中没有的供应商按可扣款处理
财务更正口径:厂家记账配置表中没有的供应商(含配置不在生效期内)视同正常记账,作为厂家扣款项;
取消“待配置”判定。工单未带供应商、或多供应商判定不一致的仍为“待确认”,不计入扣款。

涉及:扣款金额汇总口径;无数据库变更。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JouFR6TJ7vGscRJanYScEo
2026-10-19 11:19:27 +08:00

132 lines
6.6 KiB
PHP

<?php
namespace Tests\Feature\Business;
use App\Models\Auth\Permission;
use Modules\EcommerceFinance\Repositories\SupplierBookkeepingWorkOrderRepository;
use Tests\Feature\FeatureTestCase;
class SupplierBookkeepingPageTest extends FeatureTestCase
{
private function row(array $patch = []): array
{
$row = array_fill_keys(array_keys(\Modules\EcommerceFinance\View\SupplierBookkeepingPageData::COLUMNS), '');
return array_replace($row, [
'started_at' => '2026-09-05 10:00:00', 'work_order_no' => 'GD614939067', 'initiator' => '梦得',
'bookkeeping_reason' => '厂家记账/孔位错误', 'reason_level_1' => '厂家记账', 'reason_level_2' => '孔位错误',
'bookkeeping_type' => '补偿款项', 'amount' => '382.15', 'actual_paid_amount' => '399.41',
'online_order_no' => '5127787476014026744', 'shop_name' => '淘宝-亿家达家居', 'status' => '待处理',
'supplier' => '彩虹', 'product_code' => "DNZ0134101N24V01\nDNZ0134102N24V01",
'attachment' => 'https://jgd-static.example/a.png', 'work_order_type' => '记账',
], $patch);
}
private function mockRepository(array $rows, string $code = 'ready'): void
{
$repository = \Mockery::mock(SupplierBookkeepingWorkOrderRepository::class);
$repository->shouldReceive('syncStatus')->andReturn(['code' => $code, 'last_succeeded_at' => '2026-10-18 21:00:00']);
$repository->shouldReceive('rows')->andReturn($rows);
$this->app->instance(SupplierBookkeepingWorkOrderRepository::class, $repository);
$this->user->attachPermission(Permission::where('name', 'read-admin-panel')->firstOrFail());
}
private function url(array $query = []): string
{
return route('business.pages.show', [
'company_id' => $this->company->id, 'section' => 'supplier-payables', 'page' => 'manufacturer-bookkeeping',
]) . ($query ? '?' . http_build_query($query) : '');
}
public function test_page_renders_rows_totals_and_filters(): void
{
$this->mockRepository([
$this->row(),
$this->row(['work_order_no' => 'GD-WAREHOUSE', 'bookkeeping_reason' => '仓库记账/退货运费', 'reason_level_1' => '仓库记账', 'amount' => '10.05', 'bookkeeping_type' => '运费损耗']),
]);
$this->loginAs()->get($this->url())
->assertOk()
->assertSee('厂家记账')
->assertSee('GD614939067')
->assertSee('GD-WAREHOUSE')
->assertSee('392.20')
->assertSee('运费损耗')
->assertSee('附件1');
$this->loginAs()->get($this->url(['reason' => '仓库记账']))
->assertOk()
->assertSee('GD-WAREHOUSE')
->assertDontSee('GD614939067')
->assertSee('10.05');
$this->withExceptionHandling()->loginAs()->get($this->url(['reason' => 'DROP TABLE']))->assertStatus(422);
}
public function test_page_explains_pending_initial_sync(): void
{
$this->mockRepository([], 'initializing');
$this->loginAs()->get($this->url())
->assertOk()
->assertSee('尚未完成首次同步')
->assertSee('当前为空不代表没有记账工单');
}
public function test_export_uses_same_filters_and_selected_columns(): void
{
$this->mockRepository([$this->row(), $this->row(['work_order_no' => 'GD-2', 'status' => '已完成'])]);
$response = $this->loginAs()->get(route('business.supplier-bookkeeping.export', [
'company_id' => $this->company->id, 'status' => '待处理', 'columns' => 'work_order_no,online_order_no,amount',
]));
$response->assertOk();
$csv = $response->streamedContent();
$this->assertStringContainsString("工单编号,线上订单号,记账金额", $csv);
$this->assertStringContainsString("GD614939067,'5127787476014026744,382.15", $csv);
$this->assertStringNotContainsString('GD-2', $csv);
}
public function test_seeded_configs_drive_deduction_judgement_totals_and_filter(): void
{
$this->mockRepository([
$this->row(),
$this->row(['work_order_no' => 'GD-NORMAL', 'supplier' => '鑫呈', 'amount' => '100.00']),
$this->row(['work_order_no' => 'GD-NONE', 'supplier' => '尊享', 'amount' => '50.00']),
$this->row(['work_order_no' => 'GD-DROP-OTHER', 'supplier' => '曹县洪耀', 'amount' => '30.00']),
$this->row(['work_order_no' => 'GD-DROP-WRONG', 'supplier' => '曹县洪耀', 'amount' => '20.50', 'reason_level_1' => '仓库记账',
'reason_level_2' => '仓库发错货(面单照片,实物照片,条形码照片)', 'bookkeeping_reason' => '仓库记账/仓库发错货(面单照片,实物照片,条形码照片)', 'shipping_warehouse' => '曹县洪耀代发仓']),
$this->row(['work_order_no' => 'GD-MAIN-WRONG', 'supplier' => '曹县洪耀', 'amount' => '8.00', 'reason_level_1' => '仓库记账',
'reason_level_2' => '仓库发错货(面单照片,实物照片,条形码照片)', 'bookkeeping_reason' => '仓库记账/仓库发错货(面单照片,实物照片,条形码照片)', 'shipping_warehouse' => '常州主仓']),
]);
$this->loginAs()->get($this->url())
->assertOk()
->assertSee('厂家扣款判定')
->assertSee('仅代发仓发错货记账')
->assertSee('502.65')
->assertSee('供应商不在配置表,按正常记账扣款');
$this->loginAs()->get($this->url(['deduction' => '扣款']))
->assertOk()
->assertSee('GD-NORMAL')
->assertSee('GD-DROP-WRONG')
->assertSee('GD614939067')
->assertDontSee('GD-NONE')
->assertDontSee('GD-DROP-OTHER')
->assertDontSee('GD-MAIN-WRONG');
$this->loginAs()->get($this->url(['deduction' => '不扣款']))->assertOk()->assertSee('GD-NONE')->assertDontSee('GD614939067');
$csv = $this->loginAs()->get(route('business.supplier-bookkeeping.export', [
'company_id' => $this->company->id, 'deduction' => '扣款', 'columns' => 'work_order_no,deduction_status,deduction_basis',
]))->assertOk()->streamedContent();
$this->assertStringContainsString('工单编号,厂家扣款判定,判定说明', $csv);
$this->assertStringContainsString('GD-DROP-WRONG,扣款,代发仓发错货,记厂家扣款', $csv);
$this->assertStringNotContainsString('GD-NONE', $csv);
$this->withExceptionHandling()->loginAs()->get($this->url(['deduction' => 'x']))->assertStatus(422);
}
}