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),