CaiWuXiTong/tests/Unit/EcommerceFinance/BillOffsetMirrorRepositoryTest.php

117 lines
6.3 KiB
PHP

<?php
namespace Tests\Unit\EcommerceFinance;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Modules\EcommerceFinance\Repositories\BillOffsetMirrorRepository;
use Modules\EcommerceFinance\Repositories\GenericBusinessMirrorRepository;
use Modules\EcommerceFinance\Services\BusinessMirrorDatasetRegistry;
use RuntimeException;
use Tests\TestCase;
class BillOffsetMirrorRepositoryTest extends TestCase
{
private BillOffsetMirrorRepository $repository;
protected function setUp(): void
{
parent::setUp();
config([
'database.connections.business_mirror' => ['driver' => 'sqlite', 'database' => ':memory:', 'prefix' => ''],
'upstream_mirrors.connection' => 'business_mirror',
'upstream_mirrors.datasets' => [BillOffsetMirrorRepository::DATASET => [
'source_key' => 'operations_replica', 'schema' => 'rpt', 'object' => 'jst_originalBillInfo',
'target' => 'ops_jst_original_bill_info', 'keys' => ['Id'],
]],
]);
DB::purge('business_mirror');
$schema = Schema::connection('business_mirror');
$schema->create('business_mirror_table_states', function (Blueprint $table): void {
$table->string('dataset_key')->primary();
$table->dateTime('initial_completed_at')->nullable();
$table->string('status')->nullable();
$table->dateTime('last_succeeded_at')->nullable();
});
$schema->create('ops_jst_original_bill_info', function (Blueprint $table): void {
$table->integer('Id');
$table->dateTime('fee_time')->nullable();
$table->string('fee_name')->nullable();
$table->string('inout_type')->nullable();
$table->string('so_id')->nullable();
$table->string('p_auto_id')->nullable();
$table->string('sku_id')->nullable();
$table->string('shop_sku_id')->nullable();
$table->string('shop_i_id')->nullable();
$table->decimal('amount', 18, 2)->nullable();
});
$schema->create('ops_jst_orders', function (Blueprint $table): void {
$table->integer('o_id'); $table->string('so_id')->nullable(); $table->string('shop_name')->nullable(); $table->string('shop_id')->nullable();
});
$schema->create('ops_jst_order_item', function (Blueprint $table): void {
$table->integer('o_id'); $table->string('sku_id')->nullable(); $table->string('i_id')->nullable(); $table->string('shop_sku_id')->nullable(); $table->string('shop_i_id')->nullable();
});
$this->repository = new BillOffsetMirrorRepository(new BusinessMirrorDatasetRegistry(), new GenericBusinessMirrorRepository(app('db')));
}
public function test_it_filters_joins_orders_and_calculates_summary(): void
{
DB::connection('business_mirror')->table('business_mirror_table_states')->insert([
'dataset_key' => BillOffsetMirrorRepository::DATASET,
'initial_completed_at' => '2026-09-08 09:00:00', 'status' => 'succeeded', 'last_succeeded_at' => '2026-09-08 09:00:00',
]);
DB::connection('business_mirror')->table('ops_jst_original_bill_info')->insert([
['Id' => 1, 'fee_time' => '2026-08-01 10:00:00', 'fee_name' => '500112冲减收入', 'inout_type' => '收入', 'so_id' => 'SO-1', 'sku_id' => 'SKU-1', 'amount' => -20],
['Id' => 2, 'fee_time' => '2026-08-02 10:00:00', 'fee_name' => '500112冲减收入', 'inout_type' => '收入', 'so_id' => 'SO-2', 'sku_id' => 'SKU-2', 'amount' => 18.25],
['Id' => 4, 'fee_time' => '2026-08-01 10:00:00', 'fee_name' => '订单收入', 'inout_type' => '收入', 'so_id' => 'SO-1', 'sku_id' => 'SKU-1', 'amount' => 100],
]);
DB::connection('business_mirror')->table('ops_jst_orders')->insert([
['o_id' => 1001, 'so_id' => 'SO-1', 'shop_name' => '测试店铺', 'shop_id' => 'SHOP-1'],
['o_id' => 1002, 'so_id' => 'SO-2', 'shop_name' => '其他店铺', 'shop_id' => 'SHOP-2'],
]);
DB::connection('business_mirror')->table('ops_jst_order_item')->insert([
['o_id' => 1001, 'sku_id' => 'SKU-1', 'i_id' => 'STYLE-1', 'shop_sku_id' => 'SP-1', 'shop_i_id' => 'SI-1'],
]);
$result = $this->repository->paginate(['from' => '2026-08-01', 'to' => '2026-08-01', 'shop_name' => '测试店铺', 'sku_id' => 'SKU-1'], 1, 10);
$this->assertSame(1, $result['total']);
$this->assertSame('1001', (string) $result['data'][0]['internal_order_no']);
$this->assertSame('测试店铺', $result['data'][0]['shop_name']);
$this->assertSame('STYLE-1', $result['data'][0]['style_code']);
$this->assertSame(-20.0, $result['summary']['amount']);
$this->assertSame('succeeded', $result['sync']['status']);
}
public function test_it_rejects_unready_mirror(): void
{
$this->expectException(RuntimeException::class);
$this->expectExceptionMessage('bill_offset_mirror_not_ready');
$this->repository->paginate([], 1, 10);
}
public function test_it_reads_bill_rows_when_order_mirror_tables_are_not_available(): void
{
$schema = Schema::connection('business_mirror');
$schema->dropIfExists('ops_jst_order_item');
$schema->dropIfExists('ops_jst_orders');
DB::connection('business_mirror')->table('business_mirror_table_states')->insert([
'dataset_key' => BillOffsetMirrorRepository::DATASET,
'initial_completed_at' => '2026-09-08 09:00:00', 'status' => 'succeeded', 'last_succeeded_at' => '2026-09-08 09:00:00',
]);
DB::connection('business_mirror')->table('ops_jst_original_bill_info')->insert([
'Id' => 3, 'fee_time' => '2026-08-03 10:00:00', 'fee_name' => '500112冲减收入', 'inout_type' => '收入',
'so_id' => 'SO-3', 'sku_id' => 'SKU-3', 'amount' => 12.5,
]);
$result = $this->repository->paginate([], 1, 10);
$this->assertSame(1, $result['total']);
$this->assertSame('SO-3', $result['data'][0]['internal_order_no']);
$this->assertSame('SKU-3', $result['data'][0]['product_code']);
$this->assertSame(12.5, $result['summary']['amount']);
$this->assertSame(0, $this->repository->paginate(['shop_name' => '测试店铺'], 1, 10)['total']);
}
}