feat: register shared original bill mirror
This commit is contained in:
parent
d48cb7d639
commit
f0150f1c49
@ -168,6 +168,25 @@ return [
|
||||
],
|
||||
],
|
||||
'operations_replica.rpt.jst_shopInfo' => ['source_key' => 'operations_replica', 'schema' => 'rpt', 'object' => 'jst_shopInfo', 'target' => 'ops_jst_shop_info', 'keys' => ['Id'], 'watermark' => 'updateTime'],
|
||||
'operations_replica.rpt.jst_originalBillInfo' => [
|
||||
'source_key' => 'operations_replica',
|
||||
'schema' => 'rpt',
|
||||
'object' => 'jst_originalBillInfo',
|
||||
'target' => 'ops_jst_original_bill_info',
|
||||
'keys' => ['Id'],
|
||||
'watermark' => 'updateTime',
|
||||
'columns' => [
|
||||
'Id', 'shop_id', 'channel', 'fee_time', 'del_flag', 'primary_key',
|
||||
'createTime', 'updateTime', 'auto_id', 'fee_name', 'inout_type',
|
||||
'oc_amount', 'p_auto_id', 'shop_i_id', 'shop_sku_id', 'sku_id',
|
||||
'so_id', 'combine_type', 'amount',
|
||||
],
|
||||
'indexes' => [
|
||||
['Id'],
|
||||
['shop_id', 'fee_time', 'Id'],
|
||||
['fee_time', 'Id'],
|
||||
],
|
||||
],
|
||||
|
||||
// 聚水潭聚工单:协同工单列表。只复制工单查询需要的非敏感字段,
|
||||
// 正式 API 从共享镜像关联“仓内未发”类型,不在请求中直连上游。
|
||||
|
||||
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
private function connection(): string
|
||||
{
|
||||
return (string) config('upstream_mirrors.connection', 'business_mirror');
|
||||
}
|
||||
|
||||
public function up(): void
|
||||
{
|
||||
$schema = Schema::connection($this->connection());
|
||||
|
||||
if ($schema->hasTable('ops_jst_original_bill_info')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$schema->create('ops_jst_original_bill_info', function (Blueprint $table): void {
|
||||
$table->char('_mirror_key', 64)->primary();
|
||||
$table->integer('Id');
|
||||
$table->integer('shop_id')->nullable();
|
||||
$table->string('channel', 100)->nullable();
|
||||
$table->dateTime('fee_time')->nullable();
|
||||
$table->integer('del_flag')->nullable();
|
||||
$table->string('primary_key', 100)->nullable();
|
||||
$table->dateTime('createTime')->nullable();
|
||||
$table->dateTime('updateTime')->nullable();
|
||||
$table->bigInteger('auto_id')->nullable();
|
||||
$table->string('fee_name', 100)->nullable();
|
||||
$table->string('inout_type', 100)->nullable();
|
||||
$table->string('oc_amount', 100)->nullable();
|
||||
$table->string('p_auto_id', 100)->nullable();
|
||||
$table->string('shop_i_id', 100)->nullable();
|
||||
$table->string('shop_sku_id', 100)->nullable();
|
||||
$table->string('sku_id', 100)->nullable();
|
||||
$table->string('so_id', 100)->nullable();
|
||||
$table->string('combine_type', 100)->nullable();
|
||||
$table->decimal('amount', 18, 2)->nullable();
|
||||
$table->uuid('_mirror_generation')->nullable()->index();
|
||||
$table->dateTime('_mirror_synced_at', 6)->index();
|
||||
|
||||
$table->unique('Id', 'ops_original_bill_source_id_unique');
|
||||
$table->index('updateTime', 'ops_original_bill_update_time_index');
|
||||
$table->index(['shop_id', 'fee_time', 'Id'], 'ops_original_bill_shop_fee_index');
|
||||
$table->index(['fee_time', 'Id'], 'ops_original_bill_fee_time_index');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::connection($this->connection())->dropIfExists('ops_jst_original_bill_info');
|
||||
}
|
||||
};
|
||||
@ -20,6 +20,7 @@
|
||||
| 本次建立 | `config/upstream_mirrors.php` 中登记全部当前代码引用的原表;通用表级同步框架负责建表、稳定游标、断点续传、增量重叠和全量校准。 |
|
||||
| 已开始逐域切换 | 公司、店铺、商标页面在对应镜像完成首次全量后自动改读完整镜像表;首次全量前保留旧快照作为兼容回滚。其他业务域仍需逐项切换,不得宣称全项目已经完成。 |
|
||||
| 中央同步接入 | 店铺维度报表从 `jiansun.dbo.jst_originalBillInfo` 和 `dbo.fys_shopInfo_flow` 自动、可断点同步;不再依赖开发者电脑、SQLite 或人工 XLSX。 |
|
||||
| 已登记,待首次同步 | `operations_replica/rpt.jst_originalBillInfo` 登记为通用原始账单镜像 `ops_jst_original_bill_info`;保留当前 19 个业务字段,按 `Id` 断点全量、按 `updateTime` 重叠增量。部署迁移只创建空表,不自动启动约 1400 万行的首次同步。 |
|
||||
|
||||
## 经营分析副本库(operations_replica)
|
||||
|
||||
@ -40,6 +41,7 @@
|
||||
| 推广费用 | `rpt.ads_itemid_sales_cost_ratio_v2_di` | `ops_item_sales_cost_ratio` |
|
||||
| 退款退货 | `rpt.jst_returnAndRefundInfo`、`rpt.jst_returnAndRefundItem` | `ops_jst_return_refund_*` |
|
||||
| 聚水潭店铺 | `rpt.jst_shopInfo` | `ops_jst_shop_info` |
|
||||
| 聚水潭原始账单 | `rpt.jst_originalBillInfo` | `ops_jst_original_bill_info` |
|
||||
| 店铺维度报表 | `jiansun/dbo.jst_originalBillInfo + dbo.jst_shopInfo + dbo.fys_shopInfo_flow` | `store_report_bill_rows`、`store_report_lifecycle_rows`、`store_report_daily_rows` |
|
||||
| 聚水潭聚工单(仓内未发) | `rpt.work_order_main`、`rpt.work_order_sub`、`rpt.work_order_form_config`、`rpt.work_order_form_value` | `ops_work_order_main`、`ops_work_order_sub`、`ops_work_order_form_config`、`ops_work_order_form_value` |
|
||||
|
||||
@ -72,6 +74,7 @@
|
||||
7. 普通商品的采购单价同步以采购主表 `updateTime` 加明细 `Id` 作为稳定游标;页面按商品编码选择最近完成的 1688 一键代发价格。同步保存全部状态,使完成单后续取消时也能撤回旧价格;首次全量前只显示普通商品自身采购价。
|
||||
8. 聚水潭官方接口尚未接入时,普通商品历史残留排除由负责人提供的最新完整 XLSX 导出刷新。只排除“导出生成前已创建、但导出中缺失”的镜像行,导出生成后的新增商品保持可见。导入使用新同步代次,只有完整解析成功才原子替换排除表;中断或错误保留上一版。后续接入聚水潭官方“普通商品资料查询”及删除/恢复记录后,由官方接口取代人工导出校准。
|
||||
9. 店铺维度报表是已批准的中央专用数据集:生产节点按 `Id` 断点推进并回看最近 50000 行;原始账单同步后增量维护按店铺/日期汇总的 `store_report_daily_rows`,页面不得现场扫描千万级原始账单。开发机不运行刷新 worker。
|
||||
10. `operations_replica.rpt.jst_originalBillInfo` 是供多个业务功能复用的原始账单镜像。首次同步必须单独授权并在低峰期分批续传;部署、页面请求和普通开发机均不得自动启动。同步完成后,开发者通过固定 Repository 查询 `ops_jst_original_bill_info`,不得各自创建整表快照。
|
||||
|
||||
## 后续切换顺序
|
||||
|
||||
|
||||
@ -112,6 +112,48 @@ class GenericUpstreamPipelineTest extends TestCase
|
||||
$this->assertFalse($registry->scheduled($key));
|
||||
}
|
||||
|
||||
public function test_original_bill_dataset_uses_stable_cursor_and_explicit_shared_schema(): void
|
||||
{
|
||||
$configuration = require base_path('config/upstream_mirrors.php');
|
||||
config(['upstream_mirrors.datasets' => $configuration['datasets']]);
|
||||
|
||||
$key = 'operations_replica.rpt.jst_originalBillInfo';
|
||||
$registry = app(BusinessMirrorDatasetRegistry::class);
|
||||
$dataset = $registry->get($key);
|
||||
|
||||
$this->assertSame('operations_replica', $dataset->sourceKey());
|
||||
$this->assertSame('rpt', $dataset->sourceSchema());
|
||||
$this->assertSame('jst_originalBillInfo', $dataset->sourceObject());
|
||||
$this->assertSame('ops_jst_original_bill_info', $dataset->targetTable());
|
||||
$this->assertSame(['Id'], $dataset->keyColumns());
|
||||
$this->assertSame('updateTime', $dataset->watermarkColumn());
|
||||
$this->assertSame([
|
||||
['Id'],
|
||||
['shop_id', 'fee_time', 'Id'],
|
||||
['fee_time', 'Id'],
|
||||
], $dataset->indexDefinitions());
|
||||
$this->assertSame([
|
||||
'Id', 'shop_id', 'channel', 'fee_time', 'del_flag', 'primary_key',
|
||||
'createTime', 'updateTime', 'auto_id', 'fee_name', 'inout_type',
|
||||
'oc_amount', 'p_auto_id', 'shop_i_id', 'shop_sku_id', 'sku_id',
|
||||
'so_id', 'combine_type', 'amount',
|
||||
], $registry->columnSelection($key));
|
||||
}
|
||||
|
||||
public function test_original_bill_migration_creates_compact_shared_table(): void
|
||||
{
|
||||
$migration = require base_path('database/migrations/2026_09_07_000000_create_original_bill_info_mirror_table.php');
|
||||
$migration->up();
|
||||
|
||||
$schema = Schema::connection('business_mirror');
|
||||
$this->assertTrue($schema->hasTable('ops_jst_original_bill_info'));
|
||||
$this->assertTrue($schema->hasColumn('ops_jst_original_bill_info', 'Id'));
|
||||
$this->assertTrue($schema->hasColumn('ops_jst_original_bill_info', 'updateTime'));
|
||||
$this->assertTrue($schema->hasColumn('ops_jst_original_bill_info', '_mirror_synced_at'));
|
||||
$this->assertSame('string', $schema->getColumnType('ops_jst_original_bill_info', 'channel'));
|
||||
$this->assertSame('string', $schema->getColumnType('ops_jst_original_bill_info', 'so_id'));
|
||||
}
|
||||
|
||||
/** @dataProvider nativeDrivers */
|
||||
public function test_native_tls_catalog_first_sync_pagination_and_incremental(string $driver, bool $timezoneAware = false, ?string $fixtureHost = null): void
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user