234 lines
11 KiB
PHP
234 lines
11 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\GenericBusinessMirrorRepository;
|
|
use Modules\EcommerceFinance\Repositories\StoreReceivingAlipayBillMirrorRepository;
|
|
use Modules\EcommerceFinance\Repositories\StoreReceivingPinduoduoBillMirrorRepository;
|
|
use Modules\EcommerceFinance\Services\BusinessMirrorDatasetRegistry;
|
|
use Tests\TestCase;
|
|
|
|
class StoreReceivingPinduoduoBillMirrorRepositoryTest extends TestCase
|
|
{
|
|
private StoreReceivingPinduoduoBillMirrorRepository $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' => [
|
|
StoreReceivingPinduoduoBillMirrorRepository::DATASET => [
|
|
'source_key' => 'jiansun', 'schema' => 'dbo',
|
|
'object' => 'jst_originalBillInfo', 'target' => 'js_jst_pdd_receiving_bill_rows',
|
|
'keys' => ['Id'],
|
|
'fixed_filters' => ['channel' => StoreReceivingPinduoduoBillMirrorRepository::SOURCE_CHANNEL],
|
|
],
|
|
StoreReceivingAlipayBillMirrorRepository::SHOP_DATASET => [
|
|
'source_key' => 'operations_replica', 'schema' => 'rpt',
|
|
'object' => 'jst_shopInfo', 'target' => 'ops_jst_shop_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();
|
|
$table->unsignedBigInteger('mirror_row_count')->nullable();
|
|
$table->boolean('mirror_row_count_is_exact')->default(false);
|
|
});
|
|
$schema->create('js_jst_pdd_receiving_bill_rows', function (Blueprint $table): void {
|
|
$table->integer('Id');
|
|
$table->integer('shop_id')->nullable();
|
|
foreach (['channel', 'primary_key', 'fee_name', 'inout_type', 'p_auto_id', 'shop_i_id', 'shop_sku_id', 'sku_id', 'so_id', 'combine_type'] as $column) {
|
|
$table->string($column)->nullable();
|
|
}
|
|
$table->dateTime('fee_time')->nullable();
|
|
$table->dateTime('createTime')->nullable();
|
|
$table->dateTime('updateTime')->nullable();
|
|
$table->bigInteger('auto_id')->nullable();
|
|
$table->decimal('amount', 20, 6)->nullable();
|
|
});
|
|
$schema->create('ops_jst_shop_info', function (Blueprint $table): void {
|
|
$table->integer('Id');
|
|
$table->integer('shop_id')->nullable();
|
|
$table->string('shop_name')->nullable();
|
|
});
|
|
|
|
$source = new StoreReceivingAlipayBillMirrorRepository(
|
|
new BusinessMirrorDatasetRegistry(), new GenericBusinessMirrorRepository(app('db')),
|
|
);
|
|
$this->repository = new StoreReceivingPinduoduoBillMirrorRepository($source);
|
|
$this->markReady();
|
|
}
|
|
|
|
public function test_it_reads_the_pinduoduo_dedicated_dataset_and_maps_source_fields(): void
|
|
{
|
|
DB::connection('business_mirror')->table('ops_jst_shop_info')->insert([
|
|
['Id' => 10, 'shop_id' => 7, 'shop_name' => '拼多多-测试店'],
|
|
['Id' => 11, 'shop_id' => 8, 'shop_name' => '抖音-其他店'],
|
|
]);
|
|
DB::connection('business_mirror')->table('js_jst_pdd_receiving_bill_rows')->insert([
|
|
$this->row(1, 7, 'PinduoduoImport', '2026-09-09 23:55:47', '1', 91.64),
|
|
$this->row(2, 7, 'PinduoduoImport', '2026-09-09 23:58:52', '-1', 0.66),
|
|
]);
|
|
|
|
$result = $this->repository->paginate([], 'occurred_at', 'desc', 1, 10);
|
|
|
|
$this->assertSame(2, $result['total']);
|
|
$this->assertSame('380000002', $result['data'][0]['record_code']);
|
|
$this->assertSame('拼多多-测试店', $result['data'][0]['store_name']);
|
|
$this->assertSame('260909-ORDER-2', $result['data'][0]['order_no']);
|
|
$this->assertSame('260909-ORDER-2', $result['data'][0]['payload']['merchant_order_no']);
|
|
$this->assertSame('技术服务费', $result['data'][0]['payload']['finance_type']);
|
|
$this->assertSame('拼多多货款账户', $result['data'][0]['payload']['type']);
|
|
$this->assertSame('RPA', $result['data'][0]['modifier']);
|
|
$this->assertSame(91.64, $result['summary']['income']);
|
|
$this->assertSame(0.66, $result['summary']['expense']);
|
|
$this->assertSame(90.98, $result['summary']['balance']);
|
|
}
|
|
|
|
public function test_filters_options_and_export_do_not_repeat_the_dataset_fixed_channel(): void
|
|
{
|
|
DB::connection('business_mirror')->table('ops_jst_shop_info')->insert([
|
|
['Id' => 10, 'shop_id' => 7, 'shop_name' => '拼多多-A店'],
|
|
['Id' => 11, 'shop_id' => 8, 'shop_name' => '拼多多-B店'],
|
|
['Id' => 12, 'shop_id' => 9, 'shop_name' => '抖音店'],
|
|
]);
|
|
DB::connection('business_mirror')->table('js_jst_pdd_receiving_bill_rows')->insert([
|
|
$this->row(1, 7, 'PinduoduoImport', '2026-08-12 09:00:00', '1', 22.80, '交易收入'),
|
|
$this->row(2, 8, 'PinduoduoImport', '2026-08-13 09:00:00', '-1', 0.14, '技术服务费'),
|
|
]);
|
|
$connection = DB::connection('business_mirror');
|
|
$connection->flushQueryLog();
|
|
$connection->enableQueryLog();
|
|
|
|
$result = $this->repository->paginate([
|
|
'store_name' => 'A店',
|
|
'bill_item' => '交易',
|
|
'start' => '2026-08-12',
|
|
'end' => '2026-08-12',
|
|
'keyword' => '380000001',
|
|
], 'record_code', 'asc', 1, 10);
|
|
$options = $this->repository->filterOptions();
|
|
$export = iterator_to_array($this->repository->exportRows(['bill_item' => '技术服务费']));
|
|
|
|
$this->assertSame(1, $result['total']);
|
|
$this->assertSame('380000001', $result['data'][0]['record_code']);
|
|
$this->assertSame(['拼多多-A店', '拼多多-B店'], $options['shops']);
|
|
$this->assertSame(['交易收入', '技术服务费'], $options['bill_items']);
|
|
$this->assertCount(1, $export);
|
|
$this->assertSame('380000002', $export[0]['record_code']);
|
|
$targetQueries = array_filter(
|
|
$connection->getQueryLog(),
|
|
static fn (array $query): bool => str_contains($query['query'], 'js_jst_pdd_receiving_bill_rows'),
|
|
);
|
|
$this->assertNotEmpty($targetQueries);
|
|
$this->assertCount(0, array_filter(
|
|
$targetQueries,
|
|
static fn (array $query): bool => str_contains($query['query'], '"b"."channel" = ?'),
|
|
));
|
|
$connection->disableQueryLog();
|
|
}
|
|
|
|
public function test_unfiltered_total_uses_the_exact_mirror_count(): void
|
|
{
|
|
DB::connection('business_mirror')->table('js_jst_pdd_receiving_bill_rows')->insert([
|
|
$this->row(1, 7, 'PinduoduoImport', '2026-09-09 23:55:47', '1', 91.64),
|
|
$this->row(2, 7, 'PinduoduoImport', '2026-09-09 23:58:52', '-1', 0.66),
|
|
]);
|
|
$connection = DB::connection('business_mirror');
|
|
$connection->table('business_mirror_table_states')
|
|
->where('dataset_key', StoreReceivingPinduoduoBillMirrorRepository::DATASET)
|
|
->update(['mirror_row_count' => 2, 'mirror_row_count_is_exact' => true]);
|
|
$connection->enableQueryLog();
|
|
$connection->flushQueryLog();
|
|
|
|
$result = $this->repository->paginate([], 'occurred_at', 'desc', 1, 10);
|
|
|
|
$this->assertSame(2, $result['total']);
|
|
$this->assertCount(0, array_filter(
|
|
$connection->getQueryLog(),
|
|
static fn (array $query): bool => str_contains(strtolower($query['query']), 'count(*)')
|
|
&& str_contains($query['query'], 'js_jst_pdd_receiving_bill_rows'),
|
|
));
|
|
$connection->disableQueryLog();
|
|
}
|
|
|
|
public function test_fee_name_index_config_and_migration_are_idempotent_and_reversible(): void
|
|
{
|
|
$configured = require base_path('config/upstream_mirrors.php');
|
|
$indexes = $configured['datasets'][StoreReceivingPinduoduoBillMirrorRepository::DATASET]['indexes'];
|
|
$this->assertContains(['fee_name'], $indexes);
|
|
|
|
config(['system_database.mode' => 'connected']);
|
|
$table = DB::connection('business_mirror')->table('js_jst_pdd_receiving_bill_rows');
|
|
$table->insert($this->row(1, 7, 'PinduoduoImport', '2026-08-12 09:00:00', '1', 22.80));
|
|
$before = (array) $table->first();
|
|
$migration = require base_path('database/migrations/2026_09_14_160000_index_pinduoduo_bill_filter_options.php');
|
|
|
|
$migration->up();
|
|
$migration->up();
|
|
|
|
$schema = Schema::connection('business_mirror');
|
|
$this->assertTrue($schema->hasIndex('js_jst_pdd_receiving_bill_rows', 'idx_pdd_receiving_bill_fee_name'));
|
|
$this->assertEquals($before, (array) $table->first());
|
|
|
|
$migration->down();
|
|
$this->assertFalse($schema->hasIndex('js_jst_pdd_receiving_bill_rows', 'idx_pdd_receiving_bill_fee_name'));
|
|
$this->assertEquals($before, (array) $table->first());
|
|
}
|
|
|
|
private function markReady(): void
|
|
{
|
|
foreach ([StoreReceivingPinduoduoBillMirrorRepository::DATASET, StoreReceivingAlipayBillMirrorRepository::SHOP_DATASET] as $dataset) {
|
|
DB::connection('business_mirror')->table('business_mirror_table_states')->insert([
|
|
'dataset_key' => $dataset,
|
|
'initial_completed_at' => '2026-09-11 09:00:00',
|
|
'status' => 'succeeded',
|
|
'last_succeeded_at' => '2026-09-11 09:00:00',
|
|
]);
|
|
}
|
|
}
|
|
|
|
private function row(
|
|
int $id,
|
|
int $shopId,
|
|
string $channel,
|
|
string $time,
|
|
string $direction,
|
|
float $amount,
|
|
string $feeName = '技术服务费',
|
|
): array {
|
|
return [
|
|
'Id' => $id,
|
|
'shop_id' => $shopId,
|
|
'channel' => $channel,
|
|
'primary_key' => 'KEY-' . $id,
|
|
'fee_name' => $feeName,
|
|
'inout_type' => $direction,
|
|
'p_auto_id' => 'P-' . $id,
|
|
'shop_i_id' => 'ITEM-' . $id,
|
|
'shop_sku_id' => 'SHOP-SKU-' . $id,
|
|
'sku_id' => 'SKU-' . $id,
|
|
'so_id' => '260909-ORDER-' . $id,
|
|
'combine_type' => 'double',
|
|
'fee_time' => $time,
|
|
'createTime' => '2026-09-10 13:00:48',
|
|
'updateTime' => '2026-09-10 13:00:48',
|
|
'auto_id' => 380000000 + $id,
|
|
'amount' => $amount,
|
|
];
|
|
}
|
|
}
|