Feature: 增加换货功能

This commit is contained in:
黄珑 2025-08-21 15:34:22 +08:00
parent 9c54d60d91
commit 64d01d2870
6 changed files with 169 additions and 26 deletions

View File

@ -16,6 +16,7 @@ import { OrderFee } from '../entity/order_fee.entity';
import { OrderRefund } from '../entity/order_refund.entity';
import { OrderRefundItem } from '../entity/order_retund_item.entity';
import { OrderSale } from '../entity/order_sale.entity';
import { OrderSaleOriginal } from '../entity/order_item_original.entity';
import { OrderShipping } from '../entity/order_shipping.entity';
import { Service } from '../entity/service.entity';
import { ShippingAddress } from '../entity/shipping_address.entity';
@ -57,6 +58,7 @@ export default {
OrderRefund,
OrderRefundItem,
OrderSale,
OrderSaleOriginal,
OrderShipment,
ShipmentItem,
Shipment,

View File

@ -108,6 +108,22 @@ export class OrderController {
}
}
@ApiOkResponse({
type: BooleanRes,
})
@Post('/updateOrderItems/:orderId')
async updateOrderItems(
@Param('orderId') orderId: number,
@Body() data: any
) {
try {
const res = await this.orderService.updateOrderSales(orderId, data);
return successResponse(res);
} catch (error) {
return errorResponse(error?.message || '更新失败');
}
}
@ApiOkResponse({
type: BooleanRes,
})

View File

@ -0,0 +1,78 @@
import { ApiProperty } from '@midwayjs/swagger';
import { Exclude, Expose } from 'class-transformer';
import {
Column,
CreateDateColumn,
Entity,
JoinColumn,
ManyToOne,
PrimaryGeneratedColumn,
UpdateDateColumn,
} from 'typeorm';
import { Order } from './order.entity';
@Entity('order_sale_original')
@Exclude()
export class OrderSaleOriginal {
@ApiProperty()
@PrimaryGeneratedColumn()
@Expose()
id?: number;
@ApiProperty()
@ManyToOne(() => Order)
@JoinColumn({ name: 'order_id' })
@Expose()
orderId: number; // 订单 ID
@ApiProperty()
@Column()
@Expose()
siteId: string; // 来源站点唯一标识
@ApiProperty()
@Column()
@Expose()
externalOrderItemId: string; // WooCommerce 订单item ID
@ApiProperty()
@Column()
@Expose()
productId: number;
@ApiProperty()
@Column()
@Expose()
name: string;
@ApiProperty({ description: 'sku', type: 'string' })
@Expose()
@Column()
sku: string;
@ApiProperty()
@Column()
@Expose()
quantity: number;
@ApiProperty()
@Column({ default: false })
@Expose()
isPackage: boolean;
@ApiProperty({
example: '2022-12-12 11:11:11',
description: '创建时间',
})
@CreateDateColumn()
@Expose()
createdAt?: Date;
@ApiProperty({
example: '2022-12-12 11:11:11',
description: '更新时间',
})
@UpdateDateColumn()
@Expose()
updatedAt?: Date;
}

View File

@ -27,7 +27,7 @@ export class OrderSale {
siteId: string; // 来源站点唯一标识
@ApiProperty()
@Column()
@Column({ nullable: true })
@Expose()
externalOrderItemId: string; // WooCommerce 订单item ID

View File

@ -29,6 +29,7 @@ import { OrderItem } from '../entity/order_item.entity';
import { OrderSale } from '../entity/order_sale.entity';
import { UniExpressService } from './uni_express.service';
import { StockPoint } from '../entity/stock_point.entity';
import { OrderService } from './order.service';
@Provide()
export class LogisticsService {
@ -74,6 +75,9 @@ export class LogisticsService {
@Inject()
wpService: WPService;
@Inject()
orderService: OrderService;
@Inject()
dataSourceManager: TypeORMDataSourceManager;
@ -124,7 +128,6 @@ export class LogisticsService {
async updateShipmentState(shipment: Shipment) {
try {
const data = await this.uniExpressService.getOrderStatus(shipment.return_tracking_number);
// console.log('res', data, data.data[0].state);
shipment.state = data.data[0].state;
if (shipment.state in [203, 215, 216, 230]) { // todo,写常数
shipment.finished = true;
@ -240,7 +243,6 @@ export class LogisticsService {
order.shipmentId = null;
orderRepo.save(order);
await manager.delete('shipment_item', { shipment_id: shipmentId });
shipmentRepo.remove(shipment);
const res = await this.uniExpressService.deleteShipment(shipment.return_tracking_number);
@ -293,7 +295,7 @@ export class LogisticsService {
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待确认
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,
@ -317,6 +319,7 @@ export class LogisticsService {
async createShipment(orderId: number, data: ShipmentBookDTO, userId: number) {
const order = await this.orderModel.findOneBy({ id: orderId });
const { sales } = data;
if (!order) {
throw new Error('订单不存在');
}
@ -339,7 +342,7 @@ export class LogisticsService {
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待确认
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,
@ -373,7 +376,6 @@ export class LogisticsService {
await dataSource.transaction(async manager => {
const orderRepo = manager.getRepository(Order);
const shipmentRepo = manager.getRepository(Shipment);
const shipmentItemRepo = manager.getRepository(ShipmentItem);
const tracking_provider = 'UniUni'; // todo: id未确定后写进常数
// 同步物流信息到woocommerce
@ -396,17 +398,6 @@ export class LogisticsService {
});
order.shipmentId = shipment.id;
shipmentId = shipment.id;
// onchange shipment
await data.sales.forEach(async (item) => {
console.log('item', item)
const shipmentItem: ShipmentItem = new ShipmentItem;
shipmentItem.sku = item.sku;
shipmentItem.quantity = item.quantity;
shipmentItem.shipment_id = shipmentId;
shipmentItem.order_id = orderId;
await shipmentItemRepo.save(shipmentItem);
});
}
// 同步订单状态到woocommerce
@ -428,6 +419,9 @@ export class LogisticsService {
throw transactionError;
}
// 更新产品发货信息
this.orderService.updateOrderSales(order.id, sales);
return { data: {
shipmentId
} };
@ -439,11 +433,6 @@ export class LogisticsService {
}
}
async updateShipmentItem(shipmentId: number, sales: OrderSale[]) {
const shipment:Shipment = await this.shipmentModel.findOneBy({ id: shipmentId });
console.log(shipment);
}
async syncShipment() {
try {
const shipments = await this.shipmentModel.find({

View File

@ -29,6 +29,7 @@ import { WpSite } from '../interface';
import { ShipmentItem } from '../entity/shipment_item.entity';
import { UpdateStockDTO } from '../dto/stock.dto';
import { StockService } from './stock.service';
import { OrderSaleOriginal } from '../entity/order_item_original.entity';
@Provide()
export class OrderService {
@ -50,6 +51,9 @@ export class OrderService {
@InjectEntityModel(OrderSale)
orderSaleModel: Repository<OrderSale>;
@InjectEntityModel(OrderSaleOriginal)
orderSaleOriginalModel: Repository<OrderSaleOriginal>;
@InjectEntityModel(WpProduct)
wpProductModel: Repository<WpProduct>;
@ -214,12 +218,10 @@ export class OrderService {
entity.id = existingOrder.id;
return entity;
}
console.log('/////////////');
entity.orderStatus = this.mapOrderStatus(entity.status);
const customer = await this.customerModel.findOne({
where: { email: order.customer_email },
});
console.log('error? ', this.customerModel);
if(!customer) {
await this.customerModel.save({
email: order.customer_email,
@ -1182,6 +1184,21 @@ export class OrderService {
}
}
// update order_sale_origin if not exist
try {
const order_sale_origin_count = await this.orderSaleOriginalModel.countBy({ orderId: id });
if (order_sale_origin_count === 0) {
sales.forEach(async sale => {
const { id: saleId, ...saleData } = sale;
await this.orderSaleOriginalModel.save(saleData);
});
}
} catch (error) {
console.log('create order sale origin error: ', error.message);
}
return {
...order,
siteName: site.siteName,
@ -1297,6 +1314,7 @@ export class OrderService {
return dataSource.transaction(async manager => {
const orderRepo = manager.getRepository(Order);
const orderSaleRepo = manager.getRepository(OrderSale);
const OrderSaleOriginalRepo = manager.getRepository(OrderSaleOriginal);
const productRepo = manager.getRepository(Product);
const order = await orderRepo.save({
siteId: '-1',
@ -1314,7 +1332,7 @@ export class OrderService {
});
for (const sale of sales) {
const product = await productRepo.findOne({ where: { sku: sale.sku } });
await orderSaleRepo.save({
const saleItem = {
orderId: order.id,
siteId: '-1',
externalOrderItemId: '-1',
@ -1322,7 +1340,9 @@ export class OrderService {
name: product.name,
sku: sale.sku,
quantity: sale.quantity,
});
};
await orderSaleRepo.save(saleItem);
await OrderSaleOriginalRepo.save(saleItem);
}
});
}
@ -1363,4 +1383,42 @@ export class OrderService {
pageSize,
};
}
async updateOrderSales(orderId: number, sales: OrderSale[]) {
try {
const dataSource = this.dataSourceManager.getDataSource('default');
let transactionError = undefined;
await dataSource.transaction(async manager => {
const orderRepo = manager.getRepository(Order);
const orderSaleRepo = manager.getRepository(OrderSale);
const productRepo = manager.getRepository(Product);
const order = await orderRepo.findOneBy({ id: orderId });
let product:Product;
await orderSaleRepo.delete({ orderId });
for (const sale of sales) {
product = await productRepo.findOneBy({ sku: sale.sku });
await orderSaleRepo.save({
orderId,
siteId: order.siteId,
productId: product.id,
name: product.name,
sku: sale.sku,
quantity: sale.quantity
});
};
}).catch(error => {
transactionError = error;
});
if (transactionError !== undefined) {
throw new Error(`更新物流信息错误:${transactionError.message}`);
}
return true;
} catch (error) {
throw new Error(`更新发货产品失败:${error.message}`);
}
}
}