新增合同主体(乙方)与签订公司(甲方)只读展示和导出;协议签署自动带出唯一乙方,缺失或冲突留空核对。19项直接相关测试与实际浏览器联动验证通过。无权限、金额、数据库结构或配置改动。
256 lines
12 KiB
PHP
256 lines
12 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\CourierInformationMirrorRepository;
|
|
use Modules\EcommerceFinance\Repositories\GenericBusinessMirrorRepository;
|
|
use Modules\EcommerceFinance\Services\BusinessMirrorDatasetRegistry;
|
|
use Tests\TestCase;
|
|
|
|
class CourierInformationMirrorRepositoryTest extends TestCase
|
|
{
|
|
private CourierInformationMirrorRepository $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' => [
|
|
CourierInformationMirrorRepository::DATASET_KEY => $this->definition('wp_express', 'js_wp_express', ['Id'], 'modified'),
|
|
CourierInformationMirrorRepository::NETWORK_DATASET_KEY => $this->definition('wp_express_expNet', 'js_wp_express_exp_net', ['id']),
|
|
CourierInformationMirrorRepository::ACCOUNT_DATASET_KEY => $this->definition('wp_express_account', 'js_wp_express_account', ['Id']),
|
|
CourierInformationMirrorRepository::LOG_DATASET_KEY => $this->definition('wp_express_extension', 'js_wp_express_extension', ['Id'], 'modifyTime'),
|
|
],
|
|
]);
|
|
DB::purge('business_mirror');
|
|
|
|
Schema::connection('business_mirror')->create('business_mirror_table_states', function (Blueprint $table): void {
|
|
$table->string('dataset_key')->primary();
|
|
$table->string('status')->nullable();
|
|
$table->string('run_mode')->nullable();
|
|
$table->json('cursor')->nullable();
|
|
$table->json('high_watermark')->nullable();
|
|
$table->dateTime('initial_completed_at')->nullable();
|
|
$table->dateTime('last_succeeded_at')->nullable();
|
|
$table->unsignedBigInteger('mirror_row_count')->default(0);
|
|
});
|
|
$this->createExpressTable();
|
|
$this->createRelatedTables();
|
|
|
|
$this->repository = new CourierInformationMirrorRepository(
|
|
new BusinessMirrorDatasetRegistry(),
|
|
new GenericBusinessMirrorRepository(app('db')),
|
|
);
|
|
}
|
|
|
|
public function test_it_filters_and_pages_mirrored_courier_records(): void
|
|
{
|
|
$this->markReady(2);
|
|
$this->insertExpress(1, ['expcode' => 'SF', 'expname' => '顺丰', 'status' => 1]);
|
|
$this->insertExpress(2, ['expcode' => 'YD', 'expname' => '韵达', 'status' => 0]);
|
|
|
|
$result = $this->repository->paginate([
|
|
'expcode' => 'SF',
|
|
'expname' => '',
|
|
'undefined1' => '',
|
|
'undefined2' => '',
|
|
'undefined3' => '',
|
|
'tradebtime_from' => '',
|
|
'tradebtime_to' => '',
|
|
'status' => '1',
|
|
], 1, 1);
|
|
|
|
$this->assertSame(1, $result['total']);
|
|
$this->assertSame('SF', $result['data'][0]->expcode);
|
|
$this->assertTrue($this->repository->available());
|
|
$this->assertTrue($this->repository->ready());
|
|
}
|
|
|
|
public function test_it_reads_networks_and_accounts_by_courier_code(): void
|
|
{
|
|
$this->markReady(1);
|
|
$this->markDatasetReady(CourierInformationMirrorRepository::NETWORK_DATASET_KEY);
|
|
$this->markDatasetReady(CourierInformationMirrorRepository::ACCOUNT_DATASET_KEY);
|
|
$this->markDatasetReady(CourierInformationMirrorRepository::LOG_DATASET_KEY);
|
|
DB::connection('business_mirror')->table('js_wp_express_exp_net')->insert([
|
|
'_mirror_key' => 'network-1', 'id' => 1, 'expid' => 1, 'expcode' => 'SF', 'netname' => '浦东网点',
|
|
]);
|
|
DB::connection('business_mirror')->table('js_wp_express_account')->insert([
|
|
'_mirror_key' => 'account-1', 'Id' => 1, 'expcode' => 'SF', 'accountName' => '顺丰账户',
|
|
]);
|
|
DB::connection('business_mirror')->table('js_wp_express_extension')->insert([
|
|
'_mirror_key' => 'log-1', 'Id' => 1, 'expcode' => 'SF', 'doTime' => 2,
|
|
'createTime' => '2026-08-28 10:00:00', 'modifyTime' => '2026-08-28 10:00:00',
|
|
]);
|
|
|
|
$networks = $this->repository->paginateNetworks('SF', 1, 20);
|
|
$accounts = $this->repository->paginateAccounts('SF', 1, 20);
|
|
$logs = $this->repository->paginateLogs('SF', 1, 20);
|
|
|
|
$this->assertSame(1, $networks['total']);
|
|
$this->assertSame('浦东网点', $networks['data'][0]->netname);
|
|
$this->assertSame(1, $accounts['total']);
|
|
$this->assertSame('顺丰账户', $accounts['data'][0]->accountName);
|
|
$this->assertSame(1, $logs['total']);
|
|
$this->assertSame(2, $logs['data'][0]->doTime);
|
|
}
|
|
|
|
public function test_it_reads_esign_accounts_from_the_dzqzjbr_field(): void
|
|
{
|
|
$this->markReady(2);
|
|
$this->insertExpress(1, [
|
|
'expname' => '常州圆通其他',
|
|
'dzqzjbr' => '13800000001',
|
|
]);
|
|
$this->insertExpress(2, [
|
|
'expname' => '没有账号的快递',
|
|
'dzqzjbr' => null,
|
|
]);
|
|
|
|
$accounts = $this->repository->signingAccountsByName([
|
|
'常州圆通其他',
|
|
'没有账号的快递',
|
|
]);
|
|
|
|
$this->assertSame(['常州圆通其他' => '13800000001'], $accounts);
|
|
}
|
|
|
|
public function test_it_returns_distinct_non_empty_courier_names_from_mirror_data(): void
|
|
{
|
|
$this->markReady(4);
|
|
$this->insertExpress(1, ['expname' => '顺丰']);
|
|
$this->insertExpress(2, ['expname' => '']);
|
|
$this->insertExpress(3, ['expname' => '顺丰']);
|
|
$this->insertExpress(4, ['expname' => '韵达']);
|
|
|
|
$this->assertSame(['顺丰', '韵达'], $this->repository->names());
|
|
}
|
|
|
|
public function test_contract_parties_use_source_fields_and_reject_conflicting_same_name_subjects(): void
|
|
{
|
|
$this->markReady(7);
|
|
$this->insertExpress(1, ['expname' => '快递简称', 'tradebody' => ' 乙方物流有限公司 ', 'signcom' => '甲方商贸有限公司']);
|
|
$this->insertExpress(2, ['expname' => '快递简称', 'tradebody' => '乙方物流有限公司', 'signcom' => '甲方商贸有限公司']);
|
|
$this->insertExpress(3, ['expname' => '快递简称', 'tradebody' => '已删除的其他主体', 'is_delete' => 1]);
|
|
$this->insertExpress(4, ['expname' => '冲突快递', 'tradebody' => '乙方一', 'signcom' => '甲方一']);
|
|
$this->insertExpress(5, ['expname' => '冲突快递', 'tradebody' => '乙方二', 'signcom' => '甲方一']);
|
|
$this->insertExpress(6, ['expname' => '未维护快递']);
|
|
$this->insertExpress(7, ['expname' => '不在请求内快递', 'tradebody' => '不应返回']);
|
|
|
|
$this->assertSame([
|
|
'快递简称' => ['party_b' => '乙方物流有限公司', 'party_a' => '甲方商贸有限公司', 'ambiguous' => false],
|
|
'冲突快递' => ['party_b' => '', 'party_a' => '甲方一', 'ambiguous' => true],
|
|
'未维护快递' => ['party_b' => '', 'party_a' => '', 'ambiguous' => false],
|
|
], $this->repository->contractPartiesByName(['快递简称', '冲突快递', '未维护快递']));
|
|
|
|
$row = $this->repository->paginate(['expcode' => 'EXP-1'], 1, 10)['data'][0];
|
|
$this->assertSame(' 乙方物流有限公司 ', $row->tradebody);
|
|
$this->assertSame('甲方商贸有限公司', $row->signcom);
|
|
$export = iterator_to_array($this->repository->exportRows(['expcode' => 'EXP-1']));
|
|
$this->assertSame($row->tradebody, $export[0]->tradebody);
|
|
$this->assertSame($row->signcom, $export[0]->signcom);
|
|
}
|
|
|
|
public function test_contract_parties_remain_unavailable_until_mirror_initial_sync_is_complete(): void
|
|
{
|
|
$this->insertExpress(1, ['expname' => '未就绪快递', 'tradebody' => '不能使用的部分数据']);
|
|
$this->assertSame([], $this->repository->contractPartiesByName(['未就绪快递']));
|
|
$this->markReady(1);
|
|
$this->assertSame([], $this->repository->contractPartiesByName([]));
|
|
}
|
|
|
|
private function createExpressTable(): void
|
|
{
|
|
Schema::connection('business_mirror')->create('js_wp_express', function (Blueprint $table): void {
|
|
$table->string('_mirror_key')->primary();
|
|
$table->integer('Id');
|
|
foreach (['expcode', 'expname', 'outcode', 'scexpcode', 'paymethod', 'tradebody', 'signcom', 'signmode', 'linker', 'linkmobile', 'paytype', 'undefined1', 'undefined2', 'undefined3', 'undefinedtype', 'undefined4', 'undefined5', 'dzqzjbr', 'guid', 'exp_properties'] as $column) {
|
|
$table->string($column)->nullable();
|
|
}
|
|
foreach (['status', 'addvalidsgn', 'kuaiyunsgn', 'autonosgn', 'packnosgn', 'skucountsplitsgn', 'weight0sgn', 'volume0sgn', 'handnosgn', 'decryptsgn', 'pj1sgn', 'is_delete'] as $column) {
|
|
$table->integer($column)->nullable();
|
|
}
|
|
foreach (['stopdate', 'tradebtime', 'tradeetime', 'modified'] as $column) {
|
|
$table->dateTime($column)->nullable();
|
|
}
|
|
});
|
|
}
|
|
|
|
private function createRelatedTables(): void
|
|
{
|
|
Schema::connection('business_mirror')->create('js_wp_express_exp_net', function (Blueprint $table): void {
|
|
$table->string('_mirror_key')->primary();
|
|
$table->integer('id');
|
|
$table->integer('expid')->nullable();
|
|
foreach (['expcode', 'netcode', 'netno', 'netname', 'isbill', 'province', 'city', 'area', 'town', 'address', 'linker', 'linkermobile', 'status', 'apitype', 'apipltmname', 'created', 'expnum'] as $column) {
|
|
$table->string($column)->nullable();
|
|
}
|
|
});
|
|
Schema::connection('business_mirror')->create('js_wp_express_account', function (Blueprint $table): void {
|
|
$table->string('_mirror_key')->primary();
|
|
$table->integer('Id');
|
|
foreach (['expcode', 'expname', 'accountType', 'account', 'accountName', 'accountkhh', 'createTime', 'invoice', 'erpId', 'erpAccountId'] as $column) {
|
|
$table->string($column)->nullable();
|
|
}
|
|
});
|
|
Schema::connection('business_mirror')->create('js_wp_express_extension', function (Blueprint $table): void {
|
|
$table->string('_mirror_key')->primary();
|
|
$table->integer('Id');
|
|
$table->string('expcode')->nullable();
|
|
$table->integer('doTime')->nullable();
|
|
$table->dateTime('createTime')->nullable();
|
|
$table->dateTime('modifyTime')->nullable();
|
|
});
|
|
}
|
|
|
|
private function insertExpress(int $id, array $overrides): void
|
|
{
|
|
DB::connection('business_mirror')->table('js_wp_express')->insert(array_merge([
|
|
'_mirror_key' => 'express-' . $id,
|
|
'Id' => $id,
|
|
'expcode' => 'EXP-' . $id,
|
|
'expname' => '测试快递',
|
|
'status' => 1,
|
|
'modified' => '2026-08-28 10:00:00',
|
|
], $overrides));
|
|
}
|
|
|
|
private function markReady(int $rows): void
|
|
{
|
|
$this->markDatasetReady(CourierInformationMirrorRepository::DATASET_KEY, $rows);
|
|
}
|
|
|
|
private function markDatasetReady(string $key, int $rows = 1): void
|
|
{
|
|
DB::connection('business_mirror')->table('business_mirror_table_states')->insert([
|
|
'dataset_key' => $key,
|
|
'status' => 'succeeded',
|
|
'initial_completed_at' => '2026-08-28 10:00:00',
|
|
'last_succeeded_at' => '2026-08-28 10:00:00',
|
|
'mirror_row_count' => $rows,
|
|
]);
|
|
}
|
|
|
|
private function definition(string $object, string $target, array $keys, ?string $watermark = null): array
|
|
{
|
|
return [
|
|
'source_key' => 'jiansun',
|
|
'schema' => 'dbo',
|
|
'object' => $object,
|
|
'target' => $target,
|
|
'keys' => $keys,
|
|
'watermark' => $watermark,
|
|
];
|
|
}
|
|
}
|