From 29547fbd4db304aab2941d86f3f1d2a5f9d4b679 Mon Sep 17 00:00:00 2001 From: limeng <1131177064@qq.com> Date: Wed, 28 Oct 2026 05:56:36 +0000 Subject: [PATCH] =?UTF-8?q?feat(=E7=BA=BF=E4=B8=8A=E4=BB=A3=E5=8F=91?= =?UTF-8?q?=E4=BB=B7=E6=A0=BC):=20=E6=96=B0=E5=A2=9E=E5=AE=9E=E9=99=85?= =?UTF-8?q?=E5=8F=91=E8=B4=A7=E5=95=86=E5=93=81=E7=BC=96=E7=A0=81=E4=B8=8E?= =?UTF-8?q?=E8=81=9A=E6=B0=B4=E6=BD=AD=E6=A0=87=E8=AE=B0|=E5=A4=9A?= =?UTF-8?q?=E6=A0=87=E7=AD=BE=E4=B8=A4=E5=88=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 按店铺交易单号(钉钉行)/内部单号(采购单行)批量关联聚水潭订单 (ops_jst_orders + 淘系 ops_jst_qmcust_orders),补充: - 实际发货商品编码:组合装拆开后的子商品编码×数量;优先取本行商品编码 拆出的子商品,普通商品取自身,对不上时列整单;忽略被拆分/合并/作废原单 - 聚水潭标记|多标签:订单 labels 只按当前页/导出批次的单号做索引等值查询;页面与 CSV 导出同步加列。 Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_012AvVQFrueqWakFKTdSyu5q --- app/Http/Controllers/Business/Pages.php | 4 +- .../DingOnlineDaifaPriceMirrorRepository.php | 279 +++++++++++++++++- .../online-daifa-price.blade.php | 7 +- .../Business/OnlineDaifaPricePageTest.php | 6 + .../OnlineDaifaShipSkuLabelsTest.php | 164 ++++++++++ 5 files changed, 456 insertions(+), 4 deletions(-) create mode 100644 tests/Unit/EcommerceFinance/OnlineDaifaShipSkuLabelsTest.php diff --git a/app/Http/Controllers/Business/Pages.php b/app/Http/Controllers/Business/Pages.php index 018f24d0..e9f76b34 100644 --- a/app/Http/Controllers/Business/Pages.php +++ b/app/Http/Controllers/Business/Pages.php @@ -6820,7 +6820,7 @@ class Pages extends Controller fputcsv($csv, [ '审批编号', '标题', '状态', '申请人', '收款人全称', '标签', '商品ID', '商品名称(匹配)', '店铺名称', '代发交易单号', '店铺交易单号', '发货数量', '订单实付金额', '代发订单金额', '差价', - '供应商名称', '商品编码', '创建时间', + '供应商名称', '商品编码', '实际发货商品编码', '聚水潭标记|多标签', '创建时间', ]); foreach ($this->onlineDaifaPrices->exportRows($filters) as $row) { @@ -6853,6 +6853,8 @@ class Pages extends Controller $row['price_diff'] ?? null, $this->csvText($row['supplier_name'] ?? ''), $this->csvIdentifier($row['material_no'] ?? ''), + $this->csvText($row['ship_skus'] ?? ''), + $this->csvText($row['jst_labels'] ?? ''), $this->csvText($row['workflow_created_at'] ?? ''), ]); } diff --git a/modules/EcommerceFinance/Repositories/DingOnlineDaifaPriceMirrorRepository.php b/modules/EcommerceFinance/Repositories/DingOnlineDaifaPriceMirrorRepository.php index c06ab03a..f9ebdcdc 100644 --- a/modules/EcommerceFinance/Repositories/DingOnlineDaifaPriceMirrorRepository.php +++ b/modules/EcommerceFinance/Repositories/DingOnlineDaifaPriceMirrorRepository.php @@ -24,11 +24,27 @@ class DingOnlineDaifaPriceMirrorRepository private const ORDER_DATASET_KEY = 'operations_replica.rpt.jst_Orders'; + /** 聚水潭订单来源:非淘系 + 淘系(奇门),两套表结构一致。 */ + private const JST_ORDER_SOURCES = [ + ['ops_jst_orders', 'ops_jst_order_item'], + ['ops_jst_qmcust_orders', 'ops_jst_qmcust_order_items'], + ]; + + /** 被拆分、合并、作废的原单不代表实际发货,有其它有效订单时不参与拼接。 */ + private const JST_INACTIVE_ORDER_STATUSES = ['Cancelled', 'Split', 'Merged', 'Delete']; + + private const JST_LOOKUP_CHUNK = 500; + + private const EXPORT_HYDRATE_BATCH = 200; + private readonly ConnectionInterface $connection; /** @var array>|null */ private ?array $sourceStatusCache = null; + /** @var list|null */ + private ?array $jstOrderSourceCache = null; + public function __construct(GenericBusinessMirrorRepository $mirror) { $this->connection = $mirror->connection(); @@ -98,6 +114,7 @@ class DingOnlineDaifaPriceMirrorRepository foreach ($pageRows as $row) { $data[] = $this->presentRow($row); } + $this->attachJstOrderDetails($data); $sources = $this->sourceStatuses(); $readySources = array_filter($sources, static fn (array $source): bool => (bool) ($source['ready'] ?? false)); @@ -128,9 +145,269 @@ class DingOnlineDaifaPriceMirrorRepository ->orderByDesc('detail_index') ->cursor(); + $buffer = []; foreach ($rows as $row) { - yield $this->presentRow($row); + $buffer[] = $this->presentRow($row); + if (count($buffer) >= self::EXPORT_HYDRATE_BATCH) { + $this->attachJstOrderDetails($buffer); + yield from $buffer; + $buffer = []; + } } + if ($buffer !== []) { + $this->attachJstOrderDetails($buffer); + yield from $buffer; + } + } + + /** + * 按线上订单号(钉钉行)或内部单号(采购单行)批量关联聚水潭订单,补充: + * - ship_skus:实际发货商品编码(组合装拆开后的子商品编码 × 数量); + * - jst_labels:聚水潭订单界面的「标记|多标签」。 + * + * 只按当前这一批行的单号做等值查询(so_id / o_id 均有索引),不扫整张订单表。 + * + * @param list> $rows + */ + private function attachJstOrderDetails(array &$rows): void + { + foreach ($rows as &$row) { + $row['ship_skus'] = ''; + $row['ship_sku_items'] = []; + $row['jst_labels'] = ''; + } + unset($row); + + $soIds = []; + $oIds = []; + foreach ($rows as $row) { + if (($row['source_type'] ?? 'ding') === 'purchase') { + $oId = trim((string) ($row['source_order_no'] ?? '')); + if ($oId !== '' && ctype_digit($oId)) { + $oIds[(int) $oId] = true; + } + } else { + foreach ($this->splitTradeNos((string) ($row['shop_trade_no'] ?? '')) as $soId) { + $soIds[$soId] = true; + } + } + } + if ($soIds === [] && $oIds === []) { + return; + } + + try { + [$ordersBySo, $ordersByOid] = $this->loadJstOrders(array_keys($soIds), array_keys($oIds)); + } catch (\Throwable $exception) { + report($exception); + + return; + } + + foreach ($rows as &$row) { + if (($row['source_type'] ?? 'ding') === 'purchase') { + $orders = $ordersByOid[trim((string) ($row['source_order_no'] ?? ''))] ?? []; + } else { + $orders = []; + foreach ($this->splitTradeNos((string) ($row['shop_trade_no'] ?? '')) as $soId) { + foreach ($ordersBySo[$soId] ?? [] as $order) { + $orders[$order['key']] = $order; + } + } + $orders = array_values($orders); + } + if ($orders === []) { + continue; + } + + $active = array_values(array_filter( + $orders, + static fn (array $order): bool => ! in_array($order['status'], self::JST_INACTIVE_ORDER_STATUSES, true), + )); + if ($active === []) { + $active = $orders; + } + + $labels = []; + $items = []; + foreach ($active as $order) { + foreach ($order['labels'] as $label) { + $labels[$label] = true; + } + foreach ($order['items'] as $item) { + $items[] = $item; + } + } + + $shipped = $this->shippedItemsFor($items, (string) ($row['material_no'] ?? '')); + $row['ship_sku_items'] = $shipped; + $row['ship_skus'] = implode(', ', array_map( + fn (array $item): string => $item['sku_id'] . '×' . $this->formatQty($item['qty']), + $shipped, + )); + $row['jst_labels'] = implode(',', array_keys($labels)); + } + unset($row); + } + + /** + * 同一订单里可能有多个组合装或混着普通商品:优先只取由本行「商品编码」 + * 拆出来的子商品;本行编码本身就是普通商品时取它自己;都对不上再列整单。 + * + * @param list $items + * @return list + */ + private function shippedItemsFor(array $items, string $materialNo): array + { + $materialNo = trim($materialNo); + $selected = []; + if ($materialNo !== '') { + $selected = array_values(array_filter($items, static fn (array $i): bool => $i['combine'] === $materialNo)); + if ($selected === []) { + $selected = array_values(array_filter( + $items, + static fn (array $i): bool => $i['combine'] === '' && $i['sku_id'] === $materialNo, + )); + } + } + if ($selected === []) { + $selected = $items; + } + + $merged = []; + foreach ($selected as $item) { + if ($item['sku_id'] === '') { + continue; + } + $merged[$item['sku_id']] = ($merged[$item['sku_id']] ?? 0.0) + $item['qty']; + } + + $result = []; + foreach ($merged as $skuId => $qty) { + if ($qty > 0) { + $result[] = ['sku_id' => (string) $skuId, 'qty' => $qty]; + } + } + + return $result; + } + + /** + * @param list $soIds + * @param list $oIds + * @return array{0:array>>,1:array>>} + */ + private function loadJstOrders(array $soIds, array $oIds): array + { + $bySo = []; + $byOid = []; + + foreach ($this->jstOrderSources() as $source) { + $columns = ['o_id', 'so_id']; + if ($source['status']) { + $columns[] = 'status'; + } + if ($source['labels']) { + $columns[] = 'labels'; + } + + $orders = []; + foreach (array_chunk($soIds, self::JST_LOOKUP_CHUNK) as $chunk) { + foreach ($this->connection->table($source['orders'])->whereIn('so_id', $chunk)->get($columns) as $order) { + $orders[(string) $order->o_id] = $order; + } + } + foreach (array_chunk($oIds, self::JST_LOOKUP_CHUNK) as $chunk) { + foreach ($this->connection->table($source['orders'])->whereIn('o_id', $chunk)->get($columns) as $order) { + $orders[(string) $order->o_id] = $order; + } + } + if ($orders === []) { + continue; + } + + $itemsByOrder = []; + if ($source['items'] !== '') { + $itemColumns = ['o_id', 'sku_id', 'qty']; + if ($source['combine']) { + $itemColumns[] = 'src_combine_sku_id'; + } + foreach (array_chunk(array_map('intval', array_keys($orders)), self::JST_LOOKUP_CHUNK) as $chunk) { + foreach ($this->connection->table($source['items'])->whereIn('o_id', $chunk)->get($itemColumns) as $item) { + $itemsByOrder[(string) $item->o_id][] = [ + 'sku_id' => trim((string) ($item->sku_id ?? '')), + 'qty' => (float) ($item->qty ?? 0), + 'combine' => trim((string) ($item->src_combine_sku_id ?? '')), + ]; + } + } + } + + foreach ($orders as $oId => $order) { + $entry = [ + 'key' => $source['orders'] . ':' . $oId, + 'status' => trim((string) ($order->status ?? '')), + 'labels' => $this->splitLabels((string) ($order->labels ?? '')), + 'items' => $itemsByOrder[$oId] ?? [], + ]; + $soId = trim((string) ($order->so_id ?? '')); + if ($soId !== '') { + $bySo[$soId][] = $entry; + } + $byOid[$oId][] = $entry; + } + } + + return [$bySo, $byOid]; + } + + /** @return list */ + private function jstOrderSources(): array + { + if ($this->jstOrderSourceCache !== null) { + return $this->jstOrderSourceCache; + } + + $schema = Schema::connection($this->connection->getName()); + $sources = []; + foreach (self::JST_ORDER_SOURCES as [$orders, $items]) { + if (! $schema->hasTable($orders) || ! $schema->hasColumns($orders, ['o_id', 'so_id'])) { + continue; + } + $hasItems = $schema->hasTable($items) && $schema->hasColumns($items, ['o_id', 'sku_id', 'qty']); + $sources[] = [ + 'orders' => $orders, + 'items' => $hasItems ? $items : '', + 'status' => $schema->hasColumn($orders, 'status'), + 'labels' => $schema->hasColumn($orders, 'labels'), + 'combine' => $hasItems && $schema->hasColumn($items, 'src_combine_sku_id'), + ]; + } + + return $this->jstOrderSourceCache = $sources; + } + + /** @return list */ + private function splitTradeNos(string $value): array + { + $parts = preg_split('/[\s,,;;\/]+/u', trim($value)) ?: []; + + return array_values(array_unique(array_filter(array_map('trim', $parts), static fn (string $v): bool => $v !== ''))); + } + + /** @return list */ + private function splitLabels(string $value): array + { + $parts = preg_split('/[,,]+/u', trim($value)) ?: []; + + return array_values(array_unique(array_filter(array_map('trim', $parts), static fn (string $v): bool => $v !== ''))); + } + + private function formatQty(float $qty): string + { + return abs($qty - round($qty)) < 0.0001 + ? (string) (int) round($qty) + : rtrim(rtrim(number_format($qty, 4, '.', ''), '0'), '.'); } private function filteredQuery(array $filters): Builder diff --git a/resources/views/business/pages/product-inventory/online-daifa-price.blade.php b/resources/views/business/pages/product-inventory/online-daifa-price.blade.php index fabe5791..a87f018d 100644 --- a/resources/views/business/pages/product-inventory/online-daifa-price.blade.php +++ b/resources/views/business/pages/product-inventory/online-daifa-price.blade.php @@ -46,6 +46,7 @@ .online-daifa-table th,.online-daifa-table td { padding:.55rem .65rem; border-right:1px solid var(--vip-border,#D8D2C7); border-bottom:1px solid var(--vip-border,#D8D2C7); white-space:nowrap; vertical-align:top; } .online-daifa-table th { position:sticky; top:0; z-index:1; background:var(--vip-content-accent-soft,#F7F0DE); text-align:left; font-weight:700; } .online-daifa-table tr:hover td { background:#fcfaf4; } + .online-daifa-table td.wrap { white-space:normal; min-width:12rem; max-width:22rem; word-break:break-all; } .online-daifa-table .num { text-align:right; font-variant-numeric:tabular-nums; } .online-daifa-table .unmatched { color:var(--vip-danger,#B80000); } .online-daifa-empty { padding:4rem 1rem; text-align:center; color:var(--vip-content-muted,#595959); } @@ -127,7 +128,7 @@ 商品ID商品名称(匹配)店铺名称 代发交易单号店铺交易单号 发货数量订单实付金额代发订单金额差价 - 供应商名称商品编码创建时间 + 供应商名称商品编码实际发货商品编码聚水潭标记|多标签创建时间 @forelse ($rows ?? [] as $row) @@ -152,10 +153,12 @@ {{ $money($row['price_diff']) }} {{ $num($row['supplier_name']) }} {{ $num($row['material_no']) }} + {{ ($row['ship_skus'] ?? '') !== '' ? $row['ship_skus'] : '-' }} + {{ ($row['jst_labels'] ?? '') !== '' ? $row['jst_labels'] : '-' }} {{ $row['workflow_created_at'] ?? '-' }} @empty -
{{ $error ? '镜像读取失败,请稍后重试。' : '暂无符合条件的线上代发价格数据;同步完成后会自动显示。' }}
+
{{ $error ? '镜像读取失败,请稍后重试。' : '暂无符合条件的线上代发价格数据;同步完成后会自动显示。' }}
@endforelse diff --git a/tests/Feature/Business/OnlineDaifaPricePageTest.php b/tests/Feature/Business/OnlineDaifaPricePageTest.php index 341d3680..b0cb9b83 100644 --- a/tests/Feature/Business/OnlineDaifaPricePageTest.php +++ b/tests/Feature/Business/OnlineDaifaPricePageTest.php @@ -229,6 +229,8 @@ class OnlineDaifaPricePageTest extends FeatureTestCase ], 'status_label' => '已完成', 'matched_product' => ['matched' => true, 'name' => '演示商品'], + 'ship_skus' => 'VTYZ010102×1, GDYRB020102×1', + 'jst_labels' => '京东供销订单,京喜', 'workflow_created_at' => '2026-09-01 10:00:00', ]; })()); @@ -252,6 +254,10 @@ class OnlineDaifaPricePageTest extends FeatureTestCase $this->assertStringContainsString("'6927049845766979458", $content); $this->assertStringContainsString("'6927049845766979459", $content); $this->assertStringContainsString('MAT-001', $content); + $this->assertStringContainsString('实际发货商品编码', $content); + $this->assertStringContainsString('聚水潭标记|多标签', $content); + $this->assertStringContainsString('VTYZ010102×1, GDYRB020102×1', $content); + $this->assertStringContainsString('京东供销订单,京喜', $content); } public function test_online_daifa_price_export_requires_a_ready_mirror(): void diff --git a/tests/Unit/EcommerceFinance/OnlineDaifaShipSkuLabelsTest.php b/tests/Unit/EcommerceFinance/OnlineDaifaShipSkuLabelsTest.php new file mode 100644 index 00000000..dcc834db --- /dev/null +++ b/tests/Unit/EcommerceFinance/OnlineDaifaShipSkuLabelsTest.php @@ -0,0 +1,164 @@ + ['driver' => 'sqlite', 'database' => ':memory:', 'prefix' => ''], + 'upstream_mirrors.connection' => 'business_mirror', + ]); + DB::purge('business_mirror'); + + $this->createSchema(); + $this->seedRows(); + } + + public function test_combo_row_lists_the_child_skus_and_order_labels(): void + { + $row = $this->row('3634442001971995'); + + $this->assertSame('VTYZ010102×1, GDYRB020102×1', $row['ship_skus']); + $this->assertSame('店铺-京东供销,京东供销订单,京东快递,京喜,线上发货,以旧换新·国家补贴,指定快递', $row['jst_labels']); + } + + public function test_only_the_children_of_this_rows_combo_are_listed_when_the_order_mixes_items(): void + { + $this->assertSame('CHAIR-A×2', $this->row('5000000000000001', 'ZH-CHAIR-A-2')['ship_skus']); + $this->assertSame('DESK-B×1', $this->row('5000000000000001', 'DESK-B')['ship_skus']); + $this->assertSame('CHAIR-A×2, DESK-B×1', $this->row('5000000000000001', 'UNKNOWN-CODE')['ship_skus']); + } + + public function test_split_parent_orders_are_ignored_and_children_are_merged(): void + { + $row = $this->row('6000000000000001'); + + $this->assertSame('SOFA-L×1, SOFA-R×1', $row['ship_skus']); + $this->assertSame('拆分', $row['jst_labels']); + } + + public function test_rows_without_a_jst_order_stay_blank_and_export_matches_page(): void + { + $repository = app(DingOnlineDaifaPriceMirrorRepository::class); + $this->assertSame('', $this->row('9999999999999999')['ship_skus']); + $this->assertSame('', $this->row('9999999999999999')['jst_labels']); + + $page = $repository->paginate([], 1, 100)['data']; + $export = iterator_to_array($repository->exportRows([]), false); + $this->assertSame(array_column($page, 'ship_skus'), array_column($export, 'ship_skus')); + $this->assertSame(array_column($page, 'jst_labels'), array_column($export, 'jst_labels')); + } + + /** @return array */ + private function row(string $shopTradeNo, ?string $materialNo = null): array + { + $data = app(DingOnlineDaifaPriceMirrorRepository::class)->paginate(['keyword' => $shopTradeNo], 1, 100)['data']; + foreach ($data as $row) { + if ($materialNo === null || $row['material_no'] === $materialNo) { + return $row; + } + } + $this->fail('row not found'); + } + + private function createSchema(): void + { + $schema = Schema::connection('business_mirror'); + $schema->create('business_mirror_table_states', function (Blueprint $table): void { + $table->string('dataset_key')->primary(); + $table->string('status'); + $table->dateTime('initial_completed_at')->nullable(); + $table->dateTime('last_succeeded_at')->nullable(); + }); + $schema->create(DingOnlineDaifaPriceMirrorRepository::TARGET_TABLE, function (Blueprint $table): void { + $table->string('process_instance_id'); + $table->unsignedInteger('detail_index'); + $table->string('product_id')->nullable(); + $table->string('product_name')->nullable(); + $table->string('daifa_trade_no')->nullable(); + $table->string('shop_trade_no')->nullable(); + $table->string('shop_name')->nullable(); + $table->string('payee_name')->nullable(); + $table->string('supplier_name')->nullable(); + $table->string('material_no')->nullable(); + $table->integer('ship_qty')->nullable(); + $table->decimal('paid_amount', 20, 2)->nullable(); + $table->decimal('daifa_amount', 20, 2)->nullable(); + $table->decimal('price_diff', 20, 2)->nullable(); + $table->text('workflow_payload')->nullable(); + $table->text('scheme_payload')->nullable(); + $table->text('task_payload')->nullable(); + $table->dateTime('workflow_created_at')->nullable(); + }); + $schema->create('ops_jst_orders', function (Blueprint $table): void { + $table->unsignedBigInteger('Id')->primary(); + $table->unsignedBigInteger('o_id')->index(); + $table->string('so_id')->nullable()->index(); + $table->string('shop_name')->nullable(); + $table->string('status')->nullable(); + $table->text('labels')->nullable(); + }); + $schema->create('ops_jst_order_item', function (Blueprint $table): void { + $table->unsignedBigInteger('Id')->primary(); + $table->unsignedBigInteger('o_id')->index(); + $table->string('sku_id')->nullable(); + $table->decimal('qty', 20, 4)->nullable(); + $table->string('src_combine_sku_id')->nullable(); + }); + } + + private function seedRows(): void + { + $db = DB::connection('business_mirror'); + $db->table('business_mirror_table_states')->insert([ + 'dataset_key' => DingOnlineDaifaPriceMirrorRepository::DATASET_KEY, + 'status' => 'succeeded', + 'initial_completed_at' => '2026-10-01 00:00:00', + 'last_succeeded_at' => '2026-10-28 09:00:00', + ]); + + $ding = static fn (string $id, int $index, string $soId, string $material): array => [ + 'process_instance_id' => $id, 'detail_index' => $index, 'shop_trade_no' => $soId, + 'shop_name' => '店铺-京东供销', 'material_no' => $material, 'ship_qty' => 1, + 'workflow_payload' => '{"status":"COMPLETED","result":"agree"}', 'scheme_payload' => '[]', 'task_payload' => '[]', + 'workflow_created_at' => '2026-10-0' . $index . ' 10:00:00', + ]; + $db->table(DingOnlineDaifaPriceMirrorRepository::TARGET_TABLE)->insert([ + $ding('P1', 1, '3634442001971995', 'ZH-GDYRB020102-1-VTYZ010102-1'), + $ding('P2', 1, '5000000000000001', 'ZH-CHAIR-A-2'), + $ding('P2', 2, '5000000000000001', 'DESK-B'), + $ding('P2', 3, '5000000000000001', 'UNKNOWN-CODE'), + $ding('P3', 1, '6000000000000001', 'ZH-SOFA'), + $ding('P4', 1, '9999999999999999', 'NONE'), + ]); + + $db->table('ops_jst_orders')->insert([ + ['Id' => 1, 'o_id' => 9557207, 'so_id' => '3634442001971995', 'shop_name' => '店铺-京东供销', 'status' => 'Sent', + 'labels' => '店铺-京东供销,京东供销订单,京东快递,京喜,线上发货,以旧换新·国家补贴,指定快递'], + ['Id' => 2, 'o_id' => 100, 'so_id' => '5000000000000001', 'shop_name' => 'x', 'status' => 'Sent', 'labels' => null], + ['Id' => 3, 'o_id' => 200, 'so_id' => '6000000000000001', 'shop_name' => 'x', 'status' => 'Split', 'labels' => '原单'], + ['Id' => 4, 'o_id' => 201, 'so_id' => '6000000000000001', 'shop_name' => 'x', 'status' => 'Sent', 'labels' => '拆分'], + ['Id' => 5, 'o_id' => 202, 'so_id' => '6000000000000001', 'shop_name' => 'x', 'status' => 'Sent', 'labels' => '拆分'], + ]); + $db->table('ops_jst_order_item')->insert([ + ['Id' => 1, 'o_id' => 9557207, 'sku_id' => 'VTYZ010102', 'qty' => 1, 'src_combine_sku_id' => 'ZH-GDYRB020102-1-VTYZ010102-1'], + ['Id' => 2, 'o_id' => 9557207, 'sku_id' => 'GDYRB020102', 'qty' => 1, 'src_combine_sku_id' => 'ZH-GDYRB020102-1-VTYZ010102-1'], + ['Id' => 3, 'o_id' => 100, 'sku_id' => 'CHAIR-A', 'qty' => 2, 'src_combine_sku_id' => 'ZH-CHAIR-A-2'], + ['Id' => 4, 'o_id' => 100, 'sku_id' => 'DESK-B', 'qty' => 1, 'src_combine_sku_id' => null], + ['Id' => 5, 'o_id' => 200, 'sku_id' => 'SOFA-L', 'qty' => 1, 'src_combine_sku_id' => 'ZH-SOFA'], + ['Id' => 6, 'o_id' => 200, 'sku_id' => 'SOFA-R', 'qty' => 1, 'src_combine_sku_id' => 'ZH-SOFA'], + ['Id' => 7, 'o_id' => 201, 'sku_id' => 'SOFA-L', 'qty' => 1, 'src_combine_sku_id' => 'ZH-SOFA'], + ['Id' => 8, 'o_id' => 202, 'sku_id' => 'SOFA-R', 'qty' => 1, 'src_combine_sku_id' => 'ZH-SOFA'], + ]); + } +} -- 2.47.2