CaiWuXiTong/tests/Unit/EcommerceFinance/SupplierBookkeepingDeductionRuleTest.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

88 lines
5.1 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace Tests\Unit\EcommerceFinance;
use InvalidArgumentException;
use Modules\EcommerceFinance\Services\SupplierBookkeepingDeductionRule as Rule;
use PHPUnit\Framework\TestCase;
require_once dirname(__DIR__, 3) . '/modules/EcommerceFinance/Services/SupplierBookkeepingDeductionRule.php';
class SupplierBookkeepingDeductionRuleTest extends TestCase
{
public function test_parses_every_rule_text_in_finance_sheet(): void
{
$this->assertSame(['mode' => Rule::MODE_NONE, 'effective_from' => null, 'effective_to' => null], Rule::parseRuleText('不记账'));
$this->assertSame(Rule::MODE_NORMAL, Rule::parseRuleText('正常记账')['mode']);
$this->assertSame(Rule::MODE_DROPSHIP_WRONG, Rule::parseRuleText('代发仓发货错需记账,其他原因均不记账')['mode']);
$this->assertSame(Rule::MODE_DROPSHIP_WRONG, Rule::parseRuleText('厂家暂未出货,后期若建立代发仓,发货错需记账,其他原因均不记账')['mode']);
$this->assertSame(['mode' => Rule::MODE_NONE, 'effective_from' => '2025-03-01', 'effective_to' => '2026-02-28'], Rule::parseRuleText('不记账(2025.3月-2026.2月)'));
$this->assertSame(['mode' => Rule::MODE_NONE, 'effective_from' => '2025-03-01', 'effective_to' => '2027-12-30'], Rule::parseRuleText('不记账(2025.3月-2027.12.30)'));
$this->assertSame(Rule::MODE_DROPSHIP_WRONG, Rule::parseRuleText('仅代发仓发错货记账')['mode']);
}
public function test_rejects_unknown_rule_text(): void
{
$this->expectException(InvalidArgumentException::class);
Rule::parseRuleText('看情况');
}
private function row(array $patch = []): array
{
return array_replace([
'started_at' => '2026-09-05 10:00:00', 'reason_level_1' => '厂家记账', 'reason_level_2' => '孔位错误',
'shipping_warehouse' => '常州主仓', 'supplier' => '甲厂',
], $patch);
}
private function configs(): array
{
return [
'甲厂' => ['mode' => Rule::MODE_NORMAL, 'effective_from' => null, 'effective_to' => null],
'乙厂' => ['mode' => Rule::MODE_DROPSHIP_WRONG, 'effective_from' => null, 'effective_to' => null],
'丙厂' => ['mode' => Rule::MODE_NONE, 'effective_from' => null, 'effective_to' => null],
'丁厂' => ['mode' => Rule::MODE_NONE, 'effective_from' => '2025-03-01', 'effective_to' => '2026-02-28'],
];
}
private function judge(array $patch): string
{
return Rule::decide($this->row($patch), $this->configs())['deduction_status'];
}
public function test_supplier_reasons_follow_supplier_config(): void
{
$this->assertSame(Rule::STATUS_DEDUCT, $this->judge([]));
$this->assertSame(Rule::STATUS_SKIP, $this->judge(['supplier' => '乙厂']));
$this->assertSame(Rule::STATUS_SKIP, $this->judge(['supplier' => '丙厂']));
// 配置表中没有的供应商视同正常记账,可扣款。
$this->assertSame(Rule::STATUS_DEDUCT, $this->judge(['supplier' => '未知厂']));
$this->assertSame(Rule::STATUS_REVIEW, $this->judge(['supplier' => '']));
// 限期不记账:期外视同不在配置表,可扣款。
$this->assertSame(Rule::STATUS_DEDUCT, $this->judge(['supplier' => '丁厂']));
$this->assertSame(Rule::STATUS_SKIP, $this->judge(['supplier' => '丁厂', 'started_at' => '2026-02-28 23:00:00']));
}
public function test_warehouse_reasons_only_deduct_dropship_wrong_shipment(): void
{
$wrong = ['reason_level_1' => '仓库记账', 'reason_level_2' => '仓库发错货(面单照片,实物照片,条形码照片)', 'shipping_warehouse' => '曹县洪耀代发仓'];
$this->assertSame(Rule::STATUS_DEDUCT, $this->judge($wrong + ['supplier' => '乙厂']));
$this->assertSame(Rule::STATUS_DEDUCT, $this->judge($wrong));
$this->assertSame(Rule::STATUS_SKIP, $this->judge($wrong + ['supplier' => '丙厂']));
$this->assertSame(Rule::STATUS_DEDUCT, $this->judge($wrong + ['supplier' => '未知厂']));
// 非代发仓、或代发仓的其他仓库记账原因:一律不作为厂家扣款项,无需配置。
$this->assertSame(Rule::STATUS_SKIP, $this->judge(['shipping_warehouse' => '常州主仓'] + $wrong + ['supplier' => '乙厂']));
$this->assertSame(Rule::STATUS_SKIP, $this->judge(['reason_level_2' => '仓库双面单'] + $wrong + ['supplier' => '乙厂']));
$this->assertSame(Rule::STATUS_SKIP, $this->judge(['reason_level_2' => '退货运费'] + $wrong + ['supplier' => '未知厂']));
}
public function test_multiple_suppliers_need_review_when_outcomes_differ(): void
{
$this->assertSame(Rule::STATUS_DEDUCT, $this->judge(['supplier' => "甲厂\n甲厂"]));
$result = Rule::decide($this->row(['supplier' => "甲厂\n丙厂"]), $this->configs());
$this->assertSame(Rule::STATUS_REVIEW, $result['deduction_status']);
$this->assertStringContainsString('甲厂:扣款', $result['deduction_basis']);
$this->assertSame("正常记账\n不记账", $result['supplier_config']);
}
}