feat(woocommerce): 重构订单物流追踪信息处理方式

使用元数据中的物流追踪信息替代原有接口
移除冗余的履行信息获取逻辑
This commit is contained in:
tikkhun 2026-01-23 18:29:20 +08:00
parent a556ab69bf
commit 16d27179e7
2 changed files with 59 additions and 66 deletions

View File

@ -31,11 +31,13 @@ import {
WooProductSearchParams, WooProductSearchParams,
WpMediaGetListParams, WpMediaGetListParams,
WooFulfillment, WooFulfillment,
MetaDataFulfillment,
} from '../dto/woocommerce.dto'; } from '../dto/woocommerce.dto';
import { Site } from '../entity/site.entity'; import { Site } from '../entity/site.entity';
import { WPService } from '../service/wp.service'; import { WPService } from '../service/wp.service';
import { BatchOperationDTO, BatchOperationResultDTO } from '../dto/batch.dto'; import { BatchOperationDTO, BatchOperationResultDTO } from '../dto/batch.dto';
import { toArray, toNumber } from '../utils/trans.util'; import { toArray, toNumber } from '../utils/trans.util';
import dayjs = require('dayjs');
export class WooCommerceAdapter implements ISiteAdapter { export class WooCommerceAdapter implements ISiteAdapter {
// 构造函数接收站点配置与服务实例 // 构造函数接收站点配置与服务实例
@ -255,7 +257,7 @@ export class WooCommerceAdapter implements ISiteAdapter {
} }
mapMediaSearchParams(params: UnifiedSearchParamsDTO): Partial<WpMediaGetListParams> { mapMediaSearchParams(params: UnifiedSearchParamsDTO): Partial<WpMediaGetListParams> {
const page = params.page const page = params.page
const per_page = Number( params.per_page ?? 20); const per_page = Number(params.per_page ?? 20);
return { return {
...params.where, ...params.where,
@ -293,12 +295,12 @@ export class WooCommerceAdapter implements ISiteAdapter {
throw new Error('Method not implemented.'); throw new Error('Method not implemented.');
} }
async updateMedia(where: {id: string | number}, data: any): Promise<any> { async updateMedia(where: { id: string | number }, data: any): Promise<any> {
// 更新媒体信息 // 更新媒体信息
return await this.wpService.updateMedia(Number(this.site.id), Number(where.id), data); return await this.wpService.updateMedia(Number(this.site.id), Number(where.id), data);
} }
async deleteMedia(where: {id: string | number}): Promise<boolean> { async deleteMedia(where: { id: string | number }): Promise<boolean> {
// 删除媒体资源 // 删除媒体资源
await this.wpService.deleteMedia(Number(this.site.id), Number(where.id), true); await this.wpService.deleteMedia(Number(this.site.id), Number(where.id), true);
return true; return true;
@ -348,7 +350,7 @@ export class WooCommerceAdapter implements ISiteAdapter {
// 集合过滤参数 // 集合过滤参数
if (where.exclude) mapped.exclude = toArray(where.exclude); if (where.exclude) mapped.exclude = toArray(where.exclude);
if (where.ids || where.number || where.id || where.include) mapped.include = [...new Set([where.number,where.id,...toArray(where.ids),...toArray(where.include)])].filter(Boolean); if (where.ids || where.number || where.id || where.include) mapped.include = [...new Set([where.number, where.id, ...toArray(where.ids), ...toArray(where.include)])].filter(Boolean);
if (toNumber(where.offset) !== undefined) mapped.offset = Number(where.offset); if (toNumber(where.offset) !== undefined) mapped.offset = Number(where.offset);
if (where.parent ?? where.parentId) mapped.parent = toArray(where.parent ?? where.parentId); if (where.parent ?? where.parentId) mapped.parent = toArray(where.parent ?? where.parentId);
if (where.parent_exclude ?? where.parentExclude) mapped.parent_exclude = toArray(where.parent_exclude ?? where.parentExclude); if (where.parent_exclude ?? where.parentExclude) mapped.parent_exclude = toArray(where.parent_exclude ?? where.parentExclude);
@ -397,14 +399,17 @@ export class WooCommerceAdapter implements ISiteAdapter {
mapPlatformToUnifiedOrder(item: WooOrder): UnifiedOrderDTO { mapPlatformToUnifiedOrder(item: WooOrder): UnifiedOrderDTO {
// 将 WooCommerce 订单数据映射为统一订单DTO // 将 WooCommerce 订单数据映射为统一订单DTO
// 包含账单地址与收货地址以及创建与更新时间 // 包含账单地址与收货地址以及创建与更新时间
// 映射物流追踪信息,将后端格式转换为前端期望的格式 // 映射物流追踪信息,将后端格式转换为前端期望的格式
const fulfillments = (item.fulfillments || []).map((track) => ({ const metaFulfillments: MetaDataFulfillment[] = item.meta_data?.find?.(_meta => _meta.key === "_wc_shipment_tracking_items")?.value || []
const fulfillments = metaFulfillments?.map?.((track) => {
return ({
tracking_id: track.tracking_id, tracking_id: track.tracking_id,
tracking_number: track.tracking_number, tracking_number: track.tracking_number,
tracking_product_code: track.tracking_product_code,
shipping_provider: track.tracking_provider, shipping_provider: track.tracking_provider,
date_created: track.data_sipped, date_created: dayjs(track.date_shipped),
})); })
});
return { return {
id: item.id, id: item.id,
@ -446,7 +451,7 @@ export class WooCommerceAdapter implements ISiteAdapter {
} }
// 订单操作方法 // 订单操作方法
async getOrder(where: {id: string | number}): Promise<UnifiedOrderDTO> { async getOrder(where: { id: string | number }): Promise<UnifiedOrderDTO> {
// 获取单个订单详情 // 获取单个订单详情
const api = this.wpService.createApi(this.site, 'wc/v3'); const api = this.wpService.createApi(this.site, 'wc/v3');
const res = await api.get(`orders/${where.id}`); const res = await api.get(`orders/${where.id}`);
@ -457,30 +462,8 @@ export class WooCommerceAdapter implements ISiteAdapter {
const requestParams = this.mapOrderSearchParams(params); const requestParams = this.mapOrderSearchParams(params);
const { items, total, totalPages, page, per_page } = await this.wpService.fetchResourcePaged<any>(this.site, 'orders', requestParams); const { items, total, totalPages, page, per_page } = await this.wpService.fetchResourcePaged<any>(this.site, 'orders', requestParams);
// 并行获取所有订单的履行信息
const ordersWithFulfillments = await Promise.all(
items.map(async (order: any) => {
try {
// 获取订单的履行信息
const fulfillments = await this.getOrderFulfillments(order.id);
// 将履行信息添加到订单对象中
return { return {
...order, items: items.map(this.mapPlatformToUnifiedOrder),
fulfillments: fulfillments || []
};
} catch (error) {
// 如果获取履行信息失败,仍然返回订单,只是履行信息为空数组
console.error(`获取订单 ${order.id} 的履行信息失败:`, error);
return {
...order,
fulfillments: []
};
}
})
);
return {
items: ordersWithFulfillments.map(this.mapPlatformToUnifiedOrder),
total, total,
totalPages, totalPages,
page, page,
@ -514,12 +497,12 @@ export class WooCommerceAdapter implements ISiteAdapter {
return this.mapPlatformToUnifiedOrder(res.data); return this.mapPlatformToUnifiedOrder(res.data);
} }
async updateOrder(where: {id: string | number}, data: Partial<UnifiedOrderDTO>): Promise<boolean> { async updateOrder(where: { id: string | number }, data: Partial<UnifiedOrderDTO>): Promise<boolean> {
// 更新订单并返回布尔结果 // 更新订单并返回布尔结果
return await this.wpService.updateOrder(this.site, String(where.id), data as any); return await this.wpService.updateOrder(this.site, String(where.id), data as any);
} }
async deleteOrder(where: {id: string | number}): Promise<boolean> { async deleteOrder(where: { id: string | number }): Promise<boolean> {
// 删除订单 // 删除订单
const api = this.wpService.createApi(this.site, 'wc/v3'); const api = this.wpService.createApi(this.site, 'wc/v3');
await api.delete(`orders/${where.id}`, { force: true }); await api.delete(`orders/${where.id}`, { force: true });
@ -690,8 +673,8 @@ export class WooCommerceAdapter implements ISiteAdapter {
return mapped; return mapped;
} }
mapCreateProductParams(data: Partial<UnifiedProductDTO>):Partial<WooProduct> { mapCreateProductParams(data: Partial<UnifiedProductDTO>): Partial<WooProduct> {
const {id,...mapped}= this.mapUnifiedToPlatformProduct(data); const { id, ...mapped } = this.mapUnifiedToPlatformProduct(data);
// 创建不带 id // 创建不带 id
return mapped return mapped
} }
@ -844,28 +827,28 @@ export class WooCommerceAdapter implements ISiteAdapter {
}; };
} }
// 判断是否是这个站点的sku // 判断是否是这个站点的sku
isSiteSkuThisSite(sku: string,){ isSiteSkuThisSite(sku: string,) {
return sku.startsWith(this.site.skuPrefix+'-'); return sku.startsWith(this.site.skuPrefix + '-');
} }
async getProduct(where: Partial<Pick<UnifiedProductDTO, 'id' | 'sku'>>): Promise<UnifiedProductDTO>{ async getProduct(where: Partial<Pick<UnifiedProductDTO, 'id' | 'sku'>>): Promise<UnifiedProductDTO> {
const { id, sku } = where; const { id, sku } = where;
if(id) return this.getProductById(id); if (id) return this.getProductById(id);
if(sku) return this.getProductBySku(sku); if (sku) return this.getProductBySku(sku);
throw new Error('必须提供id或sku参数'); throw new Error('必须提供id或sku参数');
} }
async getProductBySku(sku: string){ async getProductBySku(sku: string) {
// const api = this.wpService.createApi(this.site, 'wc/v3'); // const api = this.wpService.createApi(this.site, 'wc/v3');
// const res = await api.get(`products`,{ // const res = await api.get(`products`,{
// sku // sku
// }); // });
// const product = res.data[0]; // const product = res.data[0];
const res = await this.wpService.getProducts(this.site,{ const res = await this.wpService.getProducts(this.site, {
sku, sku,
page:1, page: 1,
per_page:1, per_page: 1,
}); });
const product = res?.items?.[0]; const product = res?.items?.[0];
if(!product) return null if (!product) return null
return this.mapPlatformToUnifiedProduct(product); return this.mapPlatformToUnifiedProduct(product);
} }
// 产品操作方法 // 产品操作方法
@ -976,7 +959,7 @@ export class WooCommerceAdapter implements ISiteAdapter {
async updateProduct(where: Partial<Pick<UnifiedProductDTO, 'id' | 'sku'>>, data: Partial<UnifiedProductDTO>): Promise<boolean> { async updateProduct(where: Partial<Pick<UnifiedProductDTO, 'id' | 'sku'>>, data: Partial<UnifiedProductDTO>): Promise<boolean> {
// 更新产品并返回统一产品DTO // 更新产品并返回统一产品DTO
const product = await this.getProduct(where); const product = await this.getProduct(where);
if(!product){ if (!product) {
throw new Error('产品不存在'); throw new Error('产品不存在');
} }
const updateData = this.mapUpdateProductParams(data); const updateData = this.mapUpdateProductParams(data);
@ -987,7 +970,7 @@ export class WooCommerceAdapter implements ISiteAdapter {
async deleteProduct(where: Partial<Pick<UnifiedProductDTO, 'id' | 'sku'>>): Promise<boolean> { async deleteProduct(where: Partial<Pick<UnifiedProductDTO, 'id' | 'sku'>>): Promise<boolean> {
// 删除产品 // 删除产品
const product = await this.getProduct(where); const product = await this.getProduct(where);
if(!product){ if (!product) {
throw new Error('产品不存在'); throw new Error('产品不存在');
} }
const api = this.wpService.createApi(this.site, 'wc/v3'); const api = this.wpService.createApi(this.site, 'wc/v3');
@ -1415,7 +1398,7 @@ export class WooCommerceAdapter implements ISiteAdapter {
} }
// 获取单个 webhook 详情 // 获取单个 webhook 详情
async getWebhook(where: {id: string | number}): Promise<UnifiedWebhookDTO> { async getWebhook(where: { id: string | number }): Promise<UnifiedWebhookDTO> {
try { try {
const result = await this.wpService.getWebhook(this.site, where.id); const result = await this.wpService.getWebhook(this.site, where.id);
return this.mapPlatformToUnifiedWebhook(result as WooWebhook); return this.mapPlatformToUnifiedWebhook(result as WooWebhook);

View File

@ -369,9 +369,19 @@ export interface WooOrder {
date_created_gmt?: string; date_created_gmt?: string;
date_modified?: string; date_modified?: string;
date_modified_gmt?: string; date_modified_gmt?: string;
// 物流追踪信息
fulfillments?: WooFulfillment[];
} }
export interface MetaDataFulfillment {
custom_tracking_link: string;
custom_tracking_provider: string;
date_shipped: number;
source: string;
status_shipped: string;
tracking_id: string;
tracking_number: string;
tracking_product_code: string;
tracking_provider: string;
user_id: number;
}
// 这个是一个插件的物流追踪信息 // 这个是一个插件的物流追踪信息
// 接口: // 接口:
export interface WooFulfillment { export interface WooFulfillment {