From 86fd31ac124dfb6d139b3d04d6fd7fb99f751a61 Mon Sep 17 00:00:00 2001 From: zhuotianyuan Date: Tue, 6 Jan 2026 18:43:30 +0800 Subject: [PATCH 01/12] =?UTF-8?q?feat(webhook):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=AF=B9shoppy=E5=B9=B3=E5=8F=B0webhook=E7=9A=84=E6=94=AF?= =?UTF-8?q?=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在site.entity.ts中添加webhookUrl字段 - 在auth.middleware.ts中添加/shoppy路由到白名单 - 在webhook.controller.ts中实现shoppy平台webhook处理逻辑 fix(webhook): 更新webhook控制器中的密钥值 refactor(entity): 将可选字段明确标记为可选类型 feat(adapter): 公开映射方法以支持统一接口调用 将各适配器中的私有映射方法改为公开,并在接口中定义统一方法签名 修改webhook控制器以使用适配器映射方法处理订单数据 feat: 添加订单支付日期字段并支持国家筛选 - 在ShopyyOrder接口中添加date_paid字段 - 在OrderStatisticsParams中添加country数组字段用于国家筛选 - 修改统计服务以支持按国家筛选订单数据 - 更新数据库配置和同步设置 - 优化订单服务中的类型定义和查询条件 refactor(webhook): 移除未使用的shoppy webhook处理逻辑 fix(订单服务): 修复订单内容括号处理并添加同步日志 添加订单同步过程的调试日志 修复订单内容中括号内容的处理逻辑 修正控制器方法名拼写错误 --- src/adapter/shopyy.adapter.ts | 1 + src/dto/shopyy.dto.ts | 1 + src/service/order.service.ts | 33 +++++++++++++++++++++++++-------- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/src/adapter/shopyy.adapter.ts b/src/adapter/shopyy.adapter.ts index 9a3894d..1e1af3b 100644 --- a/src/adapter/shopyy.adapter.ts +++ b/src/adapter/shopyy.adapter.ts @@ -393,6 +393,7 @@ export class ShopyyAdapter implements ISiteAdapter { tracking_number: f.tracking_number || '', shipping_provider: f.tracking_company || '', shipping_method: f.tracking_company || '', + date_created: typeof f.created_at === 'number' ? new Date(f.created_at * 1000).toISOString() : f.created_at || '', diff --git a/src/dto/shopyy.dto.ts b/src/dto/shopyy.dto.ts index bd708ab..671711d 100644 --- a/src/dto/shopyy.dto.ts +++ b/src/dto/shopyy.dto.ts @@ -1211,6 +1211,7 @@ export interface ShopyyOrder { // 时间戳信息 // ======================================== // 订单创建时间 + date_paid?: number | string; created_at?: number | string; // 订单添加时间 date_added?: string; diff --git a/src/service/order.service.ts b/src/service/order.service.ts index 0cc42ed..adc6b0a 100644 --- a/src/service/order.service.ts +++ b/src/service/order.service.ts @@ -142,6 +142,7 @@ export class OrderService { errors: [] }; console.log('开始进入循环同步订单', result.length, '个订单') + console.log('开始进入循环同步订单', result.length, '个订单') // 遍历每个订单进行同步 for (const order of result) { try { @@ -329,16 +330,33 @@ export class OrderService { this.logger.debug('订单状态为 AUTO_DRAFT,跳过处理', siteId, order.id) return; } - // 这里其实不用过滤不可编辑的行为,而是应在 save 中做判断 - // if(!order.is_editable && !forceUpdate){ - // this.logger.debug('订单不可编辑,跳过处理', siteId, order.id) - // return; - // } - // 自动转换远程订单的状态(如果需要) + // 检查数据库中是否已存在该订单 + const existingOrder = await this.orderModel.findOne({ + where: { externalOrderId: String(order.id), siteId: siteId }, + }); + // 自动更新订单状态(如果需要) await this.autoUpdateOrderStatus(siteId, order); + + if(existingOrder){ + // 矫正数据库中的订单数据 + const updateData: any = { status: order.status }; + if (this.canUpdateErpStatus(existingOrder.orderStatus)) { + updateData.orderStatus = this.mapOrderStatus(order.status as any); + } + // 更新订单主数据 + await this.orderModel.update({ externalOrderId: String(order.id), siteId: siteId }, updateData); + // 更新 fulfillments 数据 + await this.saveOrderFulfillments({ + siteId, + orderId: existingOrder.id, + externalOrderId:order.id, + fulfillments: fulfillments, + }); + } + const externalOrderId = String(order.id); // 这里的 saveOrder 已经包括了创建订单和更新订单 let orderRecord: Order = await this.saveOrder(siteId, orderData); - // 如果订单从未完成变为完成状态,则更新库存 + // 如果订单从未完成变为完成状态,则更新库存 if ( orderRecord && orderRecord.orderStatus !== ErpOrderStatus.COMPLETED && @@ -347,7 +365,6 @@ export class OrderService { await this.updateStock(orderRecord); // 不再直接返回,继续执行后续的更新操作 } - const externalOrderId = String(order.id); const orderId = orderRecord.id; // 保存订单项 await this.saveOrderItems({ -- 2.40.1 From 0ea834218de9d92497d0c6fd28cadf9ae78d0a03 Mon Sep 17 00:00:00 2001 From: zhuotianyuan Date: Tue, 13 Jan 2026 19:25:13 +0800 Subject: [PATCH 02/12] =?UTF-8?q?fix(shopyy):=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E8=AE=A2=E5=8D=95=E6=9F=A5=E8=AF=A2=E5=8F=82=E6=95=B0=E6=98=A0?= =?UTF-8?q?=E5=B0=84=E9=97=AE=E9=A2=98=E5=B9=B6=E6=B7=BB=E5=8A=A0=E6=97=B6?= =?UTF-8?q?=E9=97=B4=E8=8C=83=E5=9B=B4=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修正shopyy服务中获取所有订单的参数映射逻辑,添加支付时间范围支持 统一处理日期格式转换,确保参数正确传递 同时清理合并冲突标记和冗余代码 --- src/adapter/shopyy.adapter.ts | 4 ++-- src/dto/api.dto.ts | 17 +++++++++++++++++ src/service/freightwaves.service.ts | 2 +- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/adapter/shopyy.adapter.ts b/src/adapter/shopyy.adapter.ts index 1e1af3b..aa515f8 100644 --- a/src/adapter/shopyy.adapter.ts +++ b/src/adapter/shopyy.adapter.ts @@ -574,8 +574,8 @@ export class ShopyyAdapter implements ISiteAdapter { } mapGetAllOrdersParams(params: UnifiedSearchParamsDTO) :ShopyyGetAllOrdersParams{ - const pay_at_min = dayjs(params.after || '').unix().toString(); - const pay_at_max = dayjs(params.before || '').unix().toString(); + const pay_at_min = dayjs(params.after || '').valueOf().toString(); + const pay_at_max = dayjs(params.before || '').valueOf().toString(); return { per_page: params.per_page || 100, diff --git a/src/dto/api.dto.ts b/src/dto/api.dto.ts index b681336..93de5f8 100644 --- a/src/dto/api.dto.ts +++ b/src/dto/api.dto.ts @@ -76,6 +76,23 @@ export class ShopyyGetAllOrdersParams { order_field?: string;//排序字段(默认id) id=订单ID updated_at=最后更新时间 pay_at=支付时间 } +/** + * Shopyy获取所有订单参数DTO + */ +export class ShopyyGetAllOrdersParams { + @ApiProperty({ description: '页码', example: 1, required: false }) + page?: number; + + @ApiProperty({ description: '每页数量', example: 20, required: false }) + per_page?: number; + + @ApiProperty({ description: '支付时间范围开始', example: '2023-01-01T00:00:00Z', required: false }) + pay_at_min?: string; + + @ApiProperty({ description: '支付时间范围结束', example: '2023-01-01T23:59:59Z', required: false }) + pay_at_max?: string; +} + /** * 批量操作错误项 */ diff --git a/src/service/freightwaves.service.ts b/src/service/freightwaves.service.ts index 10900ef..bcd6ca5 100644 --- a/src/service/freightwaves.service.ts +++ b/src/service/freightwaves.service.ts @@ -423,7 +423,7 @@ export class FreightwavesService { // 设置必要的配置 this.setConfig({ appSecret: 'gELCHguGmdTLo!zfihfM91hae8G@9Sz23Mh6pHrt', - apiBaseUrl: 'https://tms.freightwaves.ca', + apiBaseUrl: 'https://console-mock.apipost.cn/mock/0', partner: '25072621035200000060' }); -- 2.40.1 From 52fa7d651ebb6b6e3ef8f0b962caa269bd37c5c3 Mon Sep 17 00:00:00 2001 From: zhuotianyuan Date: Wed, 14 Jan 2026 20:07:10 +0800 Subject: [PATCH 03/12] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E4=BA=A7?= =?UTF-8?q?=E5=93=81=E5=9B=BE=E7=89=87URL=E5=AD=97=E6=AE=B5=E5=B9=B6?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=AE=A2=E5=8D=95=E5=A4=84=E7=90=86=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加产品实体中的图片URL字段 更新订单服务以支持更多查询参数和分页 修改数据库连接配置为生产环境 调整运费服务API基础URL 优化订单适配器中的字段映射逻辑 --- src/adapter/shopyy.adapter.ts | 4 ++-- src/config/config.local.ts | 7 +++---- src/dto/api.dto.ts | 8 ++++---- src/service/freightwaves.service.ts | 2 +- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/adapter/shopyy.adapter.ts b/src/adapter/shopyy.adapter.ts index aa515f8..1e1af3b 100644 --- a/src/adapter/shopyy.adapter.ts +++ b/src/adapter/shopyy.adapter.ts @@ -574,8 +574,8 @@ export class ShopyyAdapter implements ISiteAdapter { } mapGetAllOrdersParams(params: UnifiedSearchParamsDTO) :ShopyyGetAllOrdersParams{ - const pay_at_min = dayjs(params.after || '').valueOf().toString(); - const pay_at_max = dayjs(params.before || '').valueOf().toString(); + const pay_at_min = dayjs(params.after || '').unix().toString(); + const pay_at_max = dayjs(params.before || '').unix().toString(); return { per_page: params.per_page || 100, diff --git a/src/config/config.local.ts b/src/config/config.local.ts index bd64204..1b92d9c 100644 --- a/src/config/config.local.ts +++ b/src/config/config.local.ts @@ -19,13 +19,12 @@ export default { typeorm: { dataSource: { default: { - host: '13.212.62.127', - port: "3306", + host: 'localhost', + port: "23306", username: 'root', password: 'Yoone!@.2025', database: 'inventory_v2', - synchronize: true, - logging: true, + synchronize: true }, }, }, diff --git a/src/dto/api.dto.ts b/src/dto/api.dto.ts index 93de5f8..a10f6c2 100644 --- a/src/dto/api.dto.ts +++ b/src/dto/api.dto.ts @@ -80,10 +80,7 @@ export class ShopyyGetAllOrdersParams { * Shopyy获取所有订单参数DTO */ export class ShopyyGetAllOrdersParams { - @ApiProperty({ description: '页码', example: 1, required: false }) - page?: number; - - @ApiProperty({ description: '每页数量', example: 20, required: false }) + @ApiProperty({ description: '每页数量', example: 100, required: false }) per_page?: number; @ApiProperty({ description: '支付时间范围开始', example: '2023-01-01T00:00:00Z', required: false }) @@ -91,6 +88,9 @@ export class ShopyyGetAllOrdersParams { @ApiProperty({ description: '支付时间范围结束', example: '2023-01-01T23:59:59Z', required: false }) pay_at_max?: string; + + @ApiProperty({ description: '排序字段', example: 'id', required: false }) + order_field?: string;//排序字段(默认id) id=订单ID updated_at=最后更新时间 pay_at=支付时间 } /** diff --git a/src/service/freightwaves.service.ts b/src/service/freightwaves.service.ts index bcd6ca5..10900ef 100644 --- a/src/service/freightwaves.service.ts +++ b/src/service/freightwaves.service.ts @@ -423,7 +423,7 @@ export class FreightwavesService { // 设置必要的配置 this.setConfig({ appSecret: 'gELCHguGmdTLo!zfihfM91hae8G@9Sz23Mh6pHrt', - apiBaseUrl: 'https://console-mock.apipost.cn/mock/0', + apiBaseUrl: 'https://tms.freightwaves.ca', partner: '25072621035200000060' }); -- 2.40.1 From 86aa5f5790e8d53a491a4f58781b64a233bffb56 Mon Sep 17 00:00:00 2001 From: zhuotianyuan Date: Sat, 17 Jan 2026 11:03:12 +0800 Subject: [PATCH 04/12] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E6=96=B9=E6=B3=95=E8=B0=83=E7=94=A8=E5=92=8C=E8=AE=A2?= =?UTF-8?q?=E5=8D=95=E5=86=85=E5=AE=B9=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复测试文件中错误的方法调用,从testQueryOrder改为testCreateOrder 调整订单内容格式,移除SKU显示并简化格式 修正电话号码字段的类型断言问题 修复日期格式错误,从mm改为MM 更新API基础URL和端点路径 移除不必要的日志对象调用,改用console.log --- src/adapter/shopyy.adapter.ts | 4 ++-- src/service/freightwaves.service.ts | 16 ++++++++-------- src/service/order.service.ts | 4 ++-- test-freightwaves.js | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/adapter/shopyy.adapter.ts b/src/adapter/shopyy.adapter.ts index 1e1af3b..6b373c9 100644 --- a/src/adapter/shopyy.adapter.ts +++ b/src/adapter/shopyy.adapter.ts @@ -244,7 +244,7 @@ export class ShopyyAdapter implements ISiteAdapter { fullname: billing.name || `${item.firstname} ${item.lastname}`.trim(), company: billing.company || '', email: item.customer_email || item.email || '', - phone: billing.phone || (item as any).telephone || '', + phone: billing.phone || item.telephone || '', address_1: billing.address1 || item.payment_address || '', address_2: billing.address2 || '', city: billing.city || item.payment_city || '', @@ -275,7 +275,7 @@ export class ShopyyAdapter implements ISiteAdapter { state: shipping.province || item.shipping_zone || '', postcode: shipping.zip || item.shipping_postcode || '', method_title: item.payment_method || '', - phone: shipping.phone || (item as any).telephone || '', + phone: shipping.phone || item.telephone || '', country: shipping.country_name || shipping.country_code || diff --git a/src/service/freightwaves.service.ts b/src/service/freightwaves.service.ts index 10900ef..dfb0ef6 100644 --- a/src/service/freightwaves.service.ts +++ b/src/service/freightwaves.service.ts @@ -172,7 +172,7 @@ export class FreightwavesService { private async sendRequest(url: string, data: any): Promise> { try { // 设置请求头 - 使用太平洋时间 (America/Los_Angeles) - const date = dayjs().tz('America/Los_Angeles').format('YYYY-mm-dd HH:mm:ss'); + const date = dayjs().tz('America/Los_Angeles').format('YYYY-MM-DD HH:mm:ss'); const headers = { 'Content-Type': 'application/json', 'requestDate': date, @@ -180,11 +180,11 @@ export class FreightwavesService { }; // 记录请求前的详细信息 - this.log(`Sending request to: ${this.config.apiBaseUrl}${url}`, { + console.log(`Sending request to: ${this.config.apiBaseUrl}${url}`,JSON.stringify({ headers, data - }); - + })) + console.log('Request data:', `${this.config.apiBaseUrl}${url}`, data,headers); // 发送请求 - 临时禁用SSL证书验证以解决UNABLE_TO_VERIFY_LEAF_SIGNATURE错误 const response = await axios.post>( `${this.config.apiBaseUrl}${url}`, @@ -267,7 +267,7 @@ export class FreightwavesService { partner: this.config.partner, }; - const response = await this.sendRequest('/shipService/order/createOrder?apipost_id=0422aa', requestData); + const response = await this.sendRequest('shipService/order/rateTry', requestData); return response.data; } @@ -325,13 +325,13 @@ export class FreightwavesService { // 设置必要的配置 this.setConfig({ appSecret: 'gELCHguGmdTLo!zfihfM91hae8G@9Sz23Mh6pHrt', - apiBaseUrl: 'https://tms.freightwaves.ca', + apiBaseUrl: 'http://tms.freightwaves.ca:8901/', partner: '25072621035200000060' }); // 准备测试数据 const testParams: Omit = { - shipCompany: 'DHL', + shipCompany: '', partnerOrderNumber: `test-order-${Date.now()}`, warehouseId: '25072621035200000060', shipper: { @@ -423,7 +423,7 @@ export class FreightwavesService { // 设置必要的配置 this.setConfig({ appSecret: 'gELCHguGmdTLo!zfihfM91hae8G@9Sz23Mh6pHrt', - apiBaseUrl: 'https://tms.freightwaves.ca', + apiBaseUrl: 'http://freightwaves.ca:8901/shipService/order/rateTry', partner: '25072621035200000060' }); diff --git a/src/service/order.service.ts b/src/service/order.service.ts index adc6b0a..dc363da 100644 --- a/src/service/order.service.ts +++ b/src/service/order.service.ts @@ -2529,7 +2529,7 @@ export class OrderService { const boxCount = items.reduce((total, item) => total + item.quantity, 0); // 构建订单内容 - const orderContent = items.map(item => `${item.name} (${item.sku || ''}) x ${item.quantity}`).join('; '); + const orderContent = items.map(item => `${item.name} x ${item.quantity}`).join('; '); // 构建姓名地址 const shipping = order.shipping; @@ -2561,7 +2561,7 @@ export class OrderService { '姓名地址': nameAddress, '邮箱': order.customer_email || '', '号码': phone, - '订单内容': this.removeLastParenthesesContent(orderContent), + '订单内容': orderContent, '盒数': boxCount, '换盒数': exchangeBoxCount, '换货内容': exchangeContent, diff --git a/test-freightwaves.js b/test-freightwaves.js index c41c661..9236bcf 100644 --- a/test-freightwaves.js +++ b/test-freightwaves.js @@ -9,7 +9,7 @@ async function testFreightwavesService() { // Call the test method console.log('Starting test for createOrder method...'); - const result = await service.testQueryOrder(); + const result = await service.testCreateOrder(); console.log('Test completed successfully!'); console.log('Result:', result); -- 2.40.1 From bff03de8b0f5300f9b7932987daa0ba4d9b98ed2 Mon Sep 17 00:00:00 2001 From: zhuotianyuan Date: Thu, 22 Jan 2026 16:24:57 +0800 Subject: [PATCH 05/12] =?UTF-8?q?feat(logistics):=20=E6=B7=BB=E5=8A=A0frei?= =?UTF-8?q?ghtwaves=E7=89=A9=E6=B5=81=E5=B9=B3=E5=8F=B0=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增freightwaves物流平台集成,包括运单创建、状态查询和费用试算功能 添加sync_tms.job定时任务用于同步freightwaves运单状态 扩展ShipmentBookDTO和ShipmentFeeBookDTO以支持多物流平台 重构物流服务以支持uniuni和freightwaves双平台 --- src/dto/logistics.dto.ts | 9 + src/entity/shipment.entity.ts | 4 +- src/job/sync_tms.job.ts | 40 ++++ src/service/freightwaves.service.ts | 140 +++++++++-- src/service/logistics.service.ts | 355 ++++++++++++++++++++++++---- src/service/order.service.ts | 10 +- src/service/shopyy.service.ts | 2 +- test-freightwaves.js | 2 +- 8 files changed, 486 insertions(+), 76 deletions(-) create mode 100644 src/job/sync_tms.job.ts diff --git a/src/dto/logistics.dto.ts b/src/dto/logistics.dto.ts index 206884c..fa57e60 100644 --- a/src/dto/logistics.dto.ts +++ b/src/dto/logistics.dto.ts @@ -19,9 +19,16 @@ export class ShipmentBookDTO { @ApiProperty({ type: 'number', isArray: true }) @Rule(RuleType.array().default([])) orderIds?: number[]; + + @ApiProperty() + @Rule(RuleType.string()) + shipmentPlatform: string; } export class ShipmentFeeBookDTO { + + @ApiProperty() + shipmentPlatform: string; @ApiProperty() stockPointId: number; @ApiProperty() @@ -63,6 +70,8 @@ export class ShipmentFeeBookDTO { weight: number; @ApiProperty() weightUom: string; + @ApiProperty() + address_id: number; } export class PaymentMethodDTO { diff --git a/src/entity/shipment.entity.ts b/src/entity/shipment.entity.ts index 947db07..26237d8 100644 --- a/src/entity/shipment.entity.ts +++ b/src/entity/shipment.entity.ts @@ -54,9 +54,9 @@ export class Shipment { tracking_provider?: string; @ApiProperty() - @Column() + @Column({ nullable: true }) @Expose() - unique_id: string; + unique_id?: string; @Column({ nullable: true }) @Expose() diff --git a/src/job/sync_tms.job.ts b/src/job/sync_tms.job.ts new file mode 100644 index 0000000..ece6af6 --- /dev/null +++ b/src/job/sync_tms.job.ts @@ -0,0 +1,40 @@ +import { ILogger, Inject, Logger } from '@midwayjs/core'; +import { IJob, Job } from '@midwayjs/cron'; +import { LogisticsService } from '../service/logistics.service'; +import { Repository } from 'typeorm'; +import { Shipment } from '../entity/shipment.entity'; +import { InjectEntityModel } from '@midwayjs/typeorm'; + + +@Job({ + cronTime: '0 0 12 * * *', // 每天12点执行 + start: true +}) +export class SyncTmsJob implements IJob { + @Logger() + logger: ILogger; + + @Inject() + logisticsService: LogisticsService; + + @InjectEntityModel(Shipment) + shipmentModel: Repository + + async onTick() { + const shipments:Shipment[] = await this.shipmentModel.findBy({ tracking_provider: 'freightwaves',finished: false }); + const results = await Promise.all( + shipments.map(async shipment => { + return await this.logisticsService.updateFreightwavesShipmentState(shipment); + }) + ) + this.logger.info(`更新运单状态完毕 ${JSON.stringify(results)}`); + return results + } + + onComplete(result: any) { + this.logger.info(`更新运单状态完成 ${result}`); + } + onError(error: any) { + this.logger.error(`更新运单状态失败 ${error.message}`); + } +} \ No newline at end of file diff --git a/src/service/freightwaves.service.ts b/src/service/freightwaves.service.ts index dfb0ef6..be7deee 100644 --- a/src/service/freightwaves.service.ts +++ b/src/service/freightwaves.service.ts @@ -67,7 +67,7 @@ interface Declaration { } // 费用试算请求接口 -interface RateTryRequest { +export interface RateTryRequest { shipCompany: string; partnerOrderNumber: string; warehouseId?: string; @@ -118,8 +118,8 @@ interface RateTryResponseData { // 创建订单响应数据接口 interface CreateOrderResponseData { - partnerOrderNumber: string; - shipOrderId: string; + msg: string; + data: any; } // 查询订单响应数据接口 @@ -140,10 +140,10 @@ interface QueryOrderResponseData { } // 修改订单响应数据接口 -interface ModifyOrderResponseData extends CreateOrderResponseData {} +interface ModifyOrderResponseData extends CreateOrderResponseData { } // 订单退款响应数据接口 -interface RefundOrderResponseData {} +interface RefundOrderResponseData { } @Provide() export class FreightwavesService { @@ -152,8 +152,8 @@ export class FreightwavesService { // 默认配置 private config: FreightwavesConfig = { appSecret: 'gELCHguGmdTLo!zfihfM91hae8G@9Sz23Mh6pHrt', - apiBaseUrl: 'https://tms.freightwaves.ca', - partner: '25072621035200000060', + apiBaseUrl: 'http://tms.freightwaves.ca:8901/', + partner: '25072621035200000060' }; // 初始化配置 @@ -180,19 +180,19 @@ export class FreightwavesService { }; // 记录请求前的详细信息 - console.log(`Sending request to: ${this.config.apiBaseUrl}${url}`,JSON.stringify({ + console.log(`Sending request to: ${this.config.apiBaseUrl}${url}`, JSON.stringify({ headers, data })) - console.log('Request data:', `${this.config.apiBaseUrl}${url}`, data,headers); + console.log('Request data:', `${this.config.apiBaseUrl}${url}`, data, headers); // 发送请求 - 临时禁用SSL证书验证以解决UNABLE_TO_VERIFY_LEAF_SIGNATURE错误 const response = await axios.post>( `${this.config.apiBaseUrl}${url}`, data, - { + { headers, - httpsAgent: new (require('https').Agent)({ - rejectUnauthorized: false + httpsAgent: new (require('https').Agent)({ + rejectUnauthorized: false }) } ); @@ -267,8 +267,8 @@ export class FreightwavesService { partner: this.config.partner, }; - const response = await this.sendRequest('shipService/order/rateTry', requestData); - return response.data; + const response = await this.sendRequest('shipService/order/createOrder', requestData); + return response; } /** @@ -283,6 +283,9 @@ export class FreightwavesService { }; const response = await this.sendRequest('/shipService/order/queryOrder', requestData); + if (response.code !== '00000200') { + throw new Error(response.msg); + } return response.data; } @@ -331,9 +334,9 @@ export class FreightwavesService { // 准备测试数据 const testParams: Omit = { - shipCompany: '', + shipCompany: 'UPSYYZ7000NEW', partnerOrderNumber: `test-order-${Date.now()}`, - warehouseId: '25072621035200000060', + warehouseId: '25072621030107400060', shipper: { name: 'John Doe', phone: '123-456-7890', @@ -397,12 +400,12 @@ export class FreightwavesService { // 调用创建订单方法 this.log('开始测试创建订单...'); this.log('测试参数:', testParams); - + // 注意:在实际环境中取消注释以下行来执行真实请求 const result = await this.createOrder(testParams); - this.log('创建订单成功:', result); - - + this.log('创建订单成功:', result); + + // 返回模拟结果 return { partnerOrderNumber: testParams.partnerOrderNumber, @@ -414,6 +417,95 @@ export class FreightwavesService { } } + /** + * 测试费用试算方法 + * @returns 费用试算结果 + */ + async testRateTry() { + try { + // 设置必要的配置 + this.setConfig({ + appSecret: 'gELCHguGmdTLo!zfihfM91hae8G@9Sz23Mh6pHrt', + apiBaseUrl: 'http://tms.freightwaves.ca:8901', + partner: '25072621035200000060' + }); + + // 准备测试数据 - 符合RateTryRequest接口要求 + const testParams: Omit = { + shipCompany: 'UPSYYZ7000NEW', + partnerOrderNumber: `test-rate-try-${Date.now()}`, + warehouseId: '25072621030107400060', + shipper: { + name: 'John Doe', + phone: '123-456-7890', + company: 'Test Company', + countryCode: 'CA', + city: 'Toronto', + state: 'ON', + address1: '123 Main St', + address2: 'Suite 400', + postCode: 'M5V 2T6', + countryName: 'Canada', + cityName: 'Toronto', + stateName: 'Ontario', + companyName: 'Test Company Inc.' + }, + reciver: { + name: 'Jane Smith', + phone: '987-654-3210', + company: 'Receiver Company', + countryCode: 'CA', + city: 'Vancouver', + state: 'BC', + address1: '456 Oak St', + address2: '', + postCode: 'V6J 2A9', + countryName: 'Canada', + cityName: 'Vancouver', + stateName: 'British Columbia', + companyName: 'Receiver Company Ltd.' + }, + packages: [ + { + dimensions: { + length: 10, + width: 8, + height: 6, + lengthUnit: 'IN', + weight: 5, + weightUnit: 'LB' + }, + currency: 'CAD', + description: 'Test Package' + } + ], + signService: 0 + }; + + // 调用费用试算方法 + this.log('开始测试费用试算...'); + this.log('测试参数:', testParams); + + // 注意:在实际环境中取消注释以下行来执行真实请求 + const result = await this.rateTry(testParams); + this.log('费用试算成功:', result); + + this.log('测试完成:费用试算方法调用成功(模拟)'); + this.log('提示:在实际环境中,取消注释代码中的rateTry调用行来执行真实请求'); + + // 返回模拟结果 + return { + shipCompany: 'DHL', + channelCode: 'DHL-EXPRESS', + totalAmount: 125.50, + currency: 'CAD' + }; + } catch (error) { + this.log('测试费用试算失败:', error); + throw error; + } + } + /** * 测试查询订单方法 * @returns 查询订单结果 @@ -423,7 +515,7 @@ export class FreightwavesService { // 设置必要的配置 this.setConfig({ appSecret: 'gELCHguGmdTLo!zfihfM91hae8G@9Sz23Mh6pHrt', - apiBaseUrl: 'http://freightwaves.ca:8901/shipService/order/rateTry', + apiBaseUrl: 'http://freightwaves.ca:8901', partner: '25072621035200000060' }); @@ -437,13 +529,13 @@ export class FreightwavesService { // 调用查询订单方法 this.log('开始测试查询订单...'); this.log('测试参数:', testParams); - + // 注意:在实际环境中取消注释以下行来执行真实请求 const result = await this.queryOrder(testParams); this.log('查询订单成功:', result); - + this.log('测试完成:查询订单方法调用成功(模拟)'); - + // 返回模拟结果 return { thirdOrderId: 'thirdOrder-123456789', diff --git a/src/service/logistics.service.ts b/src/service/logistics.service.ts index b37c781..787e03e 100644 --- a/src/service/logistics.service.ts +++ b/src/service/logistics.service.ts @@ -27,6 +27,7 @@ import { CanadaPostService } from './canadaPost.service'; import { OrderItem } from '../entity/order_item.entity'; import { OrderSale } from '../entity/order_sale.entity'; import { UniExpressService } from './uni_express.service'; +import { FreightwavesService, RateTryRequest } from './freightwaves.service'; import { StockPoint } from '../entity/stock_point.entity'; import { OrderService } from './order.service'; import { convertKeysFromCamelToSnake } from '../utils/object-transform.util'; @@ -73,6 +74,9 @@ export class LogisticsService { @Inject() uniExpressService: UniExpressService; + @Inject() + freightwavesService: FreightwavesService; + @Inject() wpService: WPService; @@ -126,8 +130,8 @@ export class LogisticsService { const data = await this.uniExpressService.getOrderStatus(shipment.return_tracking_number); console.log('updateShipmentState data:', data); // huo - if(data.status === 'FAIL'){ - throw new Error('获取运单状态失败,原因为'+ data.ret_msg) + if (data.status === 'FAIL') { + throw new Error('获取运单状态失败,原因为' + data.ret_msg) } shipment.state = data.data[0].state; if (shipment.state in [203, 215, 216, 230]) { // todo,写常数 @@ -141,6 +145,30 @@ export class LogisticsService { } } + //"expressFinish": 0, //是否快递创建完成(1:完成 0:未完成,需要轮询 2:失败) + async updateFreightwavesShipmentState(shipment: Shipment) { + try { + const data = await this.freightwavesService.queryOrder({ shipOrderId: shipment.order_id.toString() }); + console.log('updateFreightwavesShipmentState data:', data); + // huo + if (data.expressFinish === 2) { + throw new Error('获取运单状态失败,原因为' + data.expressFailMsg) + } + + if (data.expressFinish === 0) { + shipment.state = '203'; + shipment.finished = true; + } + + this.shipmentModel.save(shipment); + return shipment.state; + } catch (error) { + throw error; + // throw new Error(`更新运单状态失败 ${error.message}`); + } + } + + async updateShipmentStateById(id: number) { const shipment: Shipment = await this.shipmentModel.findOneBy({ id: id }); return this.updateShipmentState(shipment); @@ -294,7 +322,18 @@ export class LogisticsService { currency: 'CAD', // item_description: data.sales, // todo: 货品信息 } - const resShipmentFee = await this.uniExpressService.getRates(reqBody); + let resShipmentFee: any; + if (data.shipmentPlatform === 'uniuni') { + resShipmentFee = await this.uniExpressService.getRates(reqBody); + } else if (data.shipmentPlatform === 'freightwaves') { + + + // resShipmentFee = await this.freightwavesService.rateTry(reqBody); + } else { + throw new Error('不支持的运单平台'); + } + + if (resShipmentFee.status !== 'SUCCESS') { throw new Error(resShipmentFee.ret_msg); } @@ -319,40 +358,49 @@ export class LogisticsService { let resShipmentOrder; try { - 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, - start_postal_code: data.details.origin.address.postal_code.replace(/\s/g, ''), - pickup_address: data.details.origin.address.address_line_1, - pickup_warehouse: stock_point.upStreamStockPointId, - shipper_country_code: data.details.origin.address.country, - receiver: data.details.destination.contact_name, - city: data.details.destination.address.city, - province: data.details.destination.address.region, - country: data.details.destination.address.country, - postal_code: data.details.destination.address.postal_code.replace(/\s/g, ''), - delivery_address: data.details.destination.address.address_line_1, - receiver_phone: data.details.destination.phone_number.number, - receiver_email: data.details.destination.email_addresses, - // item_description: data.sales, // todo: 货品信息 - length: data.details.packaging_properties.packages[0].measurements.cuboid.l, - width: data.details.packaging_properties.packages[0].measurements.cuboid.w, - height: data.details.packaging_properties.packages[0].measurements.cuboid.h, - dimension_uom: data.details.packaging_properties.packages[0].measurements.cuboid.unit, - weight: data.details.packaging_properties.packages[0].measurements.weight.value, - weight_uom: data.details.packaging_properties.packages[0].measurements.weight.unit, - currency: 'CAD', - custom_field: { - 'order_id': order.externalOrderId - } - } + //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, + // start_postal_code: data.details.origin.address.postal_code.replace(/\s/g, ''), + // pickup_address: data.details.origin.address.address_line_1, + // pickup_warehouse: stock_point.upStreamStockPointId, + // shipper_country_code: data.details.origin.address.country, + // receiver: data.details.destination.contact_name, + // city: data.details.destination.address.city, + // province: data.details.destination.address.region, + // country: data.details.destination.address.country, + // postal_code: data.details.destination.address.postal_code.replace(/\s/g, ''), + // delivery_address: data.details.destination.address.address_line_1, + // receiver_phone: data.details.destination.phone_number.number, + // receiver_email: data.details.destination.email_addresses, + // // item_description: data.sales, // todo: 货品信息 + // length: data.details.packaging_properties.packages[0].measurements.cuboid.l, + // width: data.details.packaging_properties.packages[0].measurements.cuboid.w, + // height: data.details.packaging_properties.packages[0].measurements.cuboid.h, + // dimension_uom: data.details.packaging_properties.packages[0].measurements.cuboid.unit, + // weight: data.details.packaging_properties.packages[0].measurements.weight.value, + // weight_uom: data.details.packaging_properties.packages[0].measurements.weight.unit, + // currency: 'CAD', + // custom_field: { + // 'order_id': order.externalOrderId + // } + // } - // 添加运单 - resShipmentOrder = await this.uniExpressService.createShipment(reqBody); + resShipmentOrder = await this.mepShipment(data, order); + + // if (data.shipmentPlatform === 'uniuni') { + // // 添加运单 + // resShipmentOrder = await this.uniExpressService.createShipment(reqBody); + // } + + // if (data.shipmentPlatform === 'freightwaves') { + // // 添加运单 + // resShipmentOrder = await this.freightcomService.createShipment(reqBody); + // } // 记录物流信息,并将订单状态转到完成 - if (resShipmentOrder.status === 'SUCCESS') { + if (resShipmentOrder.status === 'SUCCESS' || resShipmentOrder.code === '00000200') { order.orderStatus = ErpOrderStatus.COMPLETED; } else { throw new Error('运单生成失败'); @@ -363,12 +411,24 @@ export class LogisticsService { await dataSource.transaction(async manager => { const orderRepo = manager.getRepository(Order); const shipmentRepo = manager.getRepository(Shipment); - const tracking_provider = 'UniUni'; // todo: id未确定,后写进常数 + const tracking_provider = data.shipmentPlatform; // todo: id未确定,后写进常数 // 同步物流信息到woocommerce const site = await this.siteService.get(Number(order.siteId), true); + let co: any; + let unique_id: any; + let state: any; + if (data.shipmentPlatform === 'uniuni') { + co = resShipmentOrder.data.tno; + unique_id = resShipmentOrder.data.uni_order_sn; + state = resShipmentOrder.data.uni_status_code; + } else { + co = resShipmentOrder.data?.shipOrderId; + unique_id = resShipmentOrder.data?.shipOrderId; + state = ErpOrderStatus.COMPLETED; + } const res = await this.wpService.createFulfillment(site, order.externalOrderId, { - tracking_number: resShipmentOrder.data.tno, + tracking_number: co, tracking_provider: tracking_provider, }); @@ -376,10 +436,10 @@ export class LogisticsService { const shipment = await shipmentRepo.save({ tracking_provider: tracking_provider, tracking_id: res.data.tracking_id, - unique_id: resShipmentOrder.data.uni_order_sn, + unique_id: unique_id, stockPointId: String(data.stockPointId), // todo - state: resShipmentOrder.data.uni_status_code, - return_tracking_number: resShipmentOrder.data.tno, + state: state, + return_tracking_number: co, fee: data.details.shipmentFee, order: order }); @@ -388,12 +448,15 @@ export class LogisticsService { } // 同步订单状态到woocommerce - if (order.status !== OrderStatus.COMPLETED) { - await this.wpService.updateOrder(site, order.externalOrderId, { - status: OrderStatus.COMPLETED, - }); - order.status = OrderStatus.COMPLETED; + 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); @@ -642,4 +705,208 @@ export class LogisticsService { return { items, total, current, pageSize }; } + + + async mepShipment(data: ShipmentBookDTO, order: Order) { + try { + const stock_point = await this.stockPointModel.findOneBy({ id: data.stockPointId }); + let resShipmentOrder; + + if (data.shipmentPlatform === 'uniuni') { + const reqBody = { + sender: data.details.origin.contact_name, + start_phone: data.details.origin.phone_number, + start_postal_code: data.details.origin.address.postal_code.replace(/\s/g, ''), + pickup_address: data.details.origin.address.address_line_1, + pickup_warehouse: stock_point.upStreamStockPointId, + shipper_country_code: data.details.origin.address.country, + receiver: data.details.destination.contact_name, + city: data.details.destination.address.city, + province: data.details.destination.address.region, + country: data.details.destination.address.country, + postal_code: data.details.destination.address.postal_code.replace(/\s/g, ''), + delivery_address: data.details.destination.address.address_line_1, + receiver_phone: data.details.destination.phone_number.number, + receiver_email: data.details.destination.email_addresses, + // item_description: data.sales, // todo: 货品信息 + length: data.details.packaging_properties.packages[0].measurements.cuboid.l, + width: data.details.packaging_properties.packages[0].measurements.cuboid.w, + height: data.details.packaging_properties.packages[0].measurements.cuboid.h, + dimension_uom: data.details.packaging_properties.packages[0].measurements.cuboid.unit, + weight: data.details.packaging_properties.packages[0].measurements.weight.value, + weight_uom: data.details.packaging_properties.packages[0].measurements.weight.unit, + currency: 'CAD', + custom_field: { + 'order_id': order.externalOrderId // todo: 需要获取订单的externalOrderId + } + }; + + // 添加运单 + resShipmentOrder = await this.uniExpressService.createShipment(reqBody); + } + + if (data.shipmentPlatform === 'freightwaves') { + // 根据TMS系统对接说明文档格式化参数 + const reqBody: any = { + shipCompany: 'UPSYYZ7000NEW', + partnerOrderNumber: order.siteId + '-1-' + order.externalOrderId, + warehouseId: '25072621030107400060', + shipper: { + name: data.details.origin.contact_name, // 姓名 + phone: data.details.origin.phone_number.number, // 电话(提取number属性转换为字符串) + company: '', // 公司 + countryCode: data.details.origin.address.country, // 国家Code + city: data.details.origin.address.city, // 城市 + state: data.details.origin.address.region, // 州/省Code,两个字母缩写 + address1: data.details.origin.address.address_line_1, // 详细地址 + address2: '', // 详细地址2(Address类型中没有address_line_2属性) + postCode: data.details.origin.address.postal_code.replace(/\s/g, ''), // 邮编 + countryName: data.details.origin.address.country, // 国家名称(Address类型中没有country_name属性,使用country代替) + cityName: data.details.origin.address.city, // 城市名称 + stateName: data.details.origin.address.region, // 州/省名称 + companyName: '' // 公司名称 + }, + reciver: { + name: data.details.destination.contact_name, // 姓名 + phone: data.details.destination.phone_number.number, // 电话 + company: '', // 公司 + countryCode: data.details.destination.address.country, // 国家Code + city: data.details.destination.address.city, // 城市 + state: data.details.destination.address.region, // 州/省Code,两个字母的缩写 + address1: data.details.destination.address.address_line_1, // 详细地址 + address2: '', // 详细地址2(Address类型中没有address_line_2属性) + postCode: data.details.destination.address.postal_code.replace(/\s/g, ''), // 邮编 + countryName: data.details.destination.address.country, // 国家名称(Address类型中没有country_name属性,使用country代替) + cityName: data.details.destination.address.city, // 城市名称 + stateName: data.details.destination.address.region, // 州/省名称 + companyName: '' // 公司名称 + }, + packages: [ + { + dimensions: { + length: data.details.packaging_properties.packages[0].measurements.cuboid.l, // 长 + width: data.details.packaging_properties.packages[0].measurements.cuboid.w, // 宽 + height: data.details.packaging_properties.packages[0].measurements.cuboid.h, // 高 + lengthUnit: (data.details.packaging_properties.packages[0].measurements.cuboid.unit === 'cm' ? 'CM' : 'IN') as 'CM' | 'IN', // 长度单位(IN,CM) + weight: data.details.packaging_properties.packages[0].measurements.weight.value, // 重量 + weightUnit: (data.details.packaging_properties.packages[0].measurements.weight.unit === 'kg' ? 'KG' : 'LB') as 'KG' | 'LB' // 重量单位(LB,KG) + }, + currency: 'CAD', // 币种(默认CAD) + description: 'site:' + order.siteId + ' orderId:' + order.externalOrderId // 包裹描述(确保是字符串类型) + } + ], + signService: 0 + // signService: 0, // 签名服务 0不使用, 1使用 + // declaration: { + // "boxNo": "", //箱子编号 + // "sku": "", //SKU + // "cnname": "", //中文名称 + // "enname": "", //英文名称 + // "declaredPrice": 1, //申报单价 + // "declaredQty": 1, //申报数量 + // "material": "", //材质 + // "intendedUse": "", //用途 + // "cweight": 1, //产品单重 + // "hsCode": "", //海关编码 + // "battery": "" //电池描述 + // } + }; + + // 调用freightwaves费用试算或创建订单API + // 注意:根据实际需要调用对应的方法 + // resShipmentOrder = await this.freightwavesService.rateTry(reqBody); // 费用试算 + resShipmentOrder = await this.freightwavesService.createOrder(reqBody); // 创建订单 + } + + return resShipmentOrder; + } catch (error) { + console.log('物流订单处理失败:', error); // 使用console.log代替this.log + throw error; + } + } + + /** + * 将ShipmentFeeBookDTO转换为freightwaves的RateTryRequest格式 + * @param data ShipmentFeeBookDTO数据 + * @returns RateTryRequest格式的数据 + */ + convertToFreightwavesRateTry(data: ShipmentFeeBookDTO): Omit { + // 转换为RateTryRequest格式 + return { + shipCompany: 'UPSYYZ7000NEW', // 必填,但ShipmentFeeBookDTO中缺少 + partnerOrderNumber: `order-${Date.now()}`, // 必填,使用时间戳生成 + warehouseId: '25072621030107400060', // 可选,使用stockPointId转换 + shipper: { + name: data.sender, // 必填 + phone: data.startPhone, // 必填 + company: '', // 必填,但ShipmentFeeBookDTO中缺少 + countryCode: data.shipperCountryCode, // 必填 + city: '', // 必填,但ShipmentFeeBookDTO中缺少 + state: '', // 必填,但ShipmentFeeBookDTO中缺少 + address1: data.pickupAddress, // 必填 + address2: '', // 必填,但ShipmentFeeBookDTO中缺少 + postCode: data.startPostalCode, // 必填 + countryName: '', // 必填,但ShipmentFeeBookDTO中缺少 + cityName: '', // 必填,但ShipmentFeeBookDTO中缺少 + stateName: '', // 必填,但ShipmentFeeBookDTO中缺少 + companyName: '', // 必填,但ShipmentFeeBookDTO中缺少 + }, + reciver: { + name: data.receiver, // 必填 + phone: data.receiverPhone, // 必填 + company: '', // 必填,但ShipmentFeeBookDTO中缺少 + countryCode: data.country, // 必填,使用country代替countryCode + city: data.city, // 必填 + state: data.province, // 必填,使用province代替state + address1: data.deliveryAddress, // 必填 + address2: '', // 必填,但ShipmentFeeBookDTO中缺少 + postCode: data.postalCode, // 必填 + countryName: '', // 必填,但ShipmentFeeBookDTO中缺少 + cityName: data.city, // 必填,使用city代替cityName + stateName: data.province, // 必填,使用province代替stateName + companyName: '', // 必填,但ShipmentFeeBookDTO中缺少 + }, + packages: [ + { + dimensions: { + length: data.length, // 必填 + width: data.width, // 必填 + height: data.height, // 必填 + lengthUnit: (data.dimensionUom.toUpperCase() === 'CM' ? 'CM' : 'IN') as 'CM' | 'IN', // 必填,转换为有效的单位 + weight: data.weight, // 必填 + weightUnit: (data.weightUom.toUpperCase() === 'KG' ? 'KG' : 'LB') as 'KG' | 'LB', // 必填,转换为有效的单位 + }, + currency: 'CAD', // 必填,但ShipmentFeeBookDTO中缺少,使用默认值 + description: 'Package', // 必填,但ShipmentFeeBookDTO中缺少,使用默认值 + }, + ], + signService: 0, // 可选,默认不使用签名服务 + }; + } + + /** + * 获取ShipmentFeeBookDTO缺少的freightwaves必填字段 + * @returns 缺少的必填字段列表 + */ + getMissingFreightwavesFields(): string[] { + return [ + 'shipCompany', // 渠道 + 'partnerOrderNumber', // 第三方客户订单编号 + 'shipper.company', // 发货人公司 + 'shipper.city', // 发货人城市 + 'shipper.state', // 发货人州/省Code + 'shipper.address2', // 发货人详细地址2 + 'shipper.countryName', // 发货人国家名称 + 'shipper.cityName', // 发货人城市名称 + 'shipper.stateName', // 发货人州/省名称 + 'shipper.companyName', // 发货人公司名称 + 'reciver.company', // 收货人公司 + 'reciver.address2', // 收货人详细地址2 + 'reciver.countryName', // 收货人国家名称 + 'reciver.companyName', // 收货人公司名称 + 'packages[0].currency', // 包裹币种 + 'packages[0].description', // 包裹描述 + 'partner', // 商户ID + ]; + } } diff --git a/src/service/order.service.ts b/src/service/order.service.ts index dc363da..2b9e527 100644 --- a/src/service/order.service.ts +++ b/src/service/order.service.ts @@ -732,10 +732,12 @@ export class OrderService { } if (!orderItem.sku) return; // 从数据库查询产品,关联查询组件 - const productDetail = await this.productService.getComponentDetailFromSiteSku({ sku: orderItem.sku, name: orderItem.name }); - - if (!productDetail || !productDetail.quantity) return; - const {product, quantity} = productDetail + const product = await this.productModel.findOne({ + where: { siteSkus: Like(`%${orderItem.sku}%`) }, + relations: ['components','attributes','attributes.dict'], + }); + + if (!product) return; const componentDetails: { product: Product, quantity: number }[] = product.components?.length > 0 ? await Promise.all(product.components.map(async comp => { return { product: await this.productModel.findOne({ diff --git a/src/service/shopyy.service.ts b/src/service/shopyy.service.ts index 28029bb..b42e7c7 100644 --- a/src/service/shopyy.service.ts +++ b/src/service/shopyy.service.ts @@ -481,7 +481,7 @@ export class ShopyyService { shipping_method: data.shipping_method }; - const response = await this.request(site, `orders/${orderId}/shipments`, 'POST', fulfillmentData); + const response = await this.request(site, `orders/${orderId}/fulfillments`, 'POST', fulfillmentData); return response.data; } diff --git a/test-freightwaves.js b/test-freightwaves.js index 9236bcf..c41c661 100644 --- a/test-freightwaves.js +++ b/test-freightwaves.js @@ -9,7 +9,7 @@ async function testFreightwavesService() { // Call the test method console.log('Starting test for createOrder method...'); - const result = await service.testCreateOrder(); + const result = await service.testQueryOrder(); console.log('Test completed successfully!'); console.log('Result:', result); -- 2.40.1 From 1eacee307de305ea3555e6d213ef57ce811ec02a Mon Sep 17 00:00:00 2001 From: zhuotianyuan Date: Thu, 22 Jan 2026 17:06:51 +0800 Subject: [PATCH 06/12] =?UTF-8?q?refactor(=E8=AE=A2=E5=8D=95=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1):=20=E4=BC=98=E5=8C=96=E4=BA=A7=E5=93=81=E8=AF=A6?= =?UTF-8?q?=E6=83=85=E6=9F=A5=E8=AF=A2=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 使用 productService 的 getComponentDetailFromSiteSku 方法替代直接查询,简化代码并增加数量检查 --- src/service/order.service.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/service/order.service.ts b/src/service/order.service.ts index 2b9e527..8625380 100644 --- a/src/service/order.service.ts +++ b/src/service/order.service.ts @@ -731,13 +731,12 @@ export class OrderService { await this.orderSaleModel.delete(currentOrderSale.map(v => v.id)); } if (!orderItem.sku) return; - // 从数据库查询产品,关联查询组件 - const product = await this.productModel.findOne({ - where: { siteSkus: Like(`%${orderItem.sku}%`) }, - relations: ['components','attributes','attributes.dict'], - }); - if (!product) return; + // 从数据库查询产品,关联查询组件 + const productDetail = await this.productService.getComponentDetailFromSiteSku({ sku: orderItem.sku, name: orderItem.name }); + + if (!productDetail || !productDetail.quantity) return; + const {product, quantity} = productDetail const componentDetails: { product: Product, quantity: number }[] = product.components?.length > 0 ? await Promise.all(product.components.map(async comp => { return { product: await this.productModel.findOne({ -- 2.40.1 From 66a70f6209cfdf1c6d5bbdcff16b0cefbd0c3469 Mon Sep 17 00:00:00 2001 From: zhuotianyuan Date: Thu, 22 Jan 2026 17:12:17 +0800 Subject: [PATCH 07/12] =?UTF-8?q?fix(config):=20=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E6=9C=AC=E5=9C=B0=E6=95=B0=E6=8D=AE=E5=BA=93=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E4=B8=BA=E8=BF=9C=E7=A8=8B=E6=9C=8D=E5=8A=A1=E5=99=A8=E5=9C=B0?= =?UTF-8?q?=E5=9D=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将数据库连接配置从本地localhost改为远程服务器地址13.212.62.127,并调整端口为3306 同时启用数据库日志记录功能 --- src/config/config.local.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/config/config.local.ts b/src/config/config.local.ts index 1b92d9c..bd64204 100644 --- a/src/config/config.local.ts +++ b/src/config/config.local.ts @@ -19,12 +19,13 @@ export default { typeorm: { dataSource: { default: { - host: 'localhost', - port: "23306", + host: '13.212.62.127', + port: "3306", username: 'root', password: 'Yoone!@.2025', database: 'inventory_v2', - synchronize: true + synchronize: true, + logging: true, }, }, }, -- 2.40.1 From 926e531d4f52ae4bd2ac7d4d8b2a84a089e6bf14 Mon Sep 17 00:00:00 2001 From: zhuotianyuan Date: Thu, 22 Jan 2026 17:17:46 +0800 Subject: [PATCH 08/12] =?UTF-8?q?refactor(dto):=20=E7=A7=BB=E9=99=A4?= =?UTF-8?q?=E9=87=8D=E5=A4=8D=E7=9A=84ShopyyGetAllOrdersParams=E7=B1=BB?= =?UTF-8?q?=E5=92=8C=E5=86=97=E4=BD=99=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 删除api.dto.ts中重复定义的ShopyyGetAllOrdersParams类 移除shopyy.dto.ts中冗余的date_paid字段 --- src/dto/api.dto.ts | 17 ----------------- src/dto/shopyy.dto.ts | 2 -- 2 files changed, 19 deletions(-) diff --git a/src/dto/api.dto.ts b/src/dto/api.dto.ts index a10f6c2..b681336 100644 --- a/src/dto/api.dto.ts +++ b/src/dto/api.dto.ts @@ -76,23 +76,6 @@ export class ShopyyGetAllOrdersParams { order_field?: string;//排序字段(默认id) id=订单ID updated_at=最后更新时间 pay_at=支付时间 } -/** - * Shopyy获取所有订单参数DTO - */ -export class ShopyyGetAllOrdersParams { - @ApiProperty({ description: '每页数量', example: 100, required: false }) - per_page?: number; - - @ApiProperty({ description: '支付时间范围开始', example: '2023-01-01T00:00:00Z', required: false }) - pay_at_min?: string; - - @ApiProperty({ description: '支付时间范围结束', example: '2023-01-01T23:59:59Z', required: false }) - pay_at_max?: string; - - @ApiProperty({ description: '排序字段', example: 'id', required: false }) - order_field?: string;//排序字段(默认id) id=订单ID updated_at=最后更新时间 pay_at=支付时间 -} - /** * 批量操作错误项 */ diff --git a/src/dto/shopyy.dto.ts b/src/dto/shopyy.dto.ts index 671711d..c25cc2f 100644 --- a/src/dto/shopyy.dto.ts +++ b/src/dto/shopyy.dto.ts @@ -967,8 +967,6 @@ export interface ShopyyOrder { }>; // 支付时间 pay_at?: number | null; - // 支付时间(备用) - date_paid?: number | string; // 系统支付ID sys_payment_id?: number; -- 2.40.1 From 2f57dc0d8cdc58c24a54d05bfc33162f2e9e6931 Mon Sep 17 00:00:00 2001 From: zhuotianyuan Date: Thu, 22 Jan 2026 19:36:02 +0800 Subject: [PATCH 09/12] =?UTF-8?q?fix(logistics):=20=E4=BF=AE=E5=A4=8Dshopy?= =?UTF-8?q?y=E8=AE=A2=E5=8D=95=E5=8F=91=E8=B4=A7=E9=80=BB=E8=BE=91?= =?UTF-8?q?=E5=B9=B6=E4=BC=98=E5=8C=96freightwaves=E9=9B=86=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复shopyy平台订单发货时fulfillment接口调用问题,调整请求数据结构 优化freightwaves服务集成,添加订单查询功能 移除冗余代码,清理注释 --- src/service/freightwaves.service.ts | 4 +- src/service/logistics.service.ts | 116 +++++++++++++--------------- src/service/shopyy.service.ts | 57 +++++++------- 3 files changed, 87 insertions(+), 90 deletions(-) diff --git a/src/service/freightwaves.service.ts b/src/service/freightwaves.service.ts index be7deee..fa030ee 100644 --- a/src/service/freightwaves.service.ts +++ b/src/service/freightwaves.service.ts @@ -152,7 +152,7 @@ export class FreightwavesService { // 默认配置 private config: FreightwavesConfig = { appSecret: 'gELCHguGmdTLo!zfihfM91hae8G@9Sz23Mh6pHrt', - apiBaseUrl: 'http://tms.freightwaves.ca:8901/', + apiBaseUrl: 'http://tms.freightwaves.ca:8901', partner: '25072621035200000060' }; @@ -267,7 +267,7 @@ export class FreightwavesService { partner: this.config.partner, }; - const response = await this.sendRequest('shipService/order/createOrder', requestData); + const response = await this.sendRequest('/shipService/order/createOrder', requestData); return response; } diff --git a/src/service/logistics.service.ts b/src/service/logistics.service.ts index 787e03e..baf2a43 100644 --- a/src/service/logistics.service.ts +++ b/src/service/logistics.service.ts @@ -32,6 +32,7 @@ import { StockPoint } from '../entity/stock_point.entity'; import { OrderService } from './order.service'; import { convertKeysFromCamelToSnake } from '../utils/object-transform.util'; import { SiteService } from './site.service'; +import { ShopyyService } from './shopyy.service'; @Provide() export class LogisticsService { @@ -80,6 +81,9 @@ export class LogisticsService { @Inject() wpService: WPService; + @Inject() + shopyyService: ShopyyService; + @Inject() orderService: OrderService; @@ -358,47 +362,9 @@ export class LogisticsService { let resShipmentOrder; try { - //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, - // start_postal_code: data.details.origin.address.postal_code.replace(/\s/g, ''), - // pickup_address: data.details.origin.address.address_line_1, - // pickup_warehouse: stock_point.upStreamStockPointId, - // shipper_country_code: data.details.origin.address.country, - // receiver: data.details.destination.contact_name, - // city: data.details.destination.address.city, - // province: data.details.destination.address.region, - // country: data.details.destination.address.country, - // postal_code: data.details.destination.address.postal_code.replace(/\s/g, ''), - // delivery_address: data.details.destination.address.address_line_1, - // receiver_phone: data.details.destination.phone_number.number, - // receiver_email: data.details.destination.email_addresses, - // // item_description: data.sales, // todo: 货品信息 - // length: data.details.packaging_properties.packages[0].measurements.cuboid.l, - // width: data.details.packaging_properties.packages[0].measurements.cuboid.w, - // height: data.details.packaging_properties.packages[0].measurements.cuboid.h, - // dimension_uom: data.details.packaging_properties.packages[0].measurements.cuboid.unit, - // weight: data.details.packaging_properties.packages[0].measurements.weight.value, - // weight_uom: data.details.packaging_properties.packages[0].measurements.weight.unit, - // currency: 'CAD', - // custom_field: { - // 'order_id': order.externalOrderId - // } - // } resShipmentOrder = await this.mepShipment(data, order); - // if (data.shipmentPlatform === 'uniuni') { - // // 添加运单 - // resShipmentOrder = await this.uniExpressService.createShipment(reqBody); - // } - - // if (data.shipmentPlatform === 'freightwaves') { - // // 添加运单 - // resShipmentOrder = await this.freightcomService.createShipment(reqBody); - // } - // 记录物流信息,并将订单状态转到完成 if (resShipmentOrder.status === 'SUCCESS' || resShipmentOrder.code === '00000200') { order.orderStatus = ErpOrderStatus.COMPLETED; @@ -427,28 +393,28 @@ export class LogisticsService { unique_id = resShipmentOrder.data?.shipOrderId; state = ErpOrderStatus.COMPLETED; } - const res = await this.wpService.createFulfillment(site, order.externalOrderId, { - tracking_number: co, - 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: unique_id, - stockPointId: String(data.stockPointId), // todo - state: state, - return_tracking_number: co, - fee: data.details.shipmentFee, - order: order - }); - order.shipmentId = shipment.id; - shipmentId = shipment.id; - } // 同步订单状态到woocommerce if (order.source_type != "shopyy") { + const res = await this.wpService.createFulfillment(site, order.externalOrderId, { + tracking_number: co, + 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: unique_id, + stockPointId: String(data.stockPointId), // todo + state: state, + return_tracking_number: co, + fee: data.details.shipmentFee, + order: order + }); + order.shipmentId = shipment.id; + shipmentId = shipment.id; + } if (order.status !== OrderStatus.COMPLETED) { await this.wpService.updateOrder(site, order.externalOrderId, { status: OrderStatus.COMPLETED, @@ -456,6 +422,33 @@ export class LogisticsService { order.status = OrderStatus.COMPLETED; } } + if (order.source_type === "shopyy") { + const res = await this.shopyyService.createFulfillment(site, order.externalOrderId, { + tracking_number: co, + tracking_company: resShipmentOrder.shipCompany, + carrier_code: resShipmentOrder.shipperOrderId, + }); + if (order.orderStatus === ErpOrderStatus.COMPLETED) { + const shipment = await shipmentRepo.save({ + tracking_provider: tracking_provider, + tracking_id: res.data.tracking_id, + unique_id: unique_id, + stockPointId: String(data.stockPointId), // todo + state: state, + return_tracking_number: co, + fee: data.details.shipmentFee, + order: order + }); + order.shipmentId = shipment.id; + shipmentId = shipment.id; + } + if (order.status !== OrderStatus.COMPLETED) { + // await this.shopyyService.updateOrder(site, order.externalOrderId, { + // status: OrderStatus.COMPLETED, + // }); + order.status = OrderStatus.COMPLETED; + } + } order.orderStatus = ErpOrderStatus.COMPLETED; @@ -796,7 +789,7 @@ export class LogisticsService { } ], signService: 0 - // signService: 0, // 签名服务 0不使用, 1使用 + // 非跨境订单不需要declaration // declaration: { // "boxNo": "", //箱子编号 // "sku": "", //SKU @@ -812,10 +805,11 @@ export class LogisticsService { // } }; - // 调用freightwaves费用试算或创建订单API - // 注意:根据实际需要调用对应的方法 - // resShipmentOrder = await this.freightwavesService.rateTry(reqBody); // 费用试算 resShipmentOrder = await this.freightwavesService.createOrder(reqBody); // 创建订单 + const queryRes = await this.freightwavesService.queryOrder({ shipOrderId: resShipmentOrder.shipOrderId }); // 查询订单 + console.log('queryRes:', queryRes); // 打印查询结果 + resShipmentOrder.push(queryRes); + } return resShipmentOrder; diff --git a/src/service/shopyy.service.ts b/src/service/shopyy.service.ts index b42e7c7..616705f 100644 --- a/src/service/shopyy.service.ts +++ b/src/service/shopyy.service.ts @@ -10,14 +10,14 @@ import { Site } from '../entity/site.entity'; import { UnifiedReviewDTO } from '../dto/site-api.dto'; import { ShopyyGetOneOrderResult, ShopyyReview } from '../dto/shopyy.dto'; import { BatchOperationDTO, BatchOperationResultDTO } from '../dto/batch.dto'; -import { UnifiedSearchParamsDTO,ShopyyGetAllOrdersParams } from '../dto/api.dto'; +import { UnifiedSearchParamsDTO, ShopyyGetAllOrdersParams } from '../dto/api.dto'; /** * ShopYY平台服务实现 */ @Provide() export class ShopyyService { @Inject() - logger:ILogger; + logger: ILogger; /** * 获取ShopYY评论列表 * @param site 站点配置 @@ -184,9 +184,9 @@ export class ShopyyService { */ public async fetchResourcePaged(site: any, endpoint: string, params: Record = {}) { const response = await this.request(site, endpoint, 'GET', null, params); - return this.mapPageResponse(response,params); + return this.mapPageResponse(response, params); } - mapPageResponse(response:any,query: Record){ + mapPageResponse(response: any, query: Record) { if (response?.code !== 0) { throw new Error(response?.msg) } @@ -272,7 +272,7 @@ export class ShopyyService { const response = await this.request(site, `products/${productId}/variations/${variationId}`, 'GET'); return response.data; } - mapOrderSearchParams(params: UnifiedSearchParamsDTO){ + mapOrderSearchParams(params: UnifiedSearchParamsDTO) { const { after, before, ...restParams } = params; return { ...restParams, @@ -310,9 +310,9 @@ export class ShopyyService { async getAllOrders(site: any | number, params: ShopyyGetAllOrdersParams = {}, maxPages: number = 10, concurrencyLimit: number = 100): Promise { const firstPage = await this.getOrders(site, 1, 100, params); - - const { items: firstPageItems, totalPages} = firstPage; - + + const { items: firstPageItems, totalPages } = firstPage; + // 如果只有一页数据,直接返回 if (totalPages <= 1) { return firstPageItems; @@ -320,7 +320,7 @@ export class ShopyyService { // 限制最大页数,避免过多的并发请求 const actualMaxPages = Math.min(totalPages, maxPages); - + // 收集所有页面数据,从第二页开始 const allItems = [...firstPageItems]; let currentPage = 2; @@ -329,7 +329,7 @@ export class ShopyyService { while (currentPage <= actualMaxPages) { const batchPromises: Promise[] = []; const batchSize = Math.min(concurrencyLimit, actualMaxPages - currentPage + 1); - + // 创建当前批次的并发请求 for (let i = 0; i < batchSize; i++) { const page = currentPage + i; @@ -339,25 +339,25 @@ export class ShopyyService { console.error(`获取第 ${page} 页数据失败:`, error); return []; // 如果某页获取失败,返回空数组,不影响整体结果 }); - + batchPromises.push(pagePromise); } // 等待当前批次完成 const batchResults = await Promise.all(batchPromises); - + // 合并当前批次的数据 for (const pageItems of batchResults) { allItems.push(...pageItems); } - + // 移动到下一批次 currentPage += batchSize; } return allItems; } - + /** * 获取ShopYY订单详情 @@ -475,13 +475,16 @@ export class ShopyyService { async createFulfillment(site: Site, orderId: string, data: any): Promise { // ShopYY API: POST /orders/{id}/shipments const fulfillmentData = { - tracking_number: data.tracking_number, - carrier_code: data.carrier_code, - carrier_name: data.carrier_name, - shipping_method: data.shipping_method + data: [{ + order_number: orderId, + tracking_company: data.tracking_company, + tracking_number: data.tracking_number, + carrier_code: data.carrier_code, + note: "note", + mode: "" + }] }; - - const response = await this.request(site, `orders/${orderId}/fulfillments`, 'POST', fulfillmentData); + const response = await this.request(site, `orders/fulfillments`, 'POST', fulfillmentData); return response.data; } @@ -494,7 +497,7 @@ export class ShopyyService { */ async deleteFulfillment(site: any, orderId: string, fulfillmentId: string): Promise { try { - // ShopYY API: DELETE /orders/{order_id}/shipments/{fulfillment_id} + // ShopYY API: DELETE /orders/fulfillments/{fulfillment_id} await this.request(site, `orders/${orderId}/fulfillments/${fulfillmentId}`, 'DELETE'); return true; } catch (error) { @@ -542,7 +545,7 @@ export class ShopyyService { try { // ShopYY API: PUT /orders/{order_id}/shipments/{tracking_id} const fulfillmentData: any = {}; - + // 只传递有值的字段 if (data.tracking_number !== undefined) { fulfillmentData.tracking_number = data.tracking_number; @@ -645,10 +648,10 @@ export class ShopyyService { // ShopYY API: POST /products/batch const response = await this.request(site, 'products/batch', 'POST', data); const result = response.data; - + // 转换 ShopYY 批量操作结果为统一格式 - const errors: Array<{identifier: string, error: string}> = []; - + const errors: Array<{ identifier: string, error: string }> = []; + // 假设 ShopYY 返回格式与 WooCommerce 类似: { create: [...], update: [...], delete: [...] } // 错误信息可能在每个项目的 error 字段中 const checkForErrors = (items: any[]) => { @@ -661,12 +664,12 @@ export class ShopyyService { } }); }; - + // 检查每个操作类型的结果中的错误 if (result.create) checkForErrors(result.create); if (result.update) checkForErrors(result.update); if (result.delete) checkForErrors(result.delete); - + return { total: (data.create?.length || 0) + (data.update?.length || 0) + (data.delete?.length || 0), processed: (result.create?.length || 0) + (result.update?.length || 0) + (result.delete?.length || 0), -- 2.40.1 From 22a13ce0b895c4cb92d65b4cdef89640123add93 Mon Sep 17 00:00:00 2001 From: zhuotianyuan Date: Fri, 23 Jan 2026 16:29:10 +0800 Subject: [PATCH 10/12] =?UTF-8?q?feat(logistics):=20=E5=AE=8C=E5=96=84frei?= =?UTF-8?q?ghtwaves=E8=BF=90=E8=B4=B9=E8=AF=95=E7=AE=97=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 重构convertToFreightwavesRateTry方法,添加地址查询逻辑 移除freightwaves服务中无用的测试方法 修复订单同步日志格式和注释 --- src/dto/logistics.dto.ts | 2 +- src/entity/shipping_address.entity.ts | 5 + src/service/freightwaves.service.ts | 240 -------------------------- src/service/logistics.service.ts | 100 ++++------- src/service/order.service.ts | 74 ++++---- 5 files changed, 80 insertions(+), 341 deletions(-) diff --git a/src/dto/logistics.dto.ts b/src/dto/logistics.dto.ts index fa57e60..b49b72c 100644 --- a/src/dto/logistics.dto.ts +++ b/src/dto/logistics.dto.ts @@ -34,7 +34,7 @@ export class ShipmentFeeBookDTO { @ApiProperty() sender: string; @ApiProperty() - startPhone: string; + startPhone: string|any; @ApiProperty() startPostalCode: string; @ApiProperty() diff --git a/src/entity/shipping_address.entity.ts b/src/entity/shipping_address.entity.ts index 7af0422..e6fea86 100644 --- a/src/entity/shipping_address.entity.ts +++ b/src/entity/shipping_address.entity.ts @@ -47,6 +47,11 @@ export class ShippingAddress { @Expose() phone_number_country: string; + @ApiProperty() + @Column() + @Expose() + email: string; + @ApiProperty({ example: '2022-12-12 11:11:11', description: '创建时间', diff --git a/src/service/freightwaves.service.ts b/src/service/freightwaves.service.ts index fa030ee..04f51fe 100644 --- a/src/service/freightwaves.service.ts +++ b/src/service/freightwaves.service.ts @@ -314,250 +314,10 @@ export class FreightwavesService { ...params, partner: this.config.partner, }; - const response = await this.sendRequest('/shipService/order/refundOrder', requestData); return response.data; } - /** - * 测试创建订单方法 - * 用于演示如何使用createOrder方法 - */ - async testCreateOrder() { - try { - // 设置必要的配置 - this.setConfig({ - appSecret: 'gELCHguGmdTLo!zfihfM91hae8G@9Sz23Mh6pHrt', - apiBaseUrl: 'http://tms.freightwaves.ca:8901/', - partner: '25072621035200000060' - }); - - // 准备测试数据 - const testParams: Omit = { - shipCompany: 'UPSYYZ7000NEW', - partnerOrderNumber: `test-order-${Date.now()}`, - warehouseId: '25072621030107400060', - shipper: { - name: 'John Doe', - phone: '123-456-7890', - company: 'Test Company', - countryCode: 'CA', - city: 'Toronto', - state: 'ON', - address1: '123 Main St', - address2: 'Suite 400', - postCode: 'M5V 2T6', - countryName: 'Canada', - cityName: 'Toronto', - stateName: 'Ontario', - companyName: 'Test Company Inc.' - }, - reciver: { - name: 'Jane Smith', - phone: '987-654-3210', - company: 'Receiver Company', - countryCode: 'CA', - city: 'Vancouver', - state: 'BC', - address1: '456 Oak St', - address2: '', - postCode: 'V6J 2A9', - countryName: 'Canada', - cityName: 'Vancouver', - stateName: 'British Columbia', - companyName: 'Receiver Company Ltd.' - }, - packages: [ - { - dimensions: { - length: 10, - width: 8, - height: 6, - lengthUnit: 'IN', - weight: 5, - weightUnit: 'LB' - }, - currency: 'CAD', - description: 'Test Package' - } - ], - declaration: { - boxNo: 'BOX-001', - sku: 'TEST-SKU-001', - cnname: '测试产品', - enname: 'Test Product', - declaredPrice: 100, - declaredQty: 1, - material: 'Plastic', - intendedUse: 'General use', - cweight: 5, - hsCode: '39269090', - battery: 'No' - }, - signService: 0 - }; - - // 调用创建订单方法 - this.log('开始测试创建订单...'); - this.log('测试参数:', testParams); - - // 注意:在实际环境中取消注释以下行来执行真实请求 - const result = await this.createOrder(testParams); - this.log('创建订单成功:', result); - - - // 返回模拟结果 - return { - partnerOrderNumber: testParams.partnerOrderNumber, - shipOrderId: `simulated-shipOrderId-${Date.now()}` - }; - } catch (error) { - this.log('测试创建订单失败:', error); - throw error; - } - } - - /** - * 测试费用试算方法 - * @returns 费用试算结果 - */ - async testRateTry() { - try { - // 设置必要的配置 - this.setConfig({ - appSecret: 'gELCHguGmdTLo!zfihfM91hae8G@9Sz23Mh6pHrt', - apiBaseUrl: 'http://tms.freightwaves.ca:8901', - partner: '25072621035200000060' - }); - - // 准备测试数据 - 符合RateTryRequest接口要求 - const testParams: Omit = { - shipCompany: 'UPSYYZ7000NEW', - partnerOrderNumber: `test-rate-try-${Date.now()}`, - warehouseId: '25072621030107400060', - shipper: { - name: 'John Doe', - phone: '123-456-7890', - company: 'Test Company', - countryCode: 'CA', - city: 'Toronto', - state: 'ON', - address1: '123 Main St', - address2: 'Suite 400', - postCode: 'M5V 2T6', - countryName: 'Canada', - cityName: 'Toronto', - stateName: 'Ontario', - companyName: 'Test Company Inc.' - }, - reciver: { - name: 'Jane Smith', - phone: '987-654-3210', - company: 'Receiver Company', - countryCode: 'CA', - city: 'Vancouver', - state: 'BC', - address1: '456 Oak St', - address2: '', - postCode: 'V6J 2A9', - countryName: 'Canada', - cityName: 'Vancouver', - stateName: 'British Columbia', - companyName: 'Receiver Company Ltd.' - }, - packages: [ - { - dimensions: { - length: 10, - width: 8, - height: 6, - lengthUnit: 'IN', - weight: 5, - weightUnit: 'LB' - }, - currency: 'CAD', - description: 'Test Package' - } - ], - signService: 0 - }; - - // 调用费用试算方法 - this.log('开始测试费用试算...'); - this.log('测试参数:', testParams); - - // 注意:在实际环境中取消注释以下行来执行真实请求 - const result = await this.rateTry(testParams); - this.log('费用试算成功:', result); - - this.log('测试完成:费用试算方法调用成功(模拟)'); - this.log('提示:在实际环境中,取消注释代码中的rateTry调用行来执行真实请求'); - - // 返回模拟结果 - return { - shipCompany: 'DHL', - channelCode: 'DHL-EXPRESS', - totalAmount: 125.50, - currency: 'CAD' - }; - } catch (error) { - this.log('测试费用试算失败:', error); - throw error; - } - } - - /** - * 测试查询订单方法 - * @returns 查询订单结果 - */ - async testQueryOrder() { - try { - // 设置必要的配置 - this.setConfig({ - appSecret: 'gELCHguGmdTLo!zfihfM91hae8G@9Sz23Mh6pHrt', - apiBaseUrl: 'http://freightwaves.ca:8901', - partner: '25072621035200000060' - }); - - // 准备测试数据 - 可以通过partnerOrderNumber或shipOrderId查询 - const testParams: Omit = { - // 选择其中一个参数进行测试 - partnerOrderNumber: 'test-order-123456789', // 示例订单号 - // shipOrderId: 'simulated-shipOrderId-123456789' // 或者使用运单号 - }; - - // 调用查询订单方法 - this.log('开始测试查询订单...'); - this.log('测试参数:', testParams); - - // 注意:在实际环境中取消注释以下行来执行真实请求 - const result = await this.queryOrder(testParams); - this.log('查询订单成功:', result); - - this.log('测试完成:查询订单方法调用成功(模拟)'); - - // 返回模拟结果 - return { - thirdOrderId: 'thirdOrder-123456789', - shipCompany: 'DHL', - expressFinish: 0, - expressFailMsg: '', - expressOrder: { - mainTrackingNumber: '1234567890', - labelPath: ['https://example.com/label.pdf'], - totalAmount: 100, - currency: 'CAD', - balance: 50 - }, - partnerOrderNumber: testParams.partnerOrderNumber, - shipOrderId: 'simulated-shipOrderId-123456789' - }; - } catch (error) { - this.log('测试查询订单失败:', error); - throw error; - } - } - /** * 辅助日志方法,处理logger可能未定义的情况 * @param message 日志消息 diff --git a/src/service/logistics.service.ts b/src/service/logistics.service.ts index baf2a43..4e472be 100644 --- a/src/service/logistics.service.ts +++ b/src/service/logistics.service.ts @@ -279,8 +279,7 @@ export class LogisticsService { shipmentRepo.remove(shipment); - const res = await this.uniExpressService.deleteShipment(shipment.return_tracking_number); - console.log('res', res.data); // todo + await this.uniExpressService.deleteShipment(shipment.return_tracking_number); await orderRepo.save(order); @@ -310,7 +309,6 @@ export class LogisticsService { console.log('同步到woocommerce失败', error); return true; } - return true; } catch { throw new Error('删除运单失败'); @@ -330,14 +328,12 @@ export class LogisticsService { if (data.shipmentPlatform === 'uniuni') { resShipmentFee = await this.uniExpressService.getRates(reqBody); } else if (data.shipmentPlatform === 'freightwaves') { - - - // resShipmentFee = await this.freightwavesService.rateTry(reqBody); + const fre_reqBody = await this.convertToFreightwavesRateTry(data); + resShipmentFee = await this.freightwavesService.rateTry(fre_reqBody); } else { throw new Error('不支持的运单平台'); } - if (resShipmentFee.status !== 'SUCCESS') { throw new Error(resShipmentFee.ret_msg); } @@ -362,10 +358,9 @@ export class LogisticsService { let resShipmentOrder; try { - resShipmentOrder = await this.mepShipment(data, order); - // 记录物流信息,并将订单状态转到完成 + // 记录物流信息,并将订单状态转到完成,uniuni状态为SUCCESS,tms.freightwaves状态为00000200 if (resShipmentOrder.status === 'SUCCESS' || resShipmentOrder.code === '00000200') { order.orderStatus = ErpOrderStatus.COMPLETED; } else { @@ -443,25 +438,23 @@ export class LogisticsService { shipmentId = shipment.id; } if (order.status !== OrderStatus.COMPLETED) { + // shopyy未提供更新订单接口,暂不更新订单状态 // await this.shopyyService.updateOrder(site, order.externalOrderId, { // status: OrderStatus.COMPLETED, // }); order.status = OrderStatus.COMPLETED; } } - order.orderStatus = ErpOrderStatus.COMPLETED; - await orderRepo.save(order); }).catch(error => { transactionError = error + throw new Error(`请求错误:${error}`); }); if (transactionError !== undefined) { - console.log('err', transactionError); throw transactionError; } - // 更新产品发货信息 this.orderService.updateOrderSales(order.id, sales); @@ -733,7 +726,6 @@ export class LogisticsService { 'order_id': order.externalOrderId // todo: 需要获取订单的externalOrderId } }; - // 添加运单 resShipmentOrder = await this.uniExpressService.createShipment(reqBody); } @@ -742,7 +734,7 @@ export class LogisticsService { // 根据TMS系统对接说明文档格式化参数 const reqBody: any = { shipCompany: 'UPSYYZ7000NEW', - partnerOrderNumber: order.siteId + '-1-' + order.externalOrderId, + partnerOrderNumber: order.siteId + '-' + order.externalOrderId, warehouseId: '25072621030107400060', shipper: { name: data.details.origin.contact_name, // 姓名 @@ -806,10 +798,9 @@ export class LogisticsService { }; resShipmentOrder = await this.freightwavesService.createOrder(reqBody); // 创建订单 + //tms只返回了物流订单号,需要查询一次来获取完整的物流信息 const queryRes = await this.freightwavesService.queryOrder({ shipOrderId: resShipmentOrder.shipOrderId }); // 查询订单 - console.log('queryRes:', queryRes); // 打印查询结果 resShipmentOrder.push(queryRes); - } return resShipmentOrder; @@ -824,41 +815,49 @@ export class LogisticsService { * @param data ShipmentFeeBookDTO数据 * @returns RateTryRequest格式的数据 */ - convertToFreightwavesRateTry(data: ShipmentFeeBookDTO): Omit { + async convertToFreightwavesRateTry(data: ShipmentFeeBookDTO): Promise> { + + const shipments = await this.shippingAddressModel.findOne({ + where: { + id: data.address_id, + }, + }) + + const address = shipments?.address; // 转换为RateTryRequest格式 - return { + const r = { shipCompany: 'UPSYYZ7000NEW', // 必填,但ShipmentFeeBookDTO中缺少 partnerOrderNumber: `order-${Date.now()}`, // 必填,使用时间戳生成 warehouseId: '25072621030107400060', // 可选,使用stockPointId转换 shipper: { name: data.sender, // 必填 - phone: data.startPhone, // 必填 - company: '', // 必填,但ShipmentFeeBookDTO中缺少 + phone: data.startPhone.phone, // 必填 + company: address.country, // 必填,但ShipmentFeeBookDTO中缺少 countryCode: data.shipperCountryCode, // 必填 - city: '', // 必填,但ShipmentFeeBookDTO中缺少 - state: '', // 必填,但ShipmentFeeBookDTO中缺少 - address1: data.pickupAddress, // 必填 - address2: '', // 必填,但ShipmentFeeBookDTO中缺少 + city: address.city || '', // 必填,但ShipmentFeeBookDTO中缺少 + state: address.region || '', // 必填,但ShipmentFeeBookDTO中缺少 + address1: address.address_line_1, // 必填 + address2: address.address_line_1 || '', // 必填,但ShipmentFeeBookDTO中缺少 postCode: data.startPostalCode, // 必填 - countryName: '', // 必填,但ShipmentFeeBookDTO中缺少 - cityName: '', // 必填,但ShipmentFeeBookDTO中缺少 - stateName: '', // 必填,但ShipmentFeeBookDTO中缺少 - companyName: '', // 必填,但ShipmentFeeBookDTO中缺少 + countryName: address.country || '', // 必填,但ShipmentFeeBookDTO中缺少 + cityName: address.city || '', // 必填,但ShipmentFeeBookDTO中缺少 + stateName: address.region || '', // 必填,但ShipmentFeeBookDTO中缺少 + companyName: address.country || '', // 必填,但ShipmentFeeBookDTO中缺少 }, reciver: { name: data.receiver, // 必填 phone: data.receiverPhone, // 必填 - company: '', // 必填,但ShipmentFeeBookDTO中缺少 + company: address.country,// 必填,但ShipmentFeeBookDTO中缺少 countryCode: data.country, // 必填,使用country代替countryCode city: data.city, // 必填 state: data.province, // 必填,使用province代替state address1: data.deliveryAddress, // 必填 - address2: '', // 必填,但ShipmentFeeBookDTO中缺少 + address2: data.deliveryAddress, // 必填,但ShipmentFeeBookDTO中缺少 postCode: data.postalCode, // 必填 - countryName: '', // 必填,但ShipmentFeeBookDTO中缺少 - cityName: data.city, // 必填,使用city代替cityName - stateName: data.province, // 必填,使用province代替stateName - companyName: '', // 必填,但ShipmentFeeBookDTO中缺少 + countryName: address.country, // 必填,但ShipmentFeeBookDTO中缺少 + cityName: data.city || '', // 必填,使用city代替cityName + stateName: data.province || '', // 必填,使用province代替stateName + companyName: address.country || '', // 必填,但ShipmentFeeBookDTO中缺少 }, packages: [ { @@ -866,9 +865,9 @@ export class LogisticsService { length: data.length, // 必填 width: data.width, // 必填 height: data.height, // 必填 - lengthUnit: (data.dimensionUom.toUpperCase() === 'CM' ? 'CM' : 'IN') as 'CM' | 'IN', // 必填,转换为有效的单位 + lengthUnit: (data.dimensionUom === 'IN' ? 'IN' : 'CM') as 'IN' | 'CM', // 必填,转换为有效的单位 weight: data.weight, // 必填 - weightUnit: (data.weightUom.toUpperCase() === 'KG' ? 'KG' : 'LB') as 'KG' | 'LB', // 必填,转换为有效的单位 + weightUnit: (data.weightUom === 'LBS' ? 'LB' : 'KG') as 'LB' | 'KG', // 必填,转换为有效的单位 }, currency: 'CAD', // 必填,但ShipmentFeeBookDTO中缺少,使用默认值 description: 'Package', // 必填,但ShipmentFeeBookDTO中缺少,使用默认值 @@ -876,31 +875,6 @@ export class LogisticsService { ], signService: 0, // 可选,默认不使用签名服务 }; - } - - /** - * 获取ShipmentFeeBookDTO缺少的freightwaves必填字段 - * @returns 缺少的必填字段列表 - */ - getMissingFreightwavesFields(): string[] { - return [ - 'shipCompany', // 渠道 - 'partnerOrderNumber', // 第三方客户订单编号 - 'shipper.company', // 发货人公司 - 'shipper.city', // 发货人城市 - 'shipper.state', // 发货人州/省Code - 'shipper.address2', // 发货人详细地址2 - 'shipper.countryName', // 发货人国家名称 - 'shipper.cityName', // 发货人城市名称 - 'shipper.stateName', // 发货人州/省名称 - 'shipper.companyName', // 发货人公司名称 - 'reciver.company', // 收货人公司 - 'reciver.address2', // 收货人详细地址2 - 'reciver.countryName', // 收货人国家名称 - 'reciver.companyName', // 收货人公司名称 - 'packages[0].currency', // 包裹币种 - 'packages[0].description', // 包裹描述 - 'partner', // 商户ID - ]; + return r as any; } } diff --git a/src/service/order.service.ts b/src/service/order.service.ts index 8625380..41e15b3 100644 --- a/src/service/order.service.ts +++ b/src/service/order.service.ts @@ -141,8 +141,8 @@ export class OrderService { updated: 0, errors: [] }; - console.log('开始进入循环同步订单', result.length, '个订单') - console.log('开始进入循环同步订单', result.length, '个订单') + console.log('开始进入循环同步订单', result.length, '个订单') + console.log('开始进入循环同步订单', result.length, '个订单') // 遍历每个订单进行同步 for (const order of result) { try { @@ -166,7 +166,7 @@ export class OrderService { } else { syncResult.created++; } - // console.log('updated', syncResult.updated, 'created:', syncResult.created) + // console.log('updated', syncResult.updated, 'created:', syncResult.created) } catch (error) { // 记录错误但不中断整个同步过程 syncResult.errors.push({ @@ -176,8 +176,8 @@ export class OrderService { syncResult.processed++; } } - console.log('同步完成', syncResult.updated, 'created:', syncResult.created) - + console.log('同步完成', syncResult.updated, 'created:', syncResult.created) + this.logger.debug('syncOrders result', syncResult) return syncResult; } @@ -337,26 +337,26 @@ export class OrderService { // 自动更新订单状态(如果需要) await this.autoUpdateOrderStatus(siteId, order); - if(existingOrder){ - // 矫正数据库中的订单数据 - const updateData: any = { status: order.status }; - if (this.canUpdateErpStatus(existingOrder.orderStatus)) { - updateData.orderStatus = this.mapOrderStatus(order.status as any); - } - // 更新订单主数据 - await this.orderModel.update({ externalOrderId: String(order.id), siteId: siteId }, updateData); - // 更新 fulfillments 数据 - await this.saveOrderFulfillments({ - siteId, - orderId: existingOrder.id, - externalOrderId:order.id, - fulfillments: fulfillments, - }); + if (existingOrder) { + // 矫正数据库中的订单数据 + const updateData: any = { status: order.status }; + if (this.canUpdateErpStatus(existingOrder.orderStatus)) { + updateData.orderStatus = this.mapOrderStatus(order.status as any); + } + // 更新订单主数据 + await this.orderModel.update({ externalOrderId: String(order.id), siteId: siteId }, updateData); + // 更新 fulfillments 数据 + await this.saveOrderFulfillments({ + siteId, + orderId: existingOrder.id, + externalOrderId: order.id, + fulfillments: fulfillments, + }); } - const externalOrderId = String(order.id); + const externalOrderId = String(order.id); // 这里的 saveOrder 已经包括了创建订单和更新订单 let orderRecord: Order = await this.saveOrder(siteId, orderData); - // 如果订单从未完成变为完成状态,则更新库存 + // 如果订单从未完成变为完成状态,则更新库存 if ( orderRecord && orderRecord.orderStatus !== ErpOrderStatus.COMPLETED && @@ -377,7 +377,7 @@ export class OrderService { await this.saveOrderRefunds({ siteId, orderId, - externalOrderId , + externalOrderId, refunds, }); // 保存费用信息 @@ -731,12 +731,12 @@ export class OrderService { await this.orderSaleModel.delete(currentOrderSale.map(v => v.id)); } if (!orderItem.sku) return; - - // 从数据库查询产品,关联查询组件 + + // 从数据库查询产品,关联查询组件 const productDetail = await this.productService.getComponentDetailFromSiteSku({ sku: orderItem.sku, name: orderItem.name }); - - if (!productDetail || !productDetail.quantity) return; - const {product, quantity} = productDetail + + if (!productDetail || !productDetail.quantity) return; + const { product, quantity } = productDetail const componentDetails: { product: Product, quantity: number }[] = product.components?.length > 0 ? await Promise.all(product.components.map(async comp => { return { product: await this.productModel.findOne({ @@ -770,7 +770,7 @@ export class OrderService { }); return orderSale }).filter(v => v !== null) - console.log("orderSales",orderSales) + console.log("orderSales", orderSales) if (orderSales.length > 0) { await this.orderSaleModel.save(orderSales); } @@ -2676,10 +2676,10 @@ export class OrderService { // 辅助函数:删除指定位置的括号对及其内容 const removeParenthesesAt = (s: string, leftIndex: number): string => { if (leftIndex === -1) return s; - + let rightIndex = -1; let parenCount = 0; - + for (let i = leftIndex; i < s.length; i++) { const char = s[i]; if (char === '(') { @@ -2692,17 +2692,17 @@ export class OrderService { } } } - + if (rightIndex !== -1) { return s.substring(0, leftIndex) + s.substring(rightIndex + 1); } - + return s; }; // 1. 处理每个分号前面的括号对 let result = str; - + // 找出所有分号的位置 const semicolonIndices: number[] = []; for (let i = 0; i < result.length; i++) { @@ -2710,11 +2710,11 @@ export class OrderService { semicolonIndices.push(i); } } - + // 从后向前处理每个分号,避免位置变化影响后续处理 for (let i = semicolonIndices.length - 1; i >= 0; i--) { const semicolonIndex = semicolonIndices[i]; - + // 从分号位置向前查找最近的左括号 let lastLeftParenIndex = -1; for (let j = semicolonIndex - 1; j >= 0; j--) { @@ -2723,7 +2723,7 @@ export class OrderService { break; } } - + // 如果找到左括号,删除该括号对及其内容 if (lastLeftParenIndex !== -1) { result = removeParenthesesAt(result, lastLeftParenIndex); -- 2.40.1 From 5f16801f98710345aa1c2e623d1debefcef74f45 Mon Sep 17 00:00:00 2001 From: zhuotianyuan Date: Fri, 23 Jan 2026 16:33:14 +0800 Subject: [PATCH 11/12] =?UTF-8?q?refactor:=20=E7=A7=BB=E9=99=A4=E8=B0=83?= =?UTF-8?q?=E8=AF=95=E7=94=A8=E7=9A=84console.log=E8=AF=AD=E5=8F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/service/freightwaves.service.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/service/freightwaves.service.ts b/src/service/freightwaves.service.ts index 04f51fe..f2bbe0a 100644 --- a/src/service/freightwaves.service.ts +++ b/src/service/freightwaves.service.ts @@ -179,12 +179,6 @@ export class FreightwavesService { 'signature': this.generateSignature(data, date), }; - // 记录请求前的详细信息 - console.log(`Sending request to: ${this.config.apiBaseUrl}${url}`, JSON.stringify({ - headers, - data - })) - console.log('Request data:', `${this.config.apiBaseUrl}${url}`, data, headers); // 发送请求 - 临时禁用SSL证书验证以解决UNABLE_TO_VERIFY_LEAF_SIGNATURE错误 const response = await axios.post>( `${this.config.apiBaseUrl}${url}`, -- 2.40.1 From e8424afd91c304acf56aedf6da1b567e8d0570f9 Mon Sep 17 00:00:00 2001 From: zhuotianyuan Date: Fri, 23 Jan 2026 17:02:10 +0800 Subject: [PATCH 12/12] =?UTF-8?q?refactor(=E8=AE=A2=E5=8D=95=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1):=20=E6=9B=BF=E6=8D=A2console.log=E4=B8=BAlogger?= =?UTF-8?q?=E5=B9=B6=E7=A7=BB=E9=99=A4=E9=87=8D=E5=A4=8D=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 移除重复的console.log调用,统一使用logger进行日志记录 清理调试日志并优化日志级别使用 --- src/service/order.service.ts | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/src/service/order.service.ts b/src/service/order.service.ts index 41e15b3..321221c 100644 --- a/src/service/order.service.ts +++ b/src/service/order.service.ts @@ -141,8 +141,7 @@ export class OrderService { updated: 0, errors: [] }; - console.log('开始进入循环同步订单', result.length, '个订单') - console.log('开始进入循环同步订单', result.length, '个订单') + this.logger.info('开始进入循环同步订单', result.length, '个订单') // 遍历每个订单进行同步 for (const order of result) { try { @@ -151,7 +150,7 @@ export class OrderService { where: { externalOrderId: String(order.id), siteId: siteId }, }); if (!existingOrder) { - console.log("数据库中不存在", order.id, '订单状态:', order.status) + this.logger.debug("数据库中不存在", order.id, '订单状态:', order.status) } // 同步单个订单 await this.syncSingleOrder(siteId, order); @@ -176,9 +175,7 @@ export class OrderService { syncResult.processed++; } } - console.log('同步完成', syncResult.updated, 'created:', syncResult.created) - - this.logger.debug('syncOrders result', syncResult) + this.logger.info('同步完成', syncResult.updated, 'created:', syncResult.created) return syncResult; } @@ -216,7 +213,7 @@ export class OrderService { where: { externalOrderId: String(order.id), siteId: siteId }, }); if (!existingOrder) { - console.log("数据库不存在", siteId, "订单:", order.id, '订单状态:' + order.status) + this.logger.debug("数据库不存在", siteId, "订单:", order.id, '订单状态:' + order.status) } // 同步单个订单 await this.syncSingleOrder(siteId, order, true); @@ -770,7 +767,6 @@ export class OrderService { }); return orderSale }).filter(v => v !== null) - console.log("orderSales", orderSales) if (orderSales.length > 0) { await this.orderSaleModel.save(orderSales); } @@ -1562,7 +1558,6 @@ export class OrderService { GROUP BY os.productId `; - console.log('------3.5-----', pcSql, pcParams, exceptPackage); const pcResults = await this.orderSaleModel.query(pcSql, pcParams); const pcMap = new Map(); @@ -2641,13 +2636,9 @@ export class OrderService { if (!fs.existsSync(downloadsDir)) { fs.mkdirSync(downloadsDir, { recursive: true }); } - const filePath = path.join(downloadsDir, fileName); - // 写入文件 fs.writeFileSync(filePath, csvContent, 'utf8'); - - console.log(`数据已成功导出至 ${filePath}`); return filePath; } @@ -2658,7 +2649,6 @@ export class OrderService { return csvContent; } catch (error) { - console.error('导出CSV时出错:', error); throw new Error(`导出CSV文件失败: ${error.message}`); } } -- 2.40.1