CaiWuXiTong/tests/Unit/StoreReceiptProductCostLineTest.php

217 lines
8.3 KiB
PHP

<?php
namespace Tests\Unit;
use App\Business\StoreReceiptPlatformSkuMapper;
use App\Console\Commands\SyncStoreReceiptProductCost;
use PHPUnit\Framework\TestCase;
use ReflectionMethod;
class StoreReceiptProductCostLineTest extends TestCase
{
public function test_platform_placeholder_is_removed_when_internal_sku_exists(): void
{
[$lines, $placeholders, $bundles] = $this->costLines([
$this->row('platform', '955859844397', '3767501840732782900', 20, 2800),
$this->row('internal', 'DSG005016N11V01', '3767501840732782900', 20, 2800),
]);
$this->assertSame(1, $placeholders);
$this->assertSame(0, $bundles);
$this->assertSame('DSG005016N11V01', $lines[0]['sku']);
$this->assertSame(20.0, $lines[0]['qty']);
}
public function test_bundle_parent_is_removed_but_component_remains(): void
{
[$lines, $placeholders, $bundles] = $this->costLines([
$this->row('bundle-parent', '运营组合套装12994', '3832980288011632985', 2, 696),
$this->row(
'bundle-child',
'SJ038017N1410V02',
'3832980288011632985',
2,
625.26,
'运营组合套装12994',
),
]);
$this->assertSame(0, $placeholders);
$this->assertSame(1, $bundles);
$this->assertSame('SJ038017N1410V02', $lines[0]['sku']);
$this->assertSame(2.0, $lines[0]['qty']);
}
public function test_plus_parent_is_removed_when_component_amounts_match(): void
{
[$lines, $placeholders, $bundles, $plusParents] = $this->costLines([
$this->row('plus-parent', 'GBGJ-A+V01+GBGJ-B+V01', '993830851777', 1, 648.06),
$this->row('plus-child-a', 'GBGJ-AV01', '993830851777', 1, 450.03),
$this->row('plus-child-b', 'GBGJ-BV01', '993830851777', 1, 198.03),
]);
$this->assertSame(0, $placeholders);
$this->assertSame(0, $bundles);
$this->assertSame(1, $plusParents);
$this->assertSame(['GBGJ-AV01', 'GBGJ-BV01'], array_column($lines, 'sku'));
}
public function test_plus_parent_remains_when_component_amounts_do_not_match(): void
{
[$lines, $placeholders, $bundles, $plusParents] = $this->costLines([
$this->row('plus-parent', 'GBGJ-A+V01+GBGJ-B+V01', '993830851777', 1, 1142),
$this->row('plus-child-a', 'GBGJ-AV01', '993830851777', 1, 255.20),
$this->row('plus-child-b', 'GBGJ-BV01', '993830851777', 1, 328.56),
]);
$this->assertSame(0, $placeholders);
$this->assertSame(0, $bundles);
$this->assertSame(0, $plusParents);
$this->assertContains('GBGJ-A+V01+GBGJ-B+V01', array_column($lines, 'sku'));
}
public function test_non_numeric_variant_parent_is_removed_when_quantity_and_amount_match(): void
{
[$lines, $placeholders, $bundles, $plusParents, $variantParents] = $this->costLines([
$this->row('variant-parent', 'TESTP001', '3767501840732782900', 1, 91),
$this->row('variant-child', 'TESTP001N1150V01', '3767501840732782900', 1, 91),
]);
$this->assertSame(0, $placeholders);
$this->assertSame(0, $bundles);
$this->assertSame(0, $plusParents);
$this->assertSame(1, $variantParents);
$this->assertSame(['TESTP001N1150V01'], array_column($lines, 'sku'));
}
public function test_non_numeric_variant_parent_remains_when_amounts_do_not_match(): void
{
[$lines, , , , $variantParents] = $this->costLines([
$this->row('variant-parent', 'TESTP001', '3767501840732782900', 1, 91),
$this->row('variant-child', 'TESTP001N1150V01', '3767501840732782900', 1, 90),
]);
$this->assertSame(0, $variantParents);
$this->assertContains('TESTP001', array_column($lines, 'sku'));
$this->assertContains('TESTP001N1150V01', array_column($lines, 'sku'));
}
public function test_non_numeric_variant_parent_does_not_cross_platform_item_groups(): void
{
[$lines, , , , $variantParents] = $this->costLines([
$this->row('variant-parent', 'TESTP001', '3767501840732782900', 1, 91),
$this->row('variant-child', 'TESTP001N1150V01', '3767501840732782901', 1, 91),
]);
$this->assertSame(0, $variantParents);
$this->assertContains('TESTP001', array_column($lines, 'sku'));
$this->assertContains('TESTP001N1150V01', array_column($lines, 'sku'));
}
public function test_unique_platform_sku_is_replaced_after_line_filtering(): void
{
[$lines] = $this->costLines([
$this->row(
'platform',
'958530694526',
'3768947181063635112',
1,
93.25,
),
]);
$mapper = new StoreReceiptPlatformSkuMapper([
[
'shop_sku_id' => '3533103677164802',
'shop_i_id' => '3768947181063635112',
'sku_id' => 'SG006367N1028V01',
'i_id' => 'SG0063',
'properties_value' => '经典北美黑胡桃色',
],
]);
$command = new SyncStoreReceiptProductCost();
$method = new ReflectionMethod($command, 'mapPlatformSkus');
$method->setAccessible(true);
$result = $method->invoke($command, $lines, $mapper);
$this->assertSame(1, $result['auto_replaced_rows']);
$this->assertSame('SG006367N1028V01', $result['lines'][0]['sku']);
$this->assertSame('958530694526', $result['lines'][0]['original_platform_sku']);
$this->assertSame('unique', $result['lines'][0]['platform_mapping_status']);
}
public function test_yunfei_and_bcj_are_excluded_globally_and_from_bundle_components(): void
{
$command = new SyncStoreReceiptProductCost();
$constant = (new \ReflectionClass($command))->getReflectionConstant('EXCLUDED_SKUS');
$excludedSkus = $constant->getValue();
$this->assertContains('YUNFEI', $excludedSkus);
$this->assertContains('BCJ', $excludedSkus);
$method = new ReflectionMethod($command, 'expandComboSku');
$method->setAccessible(true);
$components = $method->invoke(
null,
'MKH-YUNFEI-1-BCJ-1-SG006367N1028V01-2',
3.0,
);
$this->assertSame([['SG006367N1028V01', 6.0, true]], $components);
}
public function test_priced_line_always_calculates_cost_without_unit_mismatch_override(): void
{
$command = new SyncStoreReceiptProductCost();
$method = new ReflectionMethod($command, 'calculateLineCost');
$method->setAccessible(true);
$result = $method->invoke($command, 9524.0, 58.0);
$this->assertSame(9524.0, $result['quantity']);
$this->assertSame(58.0, $result['unit_price']);
$this->assertSame(552392.0, $result['cost']);
}
/** @return array{0:list<array<string,mixed>>,1:int,2:int,3:int,4:int} */
private function costLines(array $rows): array
{
$command = new SyncStoreReceiptProductCost();
$method = new ReflectionMethod($command, 'costLines');
$method->setAccessible(true);
$placeholders = 0;
$bundles = 0;
$plusParents = 0;
$variantParents = 0;
$lines = $method->invokeArgs($command, [$rows, &$placeholders, &$bundles, &$plusParents, &$variantParents]);
return [$lines, $placeholders, $bundles, $plusParents, $variantParents];
}
/** @return array<string,mixed> */
private function row(
string $rowKey,
string $sku,
string $shopItemId,
float $quantity,
float $amount,
string $bundleParent = '',
): array {
return [
'source' => 'jst',
'sku' => $sku,
'qty' => $quantity,
'amount' => $amount,
'warehouse' => '简尚-新苏北仓',
'o_id' => '8986587',
'parent_o_id' => '',
'row_key' => $rowKey,
'status' => 'Sent',
'shop_i_id' => $shopItemId,
'shop_sku_id' => '3533103677164802',
'outer_oi_id' => 'OUTER-TEST-1',
'properties_value' => '颜色分类:六格-90*30*75cm-木纹胡桃色?赠送后背板',
'src_combine_sku_id' => $bundleParent,
];
}
}