From d59e17fefc31faf9fab47694cd8adf949260e0e2 Mon Sep 17 00:00:00 2001 From: longbot <444693295@qq.com> Date: Fri, 8 Aug 2025 19:21:43 +0800 Subject: [PATCH] =?UTF-8?q?Fix:=20=20=20bug=20fix=20=20=20=E5=AE=8C?= =?UTF-8?q?=E5=96=84=E4=B8=8B=E5=8D=95=E5=A4=B1=E8=B4=A5=EF=BC=8C=E4=BA=8B?= =?UTF-8?q?=E5=8A=A1=E5=9B=9E=E6=BB=9A=E7=9B=B8=E5=85=B3=20=20=20=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E4=BA=86=E5=8F=96=E6=B6=88=E8=BF=90=E5=8D=95=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=20=20=20=E6=B7=BB=E5=8A=A0=E8=B4=B9=E7=8E=87=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/controller/logistics.controller.ts | 16 ++- src/dto/freightcom.dto.ts | 3 + src/entity/shipment.entity.ts | 8 +- src/service/logistics.service.ts | 136 +++++++++++-------------- src/service/uni_express.service.ts | 16 +++ 5 files changed, 96 insertions(+), 83 deletions(-) diff --git a/src/controller/logistics.controller.ts b/src/controller/logistics.controller.ts index 85acf69..d2b46f5 100644 --- a/src/controller/logistics.controller.ts +++ b/src/controller/logistics.controller.ts @@ -162,6 +162,21 @@ export class LogisticsController { } } + @ApiOkResponse( + {type: BooleanRes} + ) + @Post('/getShipmentFee') + async getShipmentFee( + @Body() data: ShipmentBookDTO + ) { + try { + const fee = await this.logisticsService.getShipmentFee(data); + return successResponse(fee); + } catch (error) { + return errorResponse(error?.message || '创建失败'); + } + } + @ApiOkResponse( {type: BooleanRes} ) @@ -181,7 +196,6 @@ export class LogisticsController { return errorResponse(error?.message || '创建失败'); } } - @ApiOkResponse() @Post('/getPaymentMethods') diff --git a/src/dto/freightcom.dto.ts b/src/dto/freightcom.dto.ts index 81ee8cb..2bba475 100644 --- a/src/dto/freightcom.dto.ts +++ b/src/dto/freightcom.dto.ts @@ -219,6 +219,9 @@ export class PackagingEnvelope { // } export class ShippingDetailsDTO { + @ApiProperty() + shipmentFee: number; + @ApiProperty({ type: Location }) @Rule(RuleType.object()) origin: Location; diff --git a/src/entity/shipment.entity.ts b/src/entity/shipment.entity.ts index dcdbf5d..d106315 100644 --- a/src/entity/shipment.entity.ts +++ b/src/entity/shipment.entity.ts @@ -22,10 +22,6 @@ export class Shipment { id: string; @ApiProperty() - @Column({ name: 'order_id', nullable: true }) - @Expose() - orderId: string; - @OneToOne(() => Order) @JoinColumn({ name: 'order_id' }) order: Order; @@ -39,6 +35,10 @@ export class Shipment { @JoinColumn({ name: 'stock_point_id' }) stockPoint: StockPoint; + @Column({ nullable: false, default: 0}) + @Expose() + fee: number; + @ApiProperty() @Column({ nullable: true }) @Expose() diff --git a/src/service/logistics.service.ts b/src/service/logistics.service.ts index 9d77907..f69b264 100644 --- a/src/service/logistics.service.ts +++ b/src/service/logistics.service.ts @@ -204,6 +204,40 @@ export class LogisticsService { } } + async getShipmentFee(data: ShipmentBookDTO) { + 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, // todo,待确认 + 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', + } + const resShipmentFee = await this.uniExpressService.getRates(reqBody); + return resShipmentFee.data.totalAfterTax * 100; + } catch (e) { + throw e; + } + } + async createShipment(orderId: number, data: ShipmentBookDTO, userId: number) { const order = await this.orderModel.findOneBy({ id: orderId }); if (!order) { @@ -215,6 +249,8 @@ export class LogisticsService { ) { throw new Error('订单状态不正确 '); } + + let resShipmentOrder; try { const stock_point = await this.stockPointModel.findOneBy({ id: data.stockPointId}); const reqBody = { @@ -238,28 +274,24 @@ export class LogisticsService { 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}S`, // todo,换成KGS和LBS + weight_uom: data.details.packaging_properties.packages[0].measurements.weight.unit, currency: 'CAD', } - console.log('body', reqBody); - throw new Error('test '); - - // todo: 两个请求做异步 参考promise.all()方法 - // 获取预估费率 - const resShipmentFee = await this.uniExpressService.getRates(reqBody); // 添加运单 - const resShipmentOrder = await this.uniExpressService.createShipment(reqBody); + resShipmentOrder = await this.uniExpressService.createShipment(reqBody); // 记录物流信息,并将订单状态转到完成 if (resShipmentOrder.status === 'SUCCESS') { order.orderStatus = ErpOrderStatus.COMPLETED; + } else { + throw new Error('运单生成失败'); } const dataSource = this.dataSourceManager.getDataSource('default'); - dataSource.transaction(async manager => { + let transactionError = undefined; + await dataSource.transaction(async manager => { const orderRepo = manager.getRepository(Order); const shipmentRepo = manager.getRepository(Shipment); - if (order.orderStatus === ErpOrderStatus.COMPLETED) { const shipment = await shipmentRepo.save({ tracking_provider: 'uniuni-express', // todo: id未确定,后写进常数 @@ -267,90 +299,38 @@ export class LogisticsService { stockPointId: '1', // todo state: resShipmentOrder.data.uni_status_code, return_tracking_number: resShipmentOrder.data.tno, - order_id: order.id + fee: data.details.shipmentFee, + order_id: orderId }); order.shipmentId = shipment.id; - // 同步物流信息到woocommerce - const site = this.geSite(order.siteId); + const site = await this.geSite(order.siteId); await this.wpService.createShipment(site, order.externalOrderId, { - tracking_number: shipment.primary_tracking_number, - tracking_provider: shipment?.rate?.carrier_name, + tracking_number: shipment.return_tracking_number, + tracking_provider: shipment?.tracking_provider, }); } await orderRepo.save(order); + }).catch(error => { + transactionError = error }); + if (transactionError !== undefined) { + console.log('err', transactionError); + throw transactionError; + } + return { data: { - resShipmentFee, resShipmentOrder } }; } catch(error) { - throw new Error(`上游请求错误:${error}`); + if (resShipmentOrder.status === 'SUCCESS') { + await this.uniExpressService.deleteShipment(resShipmentOrder.data.tno); + } + throw new Error(`上游请求错误:${error}`); } - - // const dataSource = this.dataSourceManager.getDataSource('default'); - // return dataSource.transaction(async manager => { - // const productRepo = manager.getRepository(Product); - // const shipmentRepo = manager.getRepository(Shipment); - // const shipmentItemRepo = manager.getRepository(ShipmentItem); - // const orderShipmentRepo = manager.getRepository(OrderShipment); - // const stockRecordRepo = manager.getRepository(StockRecord); - // const stockRepo = manager.getRepository(Stock); - // const orderRepo = manager.getRepository(Order); - - // await shipmentRepo.save(shipment); - // await this.getShipment(shipment.id); - // const shipmentItems = []; - // for (const item of data?.sales) { - // const product = await productRepo.findOne({ where: { sku: item.sku } }); - // shipmentItems.push({ - // shipment_id: shipment.id, - // productId: product.id, - // name: product.name, - // sku: item.sku, - // quantity: item.quantity, - // }); - // const stock = await stockRepo.findOne({ - // where: { - // stockPointId: data.stockPointId, - // productSku: item.sku, - // }, - // }); - // stock.quantity -= item.quantity; - // await stockRepo.save(stock); - // await stockRecordRepo.save({ - // stockPointId: data.stockPointId, - // productSku: item.sku, - // operationType: StockRecordOperationType.OUT, - // quantityChange: item.quantity, - // operatorId: userId, - // note: `订单${[orderId, ...data.orderIds].join(',')} 发货`, - // }); - // } - // await shipmentItemRepo.save(shipmentItems); - // await orderShipmentRepo.save({ - // order_id: orderId, - // shipment_id: shipment.id, - // stockPointId: data.stockPointId, - // }); - // for (const orderId of data?.orderIds) { - // await orderShipmentRepo.save({ - // order_id: orderId, - // shipment_id: shipment.id, - // stockPointId: data.stockPointId, - // }); - // const order = await orderRepo.findOneBy({ id: orderId }); - // order.orderStatus = ErpOrderStatus.COMPLETED; - // order.status = OrderStatus.COMPLETED; - // await orderRepo.save(order); - // } - // order.orderStatus = ErpOrderStatus.COMPLETED; - // order.status = OrderStatus.COMPLETED; - // await orderRepo.save(order); - // }); } async syncShipment() { diff --git a/src/service/uni_express.service.ts b/src/service/uni_express.service.ts index eb8d8be..fe78e0a 100644 --- a/src/service/uni_express.service.ts +++ b/src/service/uni_express.service.ts @@ -84,6 +84,22 @@ export class UniExpressService { } } + async deleteShipment(tno: string) { + const body = { + tno + }; + const token = await this.getToken(); + const config: AxiosRequestConfig= { + method: 'POST', + headers: { + 'Authorization': `Bearer ${token}` + }, + url: `${this.url}/orders/cancelorder`, + data: body + }; + return await axios.request(config); + } + async getLabel(tracking_number: string) { const body = { packageId: tracking_number -- 2.40.1