update shopee entity parse
This commit is contained in:
@@ -4,46 +4,59 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Platform\Shopee\EntityParse;
|
||||
|
||||
use App\Constants\ProductStatus;
|
||||
use App\Model\Company;
|
||||
use App\Model\Model as Entity;
|
||||
use App\Model\Store;
|
||||
use App\Platform\AbstractProductParse;
|
||||
use App\Platform\Shopee\Constants\OrderStatus;
|
||||
use App\Constants\PaymentMethod;
|
||||
use Carbon\Carbon;
|
||||
use Hyperf\Collection\LazyCollection;
|
||||
use Hyperf\Context\ApplicationContext;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Shopee 订单解析器
|
||||
* Shopee 产品解析器
|
||||
*
|
||||
* 继承 AbstractOrderParse, 实现 Shopee 平台特定的 Order 解析逻辑
|
||||
* 实现 OrderContract 契约中定义的 parseOrderItems 方法
|
||||
* @TODO 待实现:参照 Tmall\EntityParse\Product 实现 Shopee 产品数据解析
|
||||
*
|
||||
* @attention 此类文件名为 Product.php,但实际处理订单数据,建议重命名为 Order.php
|
||||
* Shopee 产品原始数据结构示例:
|
||||
* {
|
||||
* "item_id": 123456789,
|
||||
* "item_name": "商品名称",
|
||||
* "item_sku": "SKU001",
|
||||
* "item_status": "NORMAL",
|
||||
* "price_info": { "current_price": 99.00, "currency": "SGD" },
|
||||
* "stock_info": { "current_stock": 100 },
|
||||
* "image": { "image_url_list": ["https://..."] },
|
||||
* "model_list": [
|
||||
* { "model_id": 111, "model_sku": "SKU001-A", "current_price": 99.00, "stock_info": { "current_stock": 50 } }
|
||||
* ],
|
||||
* "create_time": 1640000000,
|
||||
* "update_time": 1640100000
|
||||
* }
|
||||
*
|
||||
* 状态映射:
|
||||
* - NORMAL -> ACTIVE
|
||||
* - BANNED -> BANNED
|
||||
* - UNLIST -> INACTIVE
|
||||
* - REVIEWING -> REVIEWING
|
||||
* - SELLER_DELETE -> SELLER_DELETE
|
||||
* - SHOPEE_DELETE -> PLATFORM_DELETE
|
||||
*/
|
||||
class Product extends AbstractProductParse
|
||||
{
|
||||
/**
|
||||
* 公司作用域匹配
|
||||
*
|
||||
* 从 metadata 中提取 company_id,然后查询数据库获取公司对象
|
||||
*
|
||||
* @param array $metadata
|
||||
* @return Company
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function companyScopeMatch(array $metadata): Company
|
||||
{
|
||||
// 验证必需字段
|
||||
if (!isset($metadata['company_id'])) {
|
||||
throw new InvalidArgumentException('company_id is required in metadata');
|
||||
}
|
||||
|
||||
$company_id = $metadata['company_id'];
|
||||
|
||||
$company = Company::find($company_id);
|
||||
|
||||
if (!$company) {
|
||||
@@ -56,29 +69,25 @@ class Product extends AbstractProductParse
|
||||
/**
|
||||
* 店铺作用域匹配
|
||||
*
|
||||
* 从 metadata 中提取 store_id,然后查询数据库获取店铺对象
|
||||
*
|
||||
* @param array $metadata
|
||||
* @return Store
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function storeScopeMatch(array $metadata): Store
|
||||
{
|
||||
// 验证必需字段
|
||||
if (!isset($metadata['platform_store_id'])) {
|
||||
throw new InvalidArgumentException('platform_store_id is required in metadata');
|
||||
}
|
||||
|
||||
$platform_store_id = $metadata['platform_store_id'];
|
||||
|
||||
$shopee_platform_id = 25;
|
||||
|
||||
$store = Store::where('platform_id','=', $shopee_platform_id)
|
||||
$store = Store::where('platform_id', '=', $shopee_platform_id)
|
||||
->where('platform_store_id', '=', $platform_store_id)
|
||||
->first();
|
||||
|
||||
if (!$store) {
|
||||
throw new InvalidArgumentException("Platform shopee store id {$shopee_platform_id} not found");
|
||||
throw new InvalidArgumentException("Shopee store with platform_store_id {$platform_store_id} not found");
|
||||
}
|
||||
|
||||
return $store;
|
||||
@@ -87,152 +96,136 @@ class Product extends AbstractProductParse
|
||||
/**
|
||||
* 实体数据映射
|
||||
*
|
||||
* 将原始数据映射为可供 Model 使用的数组集合
|
||||
* @TODO 待实现:解析 Shopee 产品原始数据
|
||||
*
|
||||
* @attention 当前返回格式为 ['order' => [...], 'items' => [...]]
|
||||
* 但 ProductConsumer 第 153-157 行期望直接返回订单数据数组(参考 Tmall 实现)
|
||||
* 需要调整返回格式以兼容 ProductConsumer 的 upsert 操作
|
||||
*
|
||||
* @TODO 调整返回格式:
|
||||
* - 方案1:改为直接返回订单数据数组(与 Tmall 一致)
|
||||
* - 方案2:修改 ProductConsumer 以支持当前的嵌套结构
|
||||
*
|
||||
* @param array $raw_data 原始数据数组,通常来自 $data['raw_data']
|
||||
* @return LazyCollection 返回 LazyCollection,每个元素为可供 Model::fill() 使用的数组
|
||||
* @param array $raw_data 原始数据数组
|
||||
* @return LazyCollection
|
||||
*/
|
||||
public function entityMap(array $raw_data): LazyCollection
|
||||
{
|
||||
// 使用 LazyCollection 进行延迟处理,提高性能
|
||||
// TODO: 实现 Shopee 产品数据映射
|
||||
// 参考 Tmall\EntityParse\Product::entityMap() 实现
|
||||
return LazyCollection::make(function () use ($raw_data) {
|
||||
// 如果 raw_data 是单个记录,转换为数组
|
||||
$records = isset($raw_data[0]) ? $raw_data : [$raw_data];
|
||||
|
||||
foreach ($records as $record) {
|
||||
dump($record);
|
||||
// TODO: 解析 model_list(规格列表)
|
||||
// 无规格时返回单条记录,有规格时每个 model 返回一条记录
|
||||
yield $this->mapSingleProduct($record, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 映射单个产品记录
|
||||
*
|
||||
* @TODO 待实现:根据 Shopee 实际数据结构完善字段映射
|
||||
*
|
||||
* @param array $record 商品主记录
|
||||
* @param array|null $model 规格记录
|
||||
* @return array
|
||||
*/
|
||||
private function mapSingleProduct(array $record, ?array $model): array
|
||||
{
|
||||
$raw = \json_encode($record);
|
||||
$platform_item_id = (string) ($record['item_id'] ?? '');
|
||||
$platform_model_id = $model ? (string) ($model['model_id'] ?? '') : null;
|
||||
|
||||
return [
|
||||
'company_id' => $this->getCompany()->id,
|
||||
'platform_id' => $this->getPlatform()->id,
|
||||
'store_id' => $this->getStore()->id,
|
||||
'status_id' => $this->getProductStatusId($record['item_status'] ?? 'NORMAL'),
|
||||
'type_id' => 1,
|
||||
'warehouse_id' => null,
|
||||
'sub_warehouse_id' => null,
|
||||
'platform_item_id' => $platform_item_id,
|
||||
'platform_model_id' => $platform_model_id,
|
||||
'origin_sku_id' => $model['model_sku'] ?? $record['item_sku'] ?? null,
|
||||
'mapped_sku_id' => null,
|
||||
'barcode' => null,
|
||||
'hscode' => null,
|
||||
'bundled' => null,
|
||||
'price' => $model['current_price'] ?? $record['price_info']['current_price'] ?? '0.00',
|
||||
'currency' => $record['price_info']['currency'] ?? 'USD',
|
||||
'num' => $model['stock_info']['current_stock'] ?? $record['stock_info']['current_stock'] ?? 0,
|
||||
'url' => null,
|
||||
'picture' => $record['image']['image_url_list'][0] ?? null,
|
||||
'name' => $record['item_name'] ?? null,
|
||||
'raw' => $raw,
|
||||
'ext' => null,
|
||||
'hash' => \md5($raw),
|
||||
'created_date' => isset($record['create_time'])
|
||||
? Carbon::createFromTimestamp($record['create_time'])
|
||||
: null,
|
||||
'updated_date' => isset($record['update_time'])
|
||||
? Carbon::createFromTimestamp($record['update_time'])
|
||||
: null,
|
||||
'created_at' => date('Y-m-d H:i:s'),
|
||||
'updated_at' => date('Y-m-d H:i:s'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取唯一键字段(对应数据库唯一索引)
|
||||
*
|
||||
* 对应数据库约束:
|
||||
* UNIQUE INDEX orders_store_platform_order_unique (store_id, platform_order_id)
|
||||
* 获取唯一键字段
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getUniqueBy(): array
|
||||
{
|
||||
return ['store_id', 'platform_product_id'];
|
||||
return ['store_id', 'platform_item_id', 'platform_model_id'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取可更新字段列表
|
||||
*
|
||||
* 排除:主键、唯一键、创建时间、关联 ID
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getUpdateFields(): array
|
||||
{
|
||||
// 手动指定(推荐:明确且高效,无数据库查询开销)
|
||||
return [
|
||||
'order_status_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',
|
||||
'updated_date',
|
||||
'paid_date',
|
||||
'shipping_date',
|
||||
'zipcode',
|
||||
'city',
|
||||
'province',
|
||||
'country',
|
||||
'status_id',
|
||||
'type_id',
|
||||
'warehouse_id',
|
||||
'sub_warehouse_id',
|
||||
'origin_sku_id',
|
||||
'mapped_sku_id',
|
||||
'barcode',
|
||||
'hscode',
|
||||
'bundled',
|
||||
'price',
|
||||
'currency',
|
||||
'num',
|
||||
'url',
|
||||
'picture',
|
||||
'name',
|
||||
'raw',
|
||||
'ext',
|
||||
'hash',
|
||||
'updated_date',
|
||||
'updated_at',
|
||||
];
|
||||
|
||||
// 动态计算方案(如果表字段经常变化,可以使用):
|
||||
// $entity = $this->entityMatch([
|
||||
// 'company_id' => $this->getCompany()->id,
|
||||
// 'platform_id' => $this->getPlatform()->id,
|
||||
// 'store_id' => $this->getStore()->id,
|
||||
// ]);
|
||||
// $excludeFields = array_merge(
|
||||
// ['id', 'created_at', 'created_date', 'company_id', 'platform_id'],
|
||||
// $this->getUniqueBy()
|
||||
// );
|
||||
// return $this->getTableColumnsExcept($entity, $excludeFields);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 Shopee 产品状态确定对应的本地订单状态
|
||||
* 获取产品状态 ID
|
||||
*
|
||||
* @required ProductConsumer 要求实现此方法(第 130-132 行)
|
||||
* @see \App\Constants\OrderStatus
|
||||
* 将 Shopee 产品状态映射到本地 ProductStatus 枚举
|
||||
*
|
||||
* @param string $platform_order_status Shopee 平台订单状态
|
||||
* @return int 本地订单状态 ID
|
||||
* @param string $platform_status Shopee 平台状态
|
||||
* @return int
|
||||
*/
|
||||
public function getProductStatusId(string $platform_order_status): int
|
||||
public function getProductStatusId(string $platform_status): int
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Shopee 产品状态到本地产品状态的映射表
|
||||
*
|
||||
* @see \App\Platform\Shopee\Constants\ProductStatus Shopee 产品订单状态枚举
|
||||
* @see \App\Constants\OrderStatus 本地产品状态枚举
|
||||
*
|
||||
* @return array<string, int>
|
||||
*/
|
||||
private function ProducttatusMap(): array
|
||||
{
|
||||
return [
|
||||
// 未付款 -> 等待付款
|
||||
'UNPAID' => \App\Constants\OrderStatus::PAYMENT_PENDING->value,
|
||||
|
||||
// 可发货(已付款,等待卖家安排发货)-> 付款完成
|
||||
'READY_TO_SHIP' => \App\Constants\OrderStatus::PAYMENT_COMPLETE->value,
|
||||
|
||||
// 已处理(卖家已安排发货并获取物流单号)-> 等待发货
|
||||
'PROCESSED' => \App\Constants\OrderStatus::AWAITING_SHIPMENT->value,
|
||||
|
||||
// 重新发货(3PL 取件失败,需要重新安排发货)-> 等待发货
|
||||
'RETRY_SHIP' => \App\Constants\OrderStatus::AWAITING_SHIPMENT->value,
|
||||
|
||||
// 已发货(包裹已交给 3PL 或已被 3PL 取走)-> 已发货
|
||||
'SHIPPED' => \App\Constants\OrderStatus::SHIPPED->value,
|
||||
|
||||
// 待确认收货(买家已收到订单)-> 已发货
|
||||
'TO_CONFIRM_RECEIVE' => \App\Constants\OrderStatus::SHIPPED->value,
|
||||
|
||||
// 取消中(订单取消正在处理)-> 取消请求中
|
||||
'IN_CANCEL' => \App\Constants\OrderStatus::CANCEL_REQUESTED->value,
|
||||
|
||||
// 已取消 -> 取消确认
|
||||
'CANCELLED' => \App\Constants\OrderStatus::CANCEL_CONFIRMED->value,
|
||||
|
||||
// 退货中(买家请求退货,退货正在处理)-> 取消请求中
|
||||
'TO_RETURN' => \App\Constants\OrderStatus::CANCEL_REQUESTED->value,
|
||||
|
||||
// 已完成 -> 完成
|
||||
'COMPLETED' => \App\Constants\OrderStatus::FINISHED->value,
|
||||
$status_map = [
|
||||
'NORMAL' => ProductStatus::ACTIVE->value,
|
||||
'BANNED' => ProductStatus::BANNED->value,
|
||||
'UNLIST' => ProductStatus::INACTIVE->value,
|
||||
'REVIEWING' => ProductStatus::REVIEWING->value,
|
||||
'SELLER_DELETE' => ProductStatus::SELLER_DELETE->value,
|
||||
'SHOPEE_DELETE' => ProductStatus::PLATFORM_DELETE->value,
|
||||
];
|
||||
}
|
||||
|
||||
return $status_map[$platform_status] ?? ProductStatus::ACTIVE->value;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user