From 39ef3acc1f5eb1fe4dd9e7418f61e28213b50247 Mon Sep 17 00:00:00 2001 From: Nick Zeng Date: Mon, 2 Feb 2026 15:13:46 +0800 Subject: [PATCH] fix order item fail to save --- backend/app/Platform/OrderConsumer.php | 37 ++++++---- .../app/Platform/Tmall/EntityParse/Order.php | 73 ++++++++++++++++--- 2 files changed, 85 insertions(+), 25 deletions(-) diff --git a/backend/app/Platform/OrderConsumer.php b/backend/app/Platform/OrderConsumer.php index 94963bb..206de7d 100644 --- a/backend/app/Platform/OrderConsumer.php +++ b/backend/app/Platform/OrderConsumer.php @@ -12,7 +12,6 @@ use Hyperf\Amqp\Message\ConsumerMessage; use Hyperf\Amqp\Result; use Hyperf\Amqp\Producer; use PhpAmqpLib\Message\AMQPMessage; -use Hyperf\Di\Annotation\Inject; use Hyperf\DbConnection\Db; use App\Model\OrderItem; use Exception; @@ -186,6 +185,7 @@ class OrderConsumer extends ConsumerMessage // 在数据库事务中尝试对 $entityMapResult 中的元素进行持久化,如果没有问题, 则返回 ACK,否则这是 NACK 且 回滚事务。 return Result::ACK; + } catch (Throwable $error) { dump("=== Error Caught ==="); dump("Error: " . $error->getMessage()); @@ -322,6 +322,14 @@ class OrderConsumer extends ConsumerMessage */ protected function processOrderItems(array $items_by_platform_order_id): void { + dump('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'); + + dump('processOrderItems'); + dump($items_by_platform_order_id); + + dump('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'); + + if (empty($items_by_platform_order_id)) { dump('No order items to process'); return; @@ -331,16 +339,11 @@ class OrderConsumer extends ConsumerMessage $all_items_to_upsert = []; $item_sub_order_ids_by_platform_order_id = []; // 记录每个平台订单的新子项 ID 列表 - foreach ($items_by_platform_order_id as $platform_order_id => $items) { - $sub_order_ids = []; - - foreach ($items as $item) { - // order_id 已由 formatOrderItemsFromRaw 通过 idMapping 填充 - $all_items_to_upsert[] = $item; - $sub_order_ids[] = $item['sub_order_id']; - } - - $item_sub_order_ids_by_platform_order_id[$platform_order_id] = $sub_order_ids; + foreach ($items_by_platform_order_id as $item) { + $platform_order_id = $item['platform_order_id']; + // order_id 已由 formatOrderItemsFromRaw 通过 idMapping 填充 + $all_items_to_upsert[] = $item; + $item_sub_order_ids_by_platform_order_id[$platform_order_id] = $item['sub_order_id']; } if (empty($all_items_to_upsert)) { @@ -378,6 +381,7 @@ class OrderConsumer extends ConsumerMessage // 4. 批量删除不在新数据中的旧 OrderItem(完全同步策略) // 利用 hypertable 按 created_date 分区的特性,确保删除条件包含 created_date 以触发分区裁剪 // 此部分业务应该很少被调用,订单子项新增或删减的情况很少见 + $this->deleteObsoleteOrderItems($all_items_to_upsert); dump("Order items processing completed"); @@ -405,9 +409,10 @@ class OrderConsumer extends ConsumerMessage $new_item_keys = []; // 集合 B foreach ($new_items as $item) { + // 统一格式化为 Y-m-d H:i:s(不带时区),确保与数据库查询结果匹配 $created_date = $item['created_date'] instanceof \DateTimeInterface - ? $item['created_date']->format('Y-m-d H:i:sP') - : $item['created_date']; + ? $item['created_date']->format('Y-m-d H:i:s') + : (new \DateTime($item['created_date']))->format('Y-m-d H:i:s'); // 订单级别的键(用于限定查询范围) $order_key = sprintf('%d|%s|%s', $item['store_id'], $item['platform_order_id'], $created_date); @@ -448,9 +453,10 @@ class OrderConsumer extends ConsumerMessage $created_dates_to_delete = []; foreach ($existing_items as $existing) { + // 统一格式化为 Y-m-d H:i:s(不带时区),与新数据保持一致 $existing_created_date = $existing->created_date instanceof \DateTimeInterface - ? $existing->created_date->format('Y-m-d H:i:sP') - : (string) $existing->created_date; + ? $existing->created_date->format('Y-m-d H:i:s') + : (new \DateTime((string) $existing->created_date))->format('Y-m-d H:i:s'); $existing_key = sprintf( '%d|%s|%s|%s', @@ -467,6 +473,7 @@ class OrderConsumer extends ConsumerMessage } } + // 4. 批量删除(利用 hypertable 主键 (id, created_date) 进行高效删除) if (!empty($ids_to_delete)) { $deleted = OrderItem::query() diff --git a/backend/app/Platform/Tmall/EntityParse/Order.php b/backend/app/Platform/Tmall/EntityParse/Order.php index b11688a..7dad2bb 100644 --- a/backend/app/Platform/Tmall/EntityParse/Order.php +++ b/backend/app/Platform/Tmall/EntityParse/Order.php @@ -266,10 +266,16 @@ class Order extends EntityParse * * orderItems 的输出结果为 \App\Model\OrderItem::fill() 可以直接使用的数据格式 * - * @param array $raw_data - * @return array + * @param array $raw_data + * @param array $platform_orders_id_to_local_db_order_id_map + * + * + * @param array $order_items_to_product_id_map = [ + * num_iid => local_db_product_id + * ] + * @return array */ - public function formatOrderItemsFromRaw(array $raw_data, array $platform_orders_id_to_local_db_order_id_map): array + public function formatOrderItemsFromRaw(array $raw_data, array $platform_orders_id_to_local_db_order_id_map, array $order_items_to_product_id_map = []): array { // 由于 $raw_data 是批量数据,包含多条订单结果,因此订单子项需要从集合中提取 // Tmall 平台响应体的数据格式为: collection->payload->orders @@ -278,10 +284,12 @@ class Order extends EntityParse $items = []; foreach ($raw_data as $raw_orders) { - foreach ($raw_orders['orders'] as $raw_order_item) { + foreach ($raw_orders['orders']['order'] as $raw_order_item) { // 数据库中父订单 id $db_order_id = $platform_orders_id_to_local_db_order_id_map[$raw_orders['tid']]; - $items[] = $this->tmallOrderItemMap($raw_order_item, $raw_orders['tid'], $db_order_id, $raw_orders['created']); + $platform_order_id = strval($raw_orders['tid']); + $local_product_id = empty($order_items_to_product_id_map) || !isset($order_items_to_product_id_map[$raw_order_item['num_iid']]) ? 0 : $order_items_to_product_id_map[$raw_order_item['num_iid']]; + $items[] = $this->tmallOrderItemMap($raw_order_item, $platform_order_id, $db_order_id, $raw_orders['created'], $local_product_id); } } @@ -292,20 +300,65 @@ class Order extends EntityParse * Tmall 订单子项映射转换 * @return void */ - private function tmallOrderItemMap(array $item, string $platform_order_id, int $parent_order_id, string $parent_order_created_date): array + private function tmallOrderItemMap(array $item, string $platform_order_id, int $parent_order_id, string $parent_order_created_date, int $local_product_id = 0): array { + // $item = [ + // "adjust_fee" => "0.00", + // "buyer_rate" => false, + // "cid" => 50026872, + // "consign_due_time" => "2_5", + // "discount_fee" => "231.98", + // "divide_order_fee" => "504.00", + // "is_bybt_order" => false, + // "is_daixiao" => false, + // "is_idle" => "0", + // "is_jzfx" => false, + // "is_oversold" => false, + // "nr_outer_iid" => "768990037900", + // "num" => 1, + // "num_iid" => 637901668632, + // "oid" => 4932549972242808538, + // "oid_str" => "4932549972242808538", + // "order_attr" => "{"esDate":"2025-12-14","pushTime":"2025-12-09 11:30:00"}", + // "order_from" => "WAP,WAP", + // "outer_iid" => "768990037900", + // "outer_sku_id" => "768990037900", + // "part_mjz_discount" => "15.00", + // "payment" => "504.00", + // "pic_path" => "https://img.alicdn.com/bao/uploaded/i4/2413132940/O1CN01duCukP1XaZLX2jVQy_!!2413132940.jpg", + // "price" => "693.00", + // "refund_status" => "NO_REFUND", + // "s_tariff_fee" => "0.00", + // "seller_rate" => false, + // "seller_type" => "B", + // "sku_id" => "6123547511321", + // "sku_properties_name" => "颜色分类:高倍Omega鱼油软胶囊 180粒/瓶", + // "snapshot_url" => "za:4932549972242808538_1", + // "status" => "WAIT_SELLER_SEND_GOODS", + // "store_code" => "STORE_11388627", + // "sub_order_tax_fee" => "57.98", + // "sub_order_tax_promotion_fee" => "0.00", + // "sub_order_tax_rate" => "0", + // "tax_coupon_discount" => "57.98", + // "tax_free" => true, + // "title" => "【优惠价】NordicNaturals挪威小鱼dha深海鱼油Omega3成人rTG高纯度epa胶囊", + // "total_fee" => "461.02", + // ] + + //@TODO order item 的业务映射需进一步补全 return [ 'company_id' => $this->getCompany()->id, 'platform_id' => $this->getPlatform()->id, 'store_id' => $this->getStore()->id, 'order_id' => $parent_order_id, - 'platform_order_id' => $platform_order_id, + 'platform_order_id' => strval($platform_order_id), 'sub_order_id' => $item['oid'], // @attention sku 的处理需要仅以规范和约束,确保 sku 准确 - 'sub_order_type_id' => '', - 'product_id' => '', + 'sub_order_type_id' => null, + // @attention 表示未找到产品 id + 'product_id' => $local_product_id, 'platform_product_id' =>$item['num_iid'], // @attention @TODO 需要对 运营侧的产品维护做进一步规范 'product_sku' => $item['outer_sku_id'] ?? null, @@ -316,7 +369,7 @@ class Order extends EntityParse 'discount' => $item['discount_fee'], 'total' => $item['divide_order_fee'], // @attention 扩展字段,用来存储其他信息 - 'ext' => '', + 'ext' => null, 'created_date' => $parent_order_created_date, ]; }