176 lines
9.7 KiB
PHP
176 lines
9.7 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', 'actual_paid_amount' => '40.00', '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);
|
||
}
|
||
|
||
public function test_small_compensation_zeroes_page_totals_and_exports_with_original_amount_and_note(): void
|
||
{
|
||
$this->mockRepository([
|
||
$this->row(['work_order_no' => 'GD-SMALL', 'amount' => '30.00', 'buyer_paid_amount' => '100', 'remark' => '原备注']),
|
||
$this->row(['work_order_no' => 'GD-EQUAL-RATIO', 'amount' => '40.00', 'buyer_paid_amount' => '100', 'actual_paid_amount' => '100.00']),
|
||
$this->row(['work_order_no' => 'GD-EQUAL-LIMIT', 'amount' => '50.00', 'buyer_paid_amount' => '200']),
|
||
]);
|
||
$response = $this->loginAs()->get($this->url())->assertOk();
|
||
$data = app(\Modules\EcommerceFinance\View\SupplierBookkeepingPageData::class)->page();
|
||
$summary = $data['bookkeepingSummary'];
|
||
$this->assertSame(9000, $summary['amount_cents']);
|
||
$this->assertSame(9000, $summary['deduction_cents']);
|
||
$this->assertSame(2, $summary['deduction_count']);
|
||
$row = $data['bookkeepingRows']->getCollection()->firstWhere('work_order_no', 'GD-SMALL');
|
||
$this->assertSame('0.00', $row['amount']);
|
||
$this->assertSame('30.00', $row['original_amount']);
|
||
$this->assertSame("原备注\n小于50且小于0.4,记账改0", $row['remark']);
|
||
$response->assertSee('原记账金额')->assertSee('小于50且小于0.4,记账改0');
|
||
$this->get($this->url(['deduction' => '扣款']))->assertOk()->assertDontSee('GD-SMALL')->assertSee('GD-EQUAL-RATIO');
|
||
$this->get($this->url(['deduction' => '不扣款']))->assertOk()->assertSee('GD-SMALL')->assertDontSee('GD-EQUAL-RATIO');
|
||
$csv = $this->get(route('business.supplier-bookkeeping.export', [
|
||
'company_id' => $this->company->id, 'columns' => 'work_order_no,amount,original_amount,remark',
|
||
]))->assertOk()->streamedContent();
|
||
$this->assertStringContainsString('GD-SMALL,0.00,30.00,', $csv);
|
||
$this->assertStringContainsString('小于50且小于0.4,记账改0', $csv);
|
||
}
|
||
|
||
public function test_second_round_zeroes_by_order_paid_when_buyer_paid_ratio_does_not_hit(): void
|
||
{
|
||
$this->mockRepository([
|
||
$this->row(['work_order_no' => 'GD-ROUND-TWO', 'amount' => '30.00', 'buyer_paid_amount' => '50.00', 'actual_paid_amount' => '100.00']),
|
||
]);
|
||
$this->loginAs()->get($this->url())->assertOk()->assertSee('GD-ROUND-TWO')->assertSee('小于50且小于0.4,记账改0');
|
||
$data = app(\Modules\EcommerceFinance\View\SupplierBookkeepingPageData::class)->page();
|
||
$this->assertSame(0, $data['bookkeepingSummary']['deduction_cents']);
|
||
$this->assertSame(0, $data['bookkeepingSummary']['amount_cents']);
|
||
$this->get($this->url(['deduction' => '扣款']))->assertOk()->assertDontSee('GD-ROUND-TWO');
|
||
$csv = $this->get(route('business.supplier-bookkeeping.export', [
|
||
'company_id' => $this->company->id, 'deduction' => '不扣款',
|
||
'columns' => 'work_order_no,amount,original_amount,remark',
|
||
]))->assertOk()->streamedContent();
|
||
$this->assertStringContainsString('GD-ROUND-TWO,0.00,30.00,', $csv);
|
||
}
|
||
}
|