From cb876e8c0f9ba27029d6280c6f4bdb33801f372d Mon Sep 17 00:00:00 2001 From: tikkhun Date: Thu, 22 Jan 2026 11:38:44 +0800 Subject: [PATCH 1/3] =?UTF-8?q?refactor(=E7=89=A9=E6=B5=81):=20=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E7=89=A9=E6=B5=81=E7=9B=B8=E5=85=B3=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E5=92=8CDTO=E4=BB=A5=E6=94=AF=E6=8C=81=E5=8F=AF=E9=80=89?= =?UTF-8?q?=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 重构物流追踪相关接口和DTO,将order_item_id和quantity改为可选字段 添加tracking_id字段到FulfillmentDTO 优化woocommerce物流数据结构映射 更新package-lock.json添加faker依赖 --- package-lock.json | 17 +++++++++++++++++ src/adapter/woocommerce.adapter.ts | 12 +++++------- src/dto/site-api.dto.ts | 6 ++++-- src/dto/woocommerce.dto.ts | 20 +++++++++----------- 4 files changed, 35 insertions(+), 20 deletions(-) diff --git a/package-lock.json b/package-lock.json index 405c79b..ae4071c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -523,6 +523,23 @@ "node": ">=18" } }, + "node_modules/@faker-js/faker": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-10.2.0.tgz", + "integrity": "sha512-rTXwAsIxpCqzUnZvrxVh3L0QA0NzToqWBLAhV+zDV3MIIwiQhAZHMdPCIaj5n/yADu/tyk12wIPgL6YHGXJP+g==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/fakerjs" + } + ], + "license": "MIT", + "peer": true, + "engines": { + "node": "^20.19.0 || ^22.13.0 || ^23.5.0 || >=24.0.0", + "npm": ">=10" + } + }, "node_modules/@hapi/bourne": { "version": "3.0.0", "resolved": "https://registry.npmmirror.com/@hapi/bourne/-/bourne-3.0.0.tgz", diff --git a/src/adapter/woocommerce.adapter.ts b/src/adapter/woocommerce.adapter.ts index e3ffcaa..9fe5549 100644 --- a/src/adapter/woocommerce.adapter.ts +++ b/src/adapter/woocommerce.adapter.ts @@ -408,13 +408,11 @@ export class WooCommerceAdapter implements ISiteAdapter { // 包含账单地址与收货地址以及创建与更新时间 // 映射物流追踪信息,将后端格式转换为前端期望的格式 - const fulfillments = (item.fulfillments || []).map((track: any) => ({ - tracking_number: track.tracking_number || '', - shipping_provider: track.shipping_provider || '', - shipping_method: track.shipping_method || '', - status: track.status || '', - date_created: track.date_created || '', - items: track.items || [], + const fulfillments = (item.fulfillments || []).map((track) => ({ + tracking_id: track.tracking_id, + tracking_number: track.tracking_number, + shipping_provider: track.tracking_provider, + date_created: track.data_sipped, })); return { diff --git a/src/dto/site-api.dto.ts b/src/dto/site-api.dto.ts index b02cd43..a5b2fc7 100644 --- a/src/dto/site-api.dto.ts +++ b/src/dto/site-api.dto.ts @@ -799,14 +799,16 @@ export class UpdateWebhookDTO { export class FulfillmentItemDTO { - @ApiProperty({ description: '订单项ID' }) + @ApiProperty({ description: '订单项ID' ,required: false}) order_item_id: number; - @ApiProperty({ description: '数量' }) + @ApiProperty({ description: '数量' ,required:false}) quantity: number; } export class FulfillmentDTO { + @ApiProperty({ description: '物流id', required: false }) + tracking_id?: string; @ApiProperty({ description: '物流单号', required: false }) tracking_number?: string; diff --git a/src/dto/woocommerce.dto.ts b/src/dto/woocommerce.dto.ts index f042838..1490dba 100644 --- a/src/dto/woocommerce.dto.ts +++ b/src/dto/woocommerce.dto.ts @@ -370,17 +370,15 @@ export interface WooOrder { date_modified?: string; date_modified_gmt?: string; // 物流追踪信息 - fulfillments?: Array<{ - tracking_number?: string; - shipping_provider?: string; - shipping_method?: string; - status?: string; - date_created?: string; - items?: Array<{ - order_item_id?: number; - quantity?: number; - }>; - }>; + fulfillments?: WooFulfillment[]; +} +// 这个是一个插件的物流追踪信息 +export interface WooFulfillment { + data_sipped: string; + tracking_id: string; + tracking_link: string; + tracking_number: string; + tracking_provider: string; } export interface WooOrderRefund { id?: number; -- 2.40.1 From d5384944a453a1b9ae6b6a09bc09855098ef852e Mon Sep 17 00:00:00 2001 From: tikkhun Date: Thu, 22 Jan 2026 14:44:42 +0800 Subject: [PATCH 2/3] =?UTF-8?q?feat(woocommerce):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E7=89=A9=E6=B5=81=E8=BF=BD=E8=B8=AA=E5=88=9B=E5=BB=BA=E5=92=8C?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加 WooFulfillmentCreateParams 接口定义并重构物流追踪创建和更新方法 使用统一的 FulfillmentDTO 类型简化参数处理 --- src/adapter/woocommerce.adapter.ts | 58 +++++++++--------------------- src/dto/woocommerce.dto.ts | 9 +++++ 2 files changed, 25 insertions(+), 42 deletions(-) diff --git a/src/adapter/woocommerce.adapter.ts b/src/adapter/woocommerce.adapter.ts index 9fe5549..0246569 100644 --- a/src/adapter/woocommerce.adapter.ts +++ b/src/adapter/woocommerce.adapter.ts @@ -17,6 +17,7 @@ import { UnifiedVariationPaginationDTO, CreateReviewDTO, UpdateReviewDTO, + FulfillmentDTO, } from '../dto/site-api.dto'; import { UnifiedPaginationDTO, UnifiedSearchParamsDTO } from '../dto/api.dto'; import { @@ -29,6 +30,7 @@ import { WooOrderSearchParams, WooProductSearchParams, WpMediaGetListParams, + WooFulfillment, } from '../dto/woocommerce.dto'; import { Site } from '../entity/site.entity'; import { WPService } from '../service/wp.service'; @@ -357,6 +359,7 @@ export class WooCommerceAdapter implements ISiteAdapter { // 集合过滤参数 if (where.exclude) mapped.exclude = toArray(where.exclude); if (where.include) mapped.include = toArray(where.include); + if (where.ids) mapped.include = toArray(where.ids); if (toNumber(where.offset) !== undefined) mapped.offset = Number(where.offset); if (where.parent ?? where.parentId) mapped.parent = toArray(where.parent ?? where.parentId); @@ -539,54 +542,25 @@ export class WooCommerceAdapter implements ISiteAdapter { return await this.wpService.getFulfillments(this.site, String(orderId)); } - async createOrderFulfillment(orderId: string | number, data: { - tracking_number: string; - shipping_provider: string; - shipping_method?: string; - status?: string; - date_created?: string; - items?: Array<{ - order_item_id: number; - quantity: number; - }>; - }): Promise { - const shipmentData: any = { - shipping_provider: data.shipping_provider, + async createOrderFulfillment(orderId: string | number, data: FulfillmentDTO): Promise { + const shipmentData: Partial = { + tracking_provider: data.shipping_provider, tracking_number: data.tracking_number, - }; - - if (data.shipping_method) { - shipmentData.shipping_method = data.shipping_method; + data_sipped: data.date_created, + // items: data.items, } - - if (data.status) { - shipmentData.status = data.status; - } - - if (data.date_created) { - shipmentData.date_created = data.date_created; - } - - if (data.items) { - shipmentData.items = data.items; - } - const response = await this.wpService.createFulfillment(this.site, String(orderId), shipmentData); return response.data; } - async updateOrderFulfillment(orderId: string | number, fulfillmentId: string, data: { - tracking_number?: string; - shipping_provider?: string; - shipping_method?: string; - status?: string; - date_created?: string; - items?: Array<{ - order_item_id: number; - quantity: number; - }>; - }): Promise { - return await this.wpService.updateFulfillment(this.site, String(orderId), fulfillmentId, data); + async updateOrderFulfillment(orderId: string | number, fulfillmentId: string, data: FulfillmentDTO): Promise { + const shipmentData: Partial = { + tracking_provider: data.shipping_provider, + tracking_number: data.tracking_number, + data_sipped: data.date_created, + // items: data.items, + } + return await this.wpService.updateFulfillment(this.site, String(orderId), fulfillmentId, shipmentData); } async deleteOrderFulfillment(orderId: string | number, fulfillmentId: string): Promise { diff --git a/src/dto/woocommerce.dto.ts b/src/dto/woocommerce.dto.ts index 1490dba..29245b7 100644 --- a/src/dto/woocommerce.dto.ts +++ b/src/dto/woocommerce.dto.ts @@ -373,6 +373,7 @@ export interface WooOrder { fulfillments?: WooFulfillment[]; } // 这个是一个插件的物流追踪信息 +// 接口: export interface WooFulfillment { data_sipped: string; tracking_id: string; @@ -380,6 +381,14 @@ export interface WooFulfillment { tracking_number: string; tracking_provider: string; } +// https://docs.zorem.com/docs/ast-free/developers/adding-tracking-info-to-orders/ +export interface WooFulfillmentCreateParams { + order_id: string; + tracking_provider: string; + tracking_number: string; + date_shipped?: string; + status_shipped?: string; +} export interface WooOrderRefund { id?: number; reason?: string; -- 2.40.1 From 75056db42c2c87c37af45e1214be1cebb4eb15dd Mon Sep 17 00:00:00 2001 From: tikkhun Date: Thu, 22 Jan 2026 15:05:41 +0800 Subject: [PATCH 3/3] =?UTF-8?q?refactor(woocommerce):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E5=8F=82=E6=95=B0=E5=A4=84=E7=90=86=E9=80=BB=E8=BE=91=E5=B9=B6?= =?UTF-8?q?=E6=8F=90=E5=8F=96=E5=B7=A5=E5=85=B7=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将参数转换逻辑提取到独立的工具模块中 合并重复的include参数处理逻辑 添加对parent_exclude参数的支持 --- src/adapter/woocommerce.adapter.ts | 16 ++-------------- src/dto/woocommerce.dto.ts | 3 ++- src/utils/trans.util.ts | 11 +++++++++++ 3 files changed, 15 insertions(+), 15 deletions(-) create mode 100644 src/utils/trans.util.ts diff --git a/src/adapter/woocommerce.adapter.ts b/src/adapter/woocommerce.adapter.ts index 0246569..f14d7d3 100644 --- a/src/adapter/woocommerce.adapter.ts +++ b/src/adapter/woocommerce.adapter.ts @@ -35,6 +35,7 @@ import { import { Site } from '../entity/site.entity'; import { WPService } from '../service/wp.service'; import { BatchOperationDTO, BatchOperationResultDTO } from '../dto/batch.dto'; +import { toArray, toNumber } from '../utils/trans.util'; export class WooCommerceAdapter implements ISiteAdapter { // 构造函数接收站点配置与服务实例 @@ -332,22 +333,11 @@ export class WooCommerceAdapter implements ISiteAdapter { // } const mapped: any = { ...(params.search ? { search: params.search } : {}), - // ...(orderBy ? { orderBy } : {}), page, per_page, }; - const toArray = (value: any): any[] => { - if (Array.isArray(value)) return value; - if (value === undefined || value === null) return []; - return String(value).split(',').map(v => v.trim()).filter(Boolean); - }; - const toNumber = (value: any): number | undefined => { - if (value === undefined || value === null || value === '') return undefined; - const n = Number(value); - return Number.isFinite(n) ? n : undefined; - }; // 时间过滤参数 if (where.after ?? where.date_created_after ?? where.created_after) mapped.after = String(where.after ?? where.date_created_after ?? where.created_after); @@ -358,9 +348,7 @@ export class WooCommerceAdapter implements ISiteAdapter { // 集合过滤参数 if (where.exclude) mapped.exclude = toArray(where.exclude); - if (where.include) mapped.include = toArray(where.include); - - if (where.ids) mapped.include = toArray(where.ids); + 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 (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); diff --git a/src/dto/woocommerce.dto.ts b/src/dto/woocommerce.dto.ts index 29245b7..c48b85f 100644 --- a/src/dto/woocommerce.dto.ts +++ b/src/dto/woocommerce.dto.ts @@ -559,7 +559,8 @@ export interface WooOrderSearchParams { order: string; orderby: string; parant: string[]; - status: (WooOrderStatusSearchParams)[]; + parent_exclude: string[]; + status: WooOrderStatusSearchParams[]; customer: number; product: number; dp: number; diff --git a/src/utils/trans.util.ts b/src/utils/trans.util.ts new file mode 100644 index 0000000..57063e3 --- /dev/null +++ b/src/utils/trans.util.ts @@ -0,0 +1,11 @@ +export const toArray = (value: any): any[] => { + if (Array.isArray(value)) return value; + if (value === undefined || value === null) return []; + return String(value).split(',').map(v => v.trim()).filter(Boolean); +}; + +export const toNumber = (value: any): number | undefined => { + if (value === undefined || value === null || value === '') return undefined; + const n = Number(value); + return Number.isFinite(n) ? n : undefined; +}; \ No newline at end of file -- 2.40.1