CaiWuXiTong/tests/Unit/AccessoryReshipMatcherTest.php

63 lines
3.7 KiB
PHP

<?php
namespace Tests\Unit;
use Modules\EcommerceFinance\Services\AccessoryReshipMatcher;
use PHPUnit\Framework\TestCase;
require_once dirname(__DIR__, 2) . '/modules/EcommerceFinance/Services/AccessoryReshipMatcher.php';
class AccessoryReshipMatcherTest extends TestCase
{
private function original(array $changes = []): array
{
return array_replace(['trade_no' => 'T001', 'warehouse_name' => '成品仓', 'barcode' => 'GBGJ-SJ038024N1410V02,OTHER-SKU', 'express_no' => 'SF001', 'express_name1' => '首发快递', 'ship_time' => '2026-08-01 12:00:00'], $changes);
}
private function accessory(array $changes = []): array
{
return array_replace(['trade_no' => 'T001', 'barcode' => 'GBGJ-SJ038024N1410V02-10,OTHER-SKU-2', 'freight' => '12.30'], $changes);
}
public function test_first_accessory_barcode_and_last_suffix_only(): void
{
$this->assertSame('GBGJ-SJ038024N1410V02', AccessoryReshipMatcher::barcode('GBGJ-SJ038024N1410V02-10,GBGJ-SJ038024N1410V02-2,GBGJ-SJ038024N1410V02-7'));
$this->assertSame('ABC', AccessoryReshipMatcher::barcode('ABC'));
$this->assertSame('', AccessoryReshipMatcher::barcode(''));
}
public function test_exact_trade_and_split_original_barcodes_without_normalizing_original(): void
{
$matcher = new AccessoryReshipMatcher;
$result = $matcher->match([$this->accessory(), $this->accessory(['barcode' => 'OTHER-SKU-2']), $this->accessory(['trade_no' => 'T002'])], [$this->original()]);
$this->assertSame(['matched', 'matched', 'unmatched'], array_column($result, 'status'));
$this->assertSame(1230, $result[0]['deduction_cents']);
$this->assertSame('2026-08', $result[0]['matches'][0]['month']);
$this->assertSame('unmatched', $matcher->match([$this->accessory()], [$this->original(['barcode' => 'GBGJ-SJ038024N1410V02-10'])])[0]['status']);
}
public function test_blank_waybill_accessory_warehouse_and_empty_keys_do_not_qualify(): void
{
$matcher = new AccessoryReshipMatcher;
$result = $matcher->match([$this->accessory(), $this->accessory(['trade_no' => '']), $this->accessory(['barcode' => ''])], [$this->original(['express_no' => ' ']), $this->original(['warehouse_name' => AccessoryReshipMatcher::WAREHOUSE])]);
$this->assertSame(['unmatched', 'unmatched', 'unmatched'], array_column($result, 'status'));
$this->assertSame([0, 0, 0], array_column($result, 'deduction_cents'));
}
public function test_multiple_matches_keep_one_deduction_and_deduplicate_same_waybill(): void
{
$matcher = new AccessoryReshipMatcher;
$originals = [$this->original(), $this->original(), $this->original(['express_no' => 'YTO002', 'express_name1' => '另一快递', 'ship_time' => '2026-09-01'])];
$result = $matcher->match([$this->accessory()], $originals);
$this->assertCount(1, $result);
$this->assertCount(2, $result[0]['matches']);
$this->assertSame(1230, $result[0]['deduction_cents']);
$this->assertSame($result, $matcher->match([$this->accessory()], $originals));
}
public function test_invalid_amount_stays_matched_but_cannot_supply_amount(): void
{
foreach ([null, '', '-2.00', 'abc'] as $value) {
$row = (new AccessoryReshipMatcher)->match([$this->accessory(['freight' => $value])], [$this->original()])[0];
$this->assertSame('matched', $row['status']);
$this->assertNull($row['deduction_cents']);
}
$this->assertSame(1230, AccessoryReshipMatcher::cents('12.3000'));
$this->assertSame(1240, AccessoryReshipMatcher::cents('12.395'));
$this->assertSame(0, AccessoryReshipMatcher::cents('0.00'));
}
}