From 45728f4cdf2fcbaf72f02ad05d7f583071932472 Mon Sep 17 00:00:00 2001 From: Nick Zeng Date: Fri, 30 Jan 2026 17:03:35 +0800 Subject: [PATCH] add order entity parse --- .../app/Platform/Tmall/EntityParse/Order.php | 201 ++++++++++++++++-- 1 file changed, 188 insertions(+), 13 deletions(-) diff --git a/backend/app/Platform/Tmall/EntityParse/Order.php b/backend/app/Platform/Tmall/EntityParse/Order.php index 80edd0e..df0aeea 100644 --- a/backend/app/Platform/Tmall/EntityParse/Order.php +++ b/backend/app/Platform/Tmall/EntityParse/Order.php @@ -4,10 +4,13 @@ declare(strict_types=1); namespace App\Platform\Tmall\EntityParse; +use App\Constants\OrderStatus; use App\Model\Company; use App\Model\Model as Entity; use App\Model\Store; use App\Entity\Parse\EntityParse; +use App\Constants\PaymentMethod; +use App\Constants\OrderType; use Hyperf\Collection\LazyCollection; use InvalidArgumentException; @@ -88,20 +91,45 @@ class Order extends EntityParse $records = isset($rawData[0]) ? $rawData : [$rawData]; foreach ($records as $record) { + + $raw = \json_encode($record); // 映射每条原始数据到 Model 可用的数组格式 yield [ - 'platform_id' => $this->getPlatform()->id, 'company_id' => $this->getCompany()->id, + 'platform_id' => $this->getPlatform()->id, 'store_id' => $this->getStore()->id, - 'unique_id' => $record['unique_id'] ?? $this->getData()['unique_id'] ?? null, - 'raw_data' => json_encode($record), - // 根据实际业务需求映射其他字段 - // 例如: - // 'order_id' => $record['order_id'] ?? null, - // 'order_status' => $record['order_status'] ?? null, - // 'order_amount' => $record['order_amount'] ?? 0, - // ... + 'order_status_id' => $this->getOrderStatusId($record['status']), + 'platform_order_id' => $record['tid'], + 'payment_method_id' => $this->getPaymentMethodId(), + 'presale' => false, + 'total_amount' => $record['total_fee'], + 'total_paid' => $record['payment'], + 'total_discount' => $record['discount_fee'], + // 实际收到的金额,如果平台有商家补贴,此金额需要重新计算 - 部分退款订单也影响此字段的值 + 'total_received' => $record['received_payment'], + 'freight_fee' => 0, + 'tax_fee' => 0, + 'discount_fee' => 0, + 'commission_fee' => 0, + 'coupon_amount' => 0, + 'voucher_amount' => 0, + 'order_type_id' => OrderType::Normor_Order->value, + 'created_date' => $record['created'], + 'updated_date' => $record['modified'] ?? null, + 'paid_date' => $record['pay_time'] ?? null, + 'shipping_date' => $record['consign_time'] ?? null, + 'zipcode' => $record['receiver_zip'] ?? '', + 'city' => $record['receiver_city'] ?? '', + 'province' => $record['receiver_state'] ?? '', + 'country' => 'CN', + 'raw' => $raw, + 'ext' => null, + 'buyer_user_id' => $record['buyer_open_uid'], + 'raw_hash' => \md5($raw), + 'created_at' => date('Y-m-d H:i:s'), + 'updated_at' => date('Y-m-d H:i:s'), ]; + } }); } @@ -115,8 +143,9 @@ class Order extends EntityParse */ public function getUniqueBy(): array { - // 天猫订单的唯一性由店铺 + 平台订单号确定 - return ['store_id', 'platform_order_id']; + // 天猫订单的唯一性由店铺 + 平台订单号确定(实际上由平台订单号就已经足够) + // @attention create_date 为数据库强制要求,必需携带 + return ['store_id', 'platform_order_id', 'created_date']; } /** @@ -130,14 +159,39 @@ class Order extends EntityParse public function getUpdateFields(): array { // 方案1:手动指定可更新字段(推荐,最明确) + // 根据实际业务需求添加其他可更新字段 return [ + 'company_id', + 'platform_id', + 'store_id', 'order_status_id', + 'platform_order_id', 'payment_method_id', - 'buyer_user_id', + 'presale', 'total_amount', + 'total_paid', + 'total_discount', + 'total_received', + 'freight_fee', + 'tax_fee', + 'discount_fee', + 'commission_fee', + 'coupon_amount', + 'voucher_amount', + 'order_type_id', + 'created_date', 'updated_date', + 'paid_date', + 'shipping_date', + 'zipcode', + 'city', + 'province', + 'country', 'raw', - // 根据实际业务需求添加其他可更新字段 + 'ext', + 'buyer_user_id', + 'raw_hash', + 'updated_at', // 更新时刷新,created_at 不包含以保留原始创建时间 ]; // 方案2:动态计算(如果字段较多且经常变动) @@ -148,4 +202,125 @@ class Order extends EntityParse // ); // return $this->getTableColumnsExcept($entity, $excludeFields); } + + + + /** + * 根据淘宝订单状态确定对应的 Tools 订单状态 + * + * @param string $platformOrderStatus 淘宝平台订单状态 + * @return int Tools 订单状态 ID + */ + public function getOrderStatusId(string $platformOrderStatus): int + { + $statusMap = $this->orderStatusMap(); + + return $statusMap[$platformOrderStatus] ?? OrderStatus::PAYMENT_COMPLETE->value; + } + + /** + * 淘宝订单状态到 Tools 订单状态的映射 + * + * @return array + */ + private function orderStatusMap(): array + { + return [ + // Payment pending (1) + 'TRADE_NO_CREATE_PAY' => OrderStatus::PAYMENT_PENDING->value, // 没有创建支付宝交易 + 'WAIT_BUYER_PAY' => OrderStatus::PAYMENT_PENDING->value, // 等待买家付款 + 'PAY_PENDING' => OrderStatus::PAYMENT_PENDING->value, // 国际信用卡支付付款确认中 + 'WAIT_PRE_AUTH_CONFIRM' => OrderStatus::PAYMENT_PENDING->value, // 0元购合约中 + + // Payment fail (2) + 'TRADE_CLOSED_BY_TAOBAO' => OrderStatus::PAYMENT_FAIL->value, // 付款以前,卖家或买家主动关闭交易 + + // Payment complete (3) + 'SELLER_CONSIGNED_PART' => OrderStatus::PAYMENT_COMPLETE->value, // 卖家部分发货 + 'WAIT_SELLER_SEND_GOODS' => OrderStatus::PAYMENT_COMPLETE->value, // 等待卖家发货,即:买家已付款 + + // Awaiting shipment (4) + 'PAID_FORBID_CONSIGN' => OrderStatus::AWAITING_SHIPMENT->value, // 拼团中订单或者发货强管控的订单,已付款但禁止发货 + + // Shipped (5) + 'WAIT_BUYER_CONFIRM_GOODS' => OrderStatus::SHIPPED->value, // 等待买家确认收货,即:卖家已发货 + 'TRADE_BUYER_SIGNED' => OrderStatus::SHIPPED->value, // 买家已签收,货到付款专用 + + // Finished (8) + 'TRADE_FINISHED' => OrderStatus::FINISHED->value, // 交易成功 + + // Cancel before shipping (9) + 'TRADE_CLOSED' => OrderStatus::CANCEL_BEFORE_SHIPPING->value, // 付款以后用户退款成功,交易自动关闭 + ]; + } + + + public function getPaymentMethodId() : int + { + // @attention 暂时固定返回支付方式为支付宝, 其他平台需要定义付款方式映射 + return PaymentMethod::ALIPAY_CN->value; + } + + + /** + * + * orderItems 的输出结果为 \App\Model\OrderItem::fill() 可以直接使用的数据格式 + * + * @param array $rawData + * @return array + */ + + public function formatOrderItemsFromRaw(array $rawData, array $platform_orders_id_to_local_db_order_id_map): array + { + // 由于 $rawData 是批量数据,包含多条订单结果,因此订单子项需要从集合中提取 + // Tmall 平台响应体的数据格式为: collection->payload->orders + // $platform_orders_id_to_local_db_order_id_map 内部元素数据格式为 [platform_order_id => local db order id] + + if(empty($rawData['orders'])){ + return []; + } + + $items = []; + + foreach ($rawData as $raw_orders) { + foreach ($raw_orders['orders'] 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']); + } + } + + return $items; + } + + /** + * Tmall 订单子项映射转换 + * @return void + */ + private function tmallOrderItemMap(array $item, string $platform_order_id, int $parent_order_id, string $parent_order_created_date): array + { + + //@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, + 'sub_order_id' => $item['oid'], + // @attention sku 的处理需要仅以规范和约束,确保 sku 准确 + 'sub_order_type_id' => '', + 'product_id' => '', + 'platform_product_id' =>$item['num_iid'], + 'product_sku' => $item['outer_sku_id'], + 'product_barcode' => '', + 'unit_price' => $item['price'], + 'quantity' => $item['num'], + 'discount' => $item['discount_fee'], + 'total' => $item['divide_order_fee'], + // @attention 扩展字段,用来存储其他信息 + 'ext' => '', + 'created_date' => $parent_order_created_date, + ]; + } }