CaiWuXiTong/tests/Unit/EcommerceFinance/JushuitanCostPriceHistoryMirrorRepositoryTest.php

199 lines
8.4 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 Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Modules\EcommerceFinance\Repositories\JushuitanCostPriceHistoryMirrorRepository;
use Tests\TestCase;
class JushuitanCostPriceHistoryMirrorRepositoryTest extends TestCase
{
private JushuitanCostPriceHistoryMirrorRepository $repository;
protected function setUp(): void
{
parent::setUp();
config()->set('database.connections.business_mirror', [
'driver' => 'sqlite',
'database' => ':memory:',
'prefix' => '',
'foreign_key_constraints' => true,
]);
config()->set('upstream_mirrors.connection', 'business_mirror');
DB::purge('business_mirror');
$this->createTables();
$this->repository = app(JushuitanCostPriceHistoryMirrorRepository::class);
}
public function test_it_stores_and_formats_multiple_cost_price_operations_for_the_same_sku(): void
{
$generation = '11111111-1111-4111-8111-111111111111';
$this->repository->startRun(
'full',
$generation,
Carbon::parse('2026-06-01'),
Carbon::parse('2026-07-01'),
false,
);
$this->repository->storePage([
[
'operation_id' => '1',
'sku_id' => '15961g',
'operation_type' => '商品与库存管理导入',
'operation_description' => '采购价:72.2222->65',
'operator_name' => '简尚',
'operated_at' => '2026-06-06 14:32:02.993',
'before_price' => 72.2222,
'after_price' => 65,
'diff_amount' => -7.2222,
],
[
'operation_id' => '2',
'sku_id' => '15961G',
'operation_type' => '编辑',
'operation_description' => '采购价:65->63',
'operator_name' => '测试人',
'operated_at' => '2026-06-07 08:00:00',
'before_price' => 65,
'after_price' => 63,
'diff_amount' => -2,
],
], Carbon::parse('2026-07-01'), 1, $generation, 2, 2);
$this->repository->complete('full', $generation, Carbon::parse('2026-07-01'), 2, 2);
$records = $this->repository->historyForSkus(['15961G'])->get('15961G');
$history = $this->repository->formatHistory($records);
$this->assertCount(2, $history);
$this->assertSame(['2', '1'], array_column($history, 'id'));
$this->assertSame('聚水潭商品及库存管理', $history[0]['source']);
$this->assertSame('测试人', $history[0]['operator']);
$this->assertSame('编辑', $history[0]['operation']);
$this->assertSame('采购价:65->63', $history[0]['remark']);
$this->assertSame('63', (string) $history[0]['after_price']);
$this->assertTrue($this->repository->syncStatus()['initialized']);
}
public function test_incremental_empty_page_and_failed_run_keep_previous_history(): void
{
DB::connection('business_mirror')->table(JushuitanCostPriceHistoryMirrorRepository::TABLE)->insert([
'operation_id' => 'existing',
'sku_id' => 'SKU-KEEP',
'sku_id_normalized' => 'SKU-KEEP',
'operation_description' => '采购价:20->18',
'operated_at' => '2026-06-01 00:00:00',
'before_price' => 20,
'after_price' => 18,
'diff_amount' => -2,
'_mirror_generation' => 'old-generation',
'row_hash' => hash('sha256', 'existing'),
'_mirror_synced_at' => '2026-06-01 00:00:00',
]);
DB::connection('business_mirror')->table(JushuitanCostPriceHistoryMirrorRepository::STATE_TABLE)->insert([
'dataset_key' => JushuitanCostPriceHistoryMirrorRepository::DATASET_KEY,
'status' => 'succeeded',
'run_mode' => 'incremental',
'generation' => '22222222-2222-4222-8222-222222222222',
'window_started_at' => '2026-06-01 00:00:00',
'window_ends_at' => '2026-06-03 00:00:00',
'initial_completed_at' => '2026-06-01 00:00:00',
'last_succeeded_at' => '2026-06-01 00:00:00',
]);
$this->repository->storePage(
[],
Carbon::parse('2026-06-03'),
1,
'22222222-2222-4222-8222-222222222222',
0,
0,
);
$this->repository->fail('upstream_unavailable');
$this->assertSame(1, DB::connection('business_mirror')->table(JushuitanCostPriceHistoryMirrorRepository::TABLE)->count());
$this->assertSame('failed', $this->repository->state()['status']);
}
public function test_empty_full_sync_keeps_existing_audit_history(): void
{
DB::connection('business_mirror')->table(JushuitanCostPriceHistoryMirrorRepository::TABLE)->insert([
'operation_id' => 'existing',
'sku_id' => 'SKU-KEEP',
'sku_id_normalized' => 'SKU-KEEP',
'operation_description' => '采购价:20->18',
'operated_at' => '2026-06-01 00:00:00',
'before_price' => 20,
'after_price' => 18,
'diff_amount' => -2,
'_mirror_generation' => 'old-generation',
'row_hash' => hash('sha256', 'existing'),
'_mirror_synced_at' => '2026-06-01 00:00:00',
]);
$generation = '33333333-3333-4333-8333-333333333333';
$this->repository->startRun(
'full',
$generation,
Carbon::parse('2026-06-01'),
Carbon::parse('2026-07-01'),
false,
);
$this->repository->complete(
'full',
$generation,
Carbon::parse('2026-07-01'),
0,
0,
);
$this->assertSame(1, DB::connection('business_mirror')->table(JushuitanCostPriceHistoryMirrorRepository::TABLE)->count());
$this->assertSame('succeeded', $this->repository->state()['status']);
}
private function createTables(): void
{
Schema::connection('business_mirror')->create(JushuitanCostPriceHistoryMirrorRepository::STATE_TABLE, function (Blueprint $table): void {
$table->string('dataset_key')->primary();
$table->string('status')->default('pending');
$table->string('run_mode')->nullable();
$table->string('generation')->nullable();
$table->dateTime('window_started_at')->nullable();
$table->dateTime('window_ends_at')->nullable();
$table->dateTime('cursor_window_started_at')->nullable();
$table->unsignedInteger('cursor_page')->nullable();
$table->dateTime('initial_completed_at')->nullable();
$table->dateTime('last_full_succeeded_at')->nullable();
$table->dateTime('last_attempted_at')->nullable();
$table->dateTime('last_succeeded_at')->nullable();
$table->unsignedBigInteger('last_processed_source_rows')->default(0);
$table->unsignedBigInteger('last_upserted_rows')->default(0);
$table->unsignedBigInteger('mirror_row_count')->default(0);
$table->string('last_error_code')->nullable();
$table->timestamps();
});
Schema::connection('business_mirror')->create(JushuitanCostPriceHistoryMirrorRepository::TABLE, function (Blueprint $table): void {
$table->string('operation_id')->primary();
$table->string('sku_id');
$table->string('sku_id_normalized');
$table->string('i_id')->nullable();
$table->string('product_name')->nullable();
$table->string('properties_value')->nullable();
$table->string('sku_type')->nullable();
$table->string('operation_type')->nullable();
$table->text('operation_description')->nullable();
$table->string('operator_name')->nullable();
$table->dateTime('operated_at')->nullable();
$table->decimal('before_price', 20, 4)->nullable();
$table->decimal('after_price', 20, 4)->nullable();
$table->decimal('diff_amount', 20, 4)->nullable();
$table->string('_mirror_generation')->nullable();
$table->string('row_hash');
$table->dateTime('_mirror_synced_at');
$table->timestamps();
});
}
}