From fe5d4bf2f0c986fd7e19ba4fe09458a1b44591a9 Mon Sep 17 00:00:00 2001 From: zhuotianyuan Date: Wed, 21 Jan 2026 15:58:22 +0800 Subject: [PATCH 1/3] =?UTF-8?q?refactor(logistics):=20=E7=A7=BB=E9=99=A4?= =?UTF-8?q?=E5=B7=B2=E6=B3=A8=E9=87=8A=E7=9A=84=E8=AE=A2=E5=8D=95=E5=AE=8C?= =?UTF-8?q?=E6=88=90=E5=A4=84=E7=90=86=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/service/logistics.service.ts | 110 +++++++++++++++---------------- 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/src/service/logistics.service.ts b/src/service/logistics.service.ts index 3b86176..1d5cb04 100644 --- a/src/service/logistics.service.ts +++ b/src/service/logistics.service.ts @@ -377,68 +377,68 @@ export class LogisticsService { // resShipmentOrder = await this.uniExpressService.createShipment(reqBody); // // 记录物流信息,并将订单状态转到完成 - if (resShipmentOrder.status === 'SUCCESS') { - order.orderStatus = ErpOrderStatus.COMPLETED; - } else { - throw new Error('运单生成失败'); - } - const dataSource = this.dataSourceManager.getDataSource('default'); - let transactionError = undefined; - let shipmentId = undefined; - await dataSource.transaction(async manager => { - const orderRepo = manager.getRepository(Order); - const shipmentRepo = manager.getRepository(Shipment); - const tracking_provider = 'UniUni'; // todo: id未确定,后写进常数 + // if (resShipmentOrder.status === 'SUCCESS') { + // order.orderStatus = ErpOrderStatus.COMPLETED; + // } else { + // throw new Error('运单生成失败'); + // } + // const dataSource = this.dataSourceManager.getDataSource('default'); + // let transactionError = undefined; + // let shipmentId = undefined; + // await dataSource.transaction(async manager => { + // const orderRepo = manager.getRepository(Order); + // const shipmentRepo = manager.getRepository(Shipment); + // const tracking_provider = 'UniUni'; // todo: id未确定,后写进常数 - // 同步物流信息到woocommerce - const site = await this.siteService.get(Number(order.siteId), true); - const res = await this.wpService.createShipment(site, order.externalOrderId, { - tracking_number: resShipmentOrder.data.tno, - tracking_provider: tracking_provider, - }); + // // 同步物流信息到woocommerce + // const site = await this.siteService.get(Number(order.siteId), true); + // const res = await this.wpService.createShipment(site, order.externalOrderId, { + // tracking_number: resShipmentOrder.data.tno, + // tracking_provider: tracking_provider, + // }); - if (order.orderStatus === ErpOrderStatus.COMPLETED) { - const shipment = await shipmentRepo.save({ - tracking_provider: tracking_provider, - tracking_id: res.data.tracking_id, - unique_id: resShipmentOrder.data.uni_order_sn, - stockPointId: String(data.stockPointId), // todo - state: resShipmentOrder.data.uni_status_code, - return_tracking_number: resShipmentOrder.data.tno, - fee: data.details.shipmentFee, - order: order - }); - order.shipmentId = shipment.id; - shipmentId = shipment.id; - } + // if (order.orderStatus === ErpOrderStatus.COMPLETED) { + // const shipment = await shipmentRepo.save({ + // tracking_provider: tracking_provider, + // tracking_id: res.data.tracking_id, + // unique_id: resShipmentOrder.data.uni_order_sn, + // stockPointId: String(data.stockPointId), // todo + // state: resShipmentOrder.data.uni_status_code, + // return_tracking_number: resShipmentOrder.data.tno, + // fee: data.details.shipmentFee, + // order: order + // }); + // order.shipmentId = shipment.id; + // shipmentId = shipment.id; + // } - // 同步订单状态到woocommerce - if (order.status !== OrderStatus.COMPLETED) { - await this.wpService.updateOrder(site, order.externalOrderId, { - status: OrderStatus.COMPLETED, - }); - order.status = OrderStatus.COMPLETED; - } - order.orderStatus = ErpOrderStatus.COMPLETED; + // // 同步订单状态到woocommerce + // if (order.status !== OrderStatus.COMPLETED) { + // await this.wpService.updateOrder(site, order.externalOrderId, { + // status: OrderStatus.COMPLETED, + // }); + // order.status = OrderStatus.COMPLETED; + // } + // order.orderStatus = ErpOrderStatus.COMPLETED; - await orderRepo.save(order); - }).catch(error => { - transactionError = error - }); + // await orderRepo.save(order); + // }).catch(error => { + // transactionError = error + // }); - if (transactionError !== undefined) { - console.log('err', transactionError); - throw transactionError; - } + // if (transactionError !== undefined) { + // console.log('err', transactionError); + // throw transactionError; + // } - // 更新产品发货信息 - this.orderService.updateOrderSales(order.id, sales); + // // 更新产品发货信息 + // this.orderService.updateOrderSales(order.id, sales); - return { - data: { - shipmentId - } - }; + // return { + // data: { + // shipmentId + // } + // }; } catch (error) { if (resShipmentOrder.status === 'SUCCESS') { await this.uniExpressService.deleteShipment(resShipmentOrder.data.tno); -- 2.40.1 From 5deedc2f45e7b5ffcbb861ba0990a8a94cfc42e1 Mon Sep 17 00:00:00 2001 From: zhuotianyuan Date: Wed, 21 Jan 2026 20:02:45 +0800 Subject: [PATCH 2/3] =?UTF-8?q?feat(logistics):=20=E5=AE=8C=E5=96=84?= =?UTF-8?q?=E7=89=A9=E6=B5=81=E6=9C=8D=E5=8A=A1=E6=8E=A5=E5=8F=A3=E5=B9=B6?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0fulfillment=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 重构物流服务接口,调整订单创建流程以支持多平台发货 添加wp服务的createFulfillment方法用于同步物流信息 优化mepShipment方法参数传递和请求体构造 --- src/service/freightwaves.service.ts | 10 +- src/service/logistics.service.ts | 182 +++++++++++++++------------- src/service/wp.service.ts | 30 +++++ 3 files changed, 131 insertions(+), 91 deletions(-) diff --git a/src/service/freightwaves.service.ts b/src/service/freightwaves.service.ts index f393261..7b8f0df 100644 --- a/src/service/freightwaves.service.ts +++ b/src/service/freightwaves.service.ts @@ -118,8 +118,8 @@ interface RateTryResponseData { // 创建订单响应数据接口 interface CreateOrderResponseData { - partnerOrderNumber: string; - shipOrderId: string; + msg: string; + data: any; } // 查询订单响应数据接口 @@ -149,11 +149,11 @@ interface RefundOrderResponseData {} export class FreightwavesService { @Inject() logger; - // 默认配置 + // 默认配置 private config: FreightwavesConfig = { appSecret: 'gELCHguGmdTLo!zfihfM91hae8G@9Sz23Mh6pHrt', - apiBaseUrl: 'https://tms.freightwaves.ca', - partner: '25072621035200000060', + apiBaseUrl: 'http://tms.freightwaves.ca:8901/', + partner: '25072621035200000060' }; // 初始化配置 diff --git a/src/service/logistics.service.ts b/src/service/logistics.service.ts index 1d5cb04..14fb228 100644 --- a/src/service/logistics.service.ts +++ b/src/service/logistics.service.ts @@ -343,8 +343,7 @@ export class LogisticsService { let resShipmentOrder; try { - resShipmentOrder = this.mepShipment(data); - // const stock_point = await this.stockPointModel.findOneBy({ id: data.stockPointId }); + //const stock_point = await this.stockPointModel.findOneBy({ id: data.stockPointId }); // const reqBody = { // sender: data.details.origin.contact_name, // start_phone: data.details.origin.phone_number, @@ -373,77 +372,89 @@ export class LogisticsService { // } // } - // // 添加运单 + resShipmentOrder =await this.mepShipment(data,order); + + // if (data.shipmentPlatform === 'uniuni') { + // // 添加运单 // resShipmentOrder = await this.uniExpressService.createShipment(reqBody); - - // // 记录物流信息,并将订单状态转到完成 - // if (resShipmentOrder.status === 'SUCCESS') { - // order.orderStatus = ErpOrderStatus.COMPLETED; - // } else { - // throw new Error('运单生成失败'); - // } - // const dataSource = this.dataSourceManager.getDataSource('default'); - // let transactionError = undefined; - // let shipmentId = undefined; - // await dataSource.transaction(async manager => { - // const orderRepo = manager.getRepository(Order); - // const shipmentRepo = manager.getRepository(Shipment); - // const tracking_provider = 'UniUni'; // todo: id未确定,后写进常数 - - // // 同步物流信息到woocommerce - // const site = await this.siteService.get(Number(order.siteId), true); - // const res = await this.wpService.createShipment(site, order.externalOrderId, { - // tracking_number: resShipmentOrder.data.tno, - // tracking_provider: tracking_provider, - // }); - - // if (order.orderStatus === ErpOrderStatus.COMPLETED) { - // const shipment = await shipmentRepo.save({ - // tracking_provider: tracking_provider, - // tracking_id: res.data.tracking_id, - // unique_id: resShipmentOrder.data.uni_order_sn, - // stockPointId: String(data.stockPointId), // todo - // state: resShipmentOrder.data.uni_status_code, - // return_tracking_number: resShipmentOrder.data.tno, - // fee: data.details.shipmentFee, - // order: order - // }); - // order.shipmentId = shipment.id; - // shipmentId = shipment.id; - // } - - // // 同步订单状态到woocommerce - // if (order.status !== OrderStatus.COMPLETED) { - // await this.wpService.updateOrder(site, order.externalOrderId, { - // status: OrderStatus.COMPLETED, - // }); - // order.status = OrderStatus.COMPLETED; - // } - // order.orderStatus = ErpOrderStatus.COMPLETED; - - // await orderRepo.save(order); - // }).catch(error => { - // transactionError = error - // }); - - // if (transactionError !== undefined) { - // console.log('err', transactionError); - // throw transactionError; // } - // // 更新产品发货信息 - // this.orderService.updateOrderSales(order.id, sales); + // if (data.shipmentPlatform === 'freightwaves') { + // // 添加运单 + // resShipmentOrder = await this.freightcomService.createShipment(reqBody); + // } - // return { - // data: { - // shipmentId - // } - // }; + // 记录物流信息,并将订单状态转到完成 + if (resShipmentOrder.status === 'SUCCESS'||resShipmentOrder.code === '00000200') { + order.orderStatus = ErpOrderStatus.COMPLETED; + } else { + throw new Error('运单生成失败'); + } + const dataSource = this.dataSourceManager.getDataSource('default'); + let transactionError = undefined; + let shipmentId = undefined; + await dataSource.transaction(async manager => { + const orderRepo = manager.getRepository(Order); + const shipmentRepo = manager.getRepository(Shipment); + const tracking_provider = data.shipmentPlatform; // todo: id未确定,后写进常数 + + // 同步物流信息到woocommerce + const site = await this.siteService.get(Number(order.siteId), true); + const res = await this.wpService.createFulfillment(site, order.externalOrderId, { + tracking_number: resShipmentOrder.data.tno, + tracking_provider: tracking_provider, + }); + + if (order.orderStatus === ErpOrderStatus.COMPLETED) { + const shipment = await shipmentRepo.save({ + tracking_provider: tracking_provider, + tracking_id: res.data.tracking_id, + unique_id: resShipmentOrder.data.uni_order_sn, + stockPointId: String(data.stockPointId), // todo + state: resShipmentOrder.data.uni_status_code, + return_tracking_number: resShipmentOrder.data.tno, + fee: data.details.shipmentFee, + order: order + }); + order.shipmentId = shipment.id; + shipmentId = shipment.id; + } + + // 同步订单状态到woocommerce + if(order.source_type!="shopyy"){ + if (order.status !== OrderStatus.COMPLETED) { + await this.wpService.updateOrder(site, order.externalOrderId, { + status: OrderStatus.COMPLETED, + }); + order.status = OrderStatus.COMPLETED; + } + } + + order.orderStatus = ErpOrderStatus.COMPLETED; + + await orderRepo.save(order); + }).catch(error => { + transactionError = error + }); + + if (transactionError !== undefined) { + console.log('err', transactionError); + throw transactionError; + } + + // 更新产品发货信息 + this.orderService.updateOrderSales(order.id, sales); + + return { + data: { + shipmentId + } + }; } catch (error) { if (resShipmentOrder.status === 'SUCCESS') { await this.uniExpressService.deleteShipment(resShipmentOrder.data.tno); } - throw new Error(`上游请求错误:${error}`); + throw new Error(`上游请求错误:${error}`); } } @@ -670,8 +681,7 @@ export class LogisticsService { - - async mepShipment(data: ShipmentBookDTO) { + async mepShipment(data: ShipmentBookDTO,order:Order) { try { const stock_point = await this.stockPointModel.findOneBy({ id: data.stockPointId }); let resShipmentOrder; @@ -701,7 +711,7 @@ export class LogisticsService { weight_uom: data.details.packaging_properties.packages[0].measurements.weight.unit, currency: 'CAD', custom_field: { - 'order_id': '' // todo: 需要获取订单的externalOrderId + 'order_id': order.externalOrderId // todo: 需要获取订单的externalOrderId } }; @@ -711,10 +721,10 @@ export class LogisticsService { if (data.shipmentPlatform === 'freightwaves') { // 根据TMS系统对接说明文档格式化参数 - const reqBody = { - shipCompany: '', // 渠道(可以不指定) - partnerOrderNumber: `order-${Date.now()}`, // 第三方客户订单编号(唯一) - warehouseId: String(stock_point.upStreamStockPointId), // 发货仓库编号(转换为字符串类型) + const reqBody: any = { + shipCompany: 'UPSYYZ7000NEW', + partnerOrderNumber: order.externalOrderId , + warehouseId: '25072621030107400060', shipper: { name: data.details.origin.contact_name, // 姓名 phone: data.details.origin.phone_number.number, // 电话(提取number属性转换为字符串) @@ -756,22 +766,22 @@ export class LogisticsService { weightUnit: (data.details.packaging_properties.packages[0].measurements.weight.unit === 'kg' ? 'KG' : 'LB') as 'KG' | 'LB' // 重量单位(LB,KG) }, currency: 'CAD', // 币种(默认CAD) - description: 'Package' // 包裹描述(确保是字符串类型) + description: '订单编号:'+order.externalOrderId // 包裹描述(确保是字符串类型) } ], - signService: 0 as 0 | 1, // 签名服务 0不使用, 1使用 + signService: 0, // 签名服务 0不使用, 1使用 declaration: { - boxNo: 'BOX-001', // 箱号 - sku: 'DEFAULT-SKU', // SKU - cnname: '默认商品', // 中文名称 - enname: 'Default Product', // 英文名称 - declaredPrice: 0, // 申报价格 - declaredQty: 1, // 申报数量 - material: 'General', // 材质 - intendedUse: 'General use', // 用途 - cweight: data.details.packaging_properties.packages[0].measurements.weight.value, // 重量 - hsCode: '39269090', // 海关编码 - battery: 'No' // 是否含电池 + "boxNo": "", //箱子编号 + "sku": "", //SKU + "cnname": "", //中文名称 + "enname": "", //英文名称 + "declaredPrice": 1, //申报单价 + "declaredQty": 1, //申报数量 + "material": "", //材质 + "intendedUse": "", //用途 + "cweight": 1, //产品单重 + "hsCode": "", //海关编码 + "battery": "" //电池描述 } }; @@ -786,7 +796,7 @@ export class LogisticsService { console.log('物流订单处理失败:', error); // 使用console.log代替this.log throw error; } - } + } /** * 将ShipmentFeeBookDTO转换为freightwaves的RateTryRequest格式 diff --git a/src/service/wp.service.ts b/src/service/wp.service.ts index 7425252..5091f6e 100644 --- a/src/service/wp.service.ts +++ b/src/service/wp.service.ts @@ -403,4 +403,34 @@ export class WPService { }; return await axios.request(config); } + + + async createFulfillment( + site: any, + orderId: string, + data: Record + ) { + const apiUrl = site.apiUrl; + const { consumerKey, consumerSecret } = site; + const auth = Buffer.from(`${consumerKey}:${consumerSecret}`).toString( + 'base64' + ); + const config: AxiosRequestConfig = { + method: 'POST', + // 构建 URL,规避多/或少/问题 + url: this.buildURL( + apiUrl, + '/wp-json', + 'wc-ast/v3/orders', + orderId, + 'shipment-trackings' + ), + headers: { + Authorization: `Basic ${auth}`, + }, + data, + }; + return await axios.request(config); + } + } \ No newline at end of file -- 2.40.1 From 00b6ca828e8b0ac275f1e2bc9f11889b3afc1df8 Mon Sep 17 00:00:00 2001 From: zhuotianyuan Date: Wed, 21 Jan 2026 20:04:32 +0800 Subject: [PATCH 3/3] =?UTF-8?q?fix(dto):=20=E4=B8=BAshipmentPlatform?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=E6=B7=BB=E5=8A=A0Rule=E6=A0=A1=E9=AA=8C?= =?UTF-8?q?=E8=A3=85=E9=A5=B0=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/dto/logistics.dto.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dto/logistics.dto.ts b/src/dto/logistics.dto.ts index a5e836d..fa57e60 100644 --- a/src/dto/logistics.dto.ts +++ b/src/dto/logistics.dto.ts @@ -21,6 +21,7 @@ export class ShipmentBookDTO { orderIds?: number[]; @ApiProperty() + @Rule(RuleType.string()) shipmentPlatform: string; } -- 2.40.1