refactor(order): 重构订单相关实体和服务逻辑 #48

Merged
longbot merged 1 commits from zksu/API:main into main 2026-01-12 07:23:25 +00:00
4 changed files with 78 additions and 87 deletions

View File

@ -227,7 +227,7 @@ export class ShopyyAdapter implements ISiteAdapter {
// ========== 订单映射方法 ========== // ========== 订单映射方法 ==========
mapPlatformToUnifiedOrder(item: ShopyyOrder): UnifiedOrderDTO { mapPlatformToUnifiedOrder(item: ShopyyOrder): UnifiedOrderDTO {
console.log(item) // console.log(item)
if(!item) throw new Error('订单数据不能为空') if(!item) throw new Error('订单数据不能为空')
// 提取账单和送货地址 如果不存在则为空对象 // 提取账单和送货地址 如果不存在则为空对象
const billing = (item).bill_address || {}; const billing = (item).bill_address || {};
@ -315,7 +315,7 @@ export class ShopyyAdapter implements ISiteAdapter {
product_id: p.product_id, product_id: p.product_id,
quantity: p.quantity, quantity: p.quantity,
total: String(p.price ?? ''), total: String(p.price ?? ''),
sku: p.sku || p.sku_code || '', sku: p.sku_code || '',
price: String(p.price ?? ''), price: String(p.price ?? ''),
}) })
); );

View File

@ -22,22 +22,22 @@ export class OrderSale {
@Expose() @Expose()
id?: number; id?: number;
@ApiProperty() @ApiProperty({ name:'原始订单ID' })
@Column() @Column()
@Expose() @Expose()
orderId: number; // 订单 ID orderId: number; // 订单 ID
@ApiProperty() @ApiProperty({ name:'站点' })
@Column({ nullable: true }) @Column()
@Expose() @Expose()
siteId: number; // 来源站点唯一标识 siteId: number; // 来源站点唯一标识
@ApiProperty() @ApiProperty({name: "原始订单 itemId"})
@Column({ nullable: true }) @Column({ nullable: true })
@Expose() @Expose()
externalOrderItemId: string; // WooCommerce 订单item ID externalOrderItemId: string; // WooCommerce 订单item ID
@ApiProperty() @ApiProperty({name: "产品 ID"})
@Column() @Column()
@Expose() @Expose()
productId: number; productId: number;
@ -62,25 +62,35 @@ export class OrderSale {
@Expose() @Expose()
isPackage: boolean; isPackage: boolean;
@ApiProperty() @ApiProperty({ description: '品牌', type: 'string',nullable: true})
@Column({ default: false })
@Expose() @Expose()
isYoone: boolean; @Column({ nullable: true })
brand?: string;
@ApiProperty() @ApiProperty({ description: '口味', type: 'string', nullable: true })
@Column({ default: false })
@Expose() @Expose()
isZex: boolean; @Column({ nullable: true })
flavor?: string;
@ApiProperty({ nullable: true }) @ApiProperty({ description: '湿度', type: 'string', nullable: true })
@Column({ type: 'int', nullable: true })
@Expose() @Expose()
size: number | null; // 其实是 strength @Column({ nullable: true })
humidity?: string;
@ApiProperty() @ApiProperty({ description: '尺寸', type: 'string', nullable: true })
@Column({ default: false })
@Expose() @Expose()
isYooneNew: boolean; @Column({ nullable: true })
size?: string;
@ApiProperty({name: '强度', nullable: true })
@Column({ nullable: true })
@Expose()
strength: string | null;
@ApiProperty({ description: '版本', type: 'string', nullable: true })
@Expose()
@Column({ nullable: true })
version?: string;
@ApiProperty({ @ApiProperty({
example: '2022-12-12 11:11:11', example: '2022-12-12 11:11:11',
@ -97,25 +107,4 @@ export class OrderSale {
@UpdateDateColumn() @UpdateDateColumn()
@Expose() @Expose()
updatedAt?: Date; updatedAt?: Date;
// // === 自动计算逻辑 ===
// @BeforeInsert()
// @BeforeUpdate()
// setFlags() {
// if (!this.name) return;
// const lower = this.name.toLowerCase();
// this.isYoone = lower.includes('yoone');
// this.isZex = lower.includes('zex');
// this.isYooneNew = this.isYoone && lower.includes('new');
// let size: number | null = null;
// const sizes = [3, 6, 9, 12, 15, 18];
// for (const s of sizes) {
// if (lower.includes(s.toString())) {
// size = s;
// break;
// }
// }
// this.size = size;
// }
} }

View File

@ -714,7 +714,7 @@ export class OrderService {
// 从数据库查询产品,关联查询组件 // 从数据库查询产品,关联查询组件
const product = await this.productModel.findOne({ const product = await this.productModel.findOne({
where: { siteSkus: Like(`%${orderItem.sku}%`) }, where: { siteSkus: Like(`%${orderItem.sku}%`) },
relations: ['components'], relations: ['components','attributes','attributes.dict'],
}); });
if (!product) return; if (!product) return;
@ -722,7 +722,7 @@ export class OrderService {
return { return {
product: await this.productModel.findOne({ product: await this.productModel.findOne({
where: { sku: comp.sku }, where: { sku: comp.sku },
relations: ['components', 'attributes'], relations: ['components', 'attributes','attributes.dict'],
}), }),
quantity: comp.quantity * orderItem.quantity, quantity: comp.quantity * orderItem.quantity,
} }
@ -739,26 +739,28 @@ export class OrderService {
name: componentDetail.product.name, name: componentDetail.product.name,
quantity: componentDetail.quantity * orderItem.quantity, quantity: componentDetail.quantity * orderItem.quantity,
sku: componentDetail.product.sku, sku: componentDetail.product.sku,
// 理论上直接存 product 的全部数据才是对的,因为这样我的数据才全面。
isPackage: componentDetail.product.type === 'bundle', isPackage: componentDetail.product.type === 'bundle',
isYoone: attrsObj?.['brand']?.name === 'yoone', isYoone: attrsObj?.['brand']?.name === 'yoone',
isZyn: attrsObj?.['brand']?.name === 'zyn', isZyn: attrsObj?.['brand']?.name === 'zyn',
isZex: attrsObj?.['brand']?.name === 'zex', isZex: attrsObj?.['brand']?.name === 'zex',
isYooneNew: attrsObj?.['brand']?.name === 'yoone' && attrsObj?.['version']?.name === 'new', isYooneNew: attrsObj?.['brand']?.name === 'yoone' && attrsObj?.['version']?.name === 'new',
size: this.extractNumberFromString(attrsObj?.['strength']?.name) || null, strength: attrsObj?.['strength']?.name,
}); });
return orderSale return orderSale
}).filter(v => v !== null) }).filter(v => v !== null)
console.log("orderSales",orderSales)
if (orderSales.length > 0) { if (orderSales.length > 0) {
await this.orderSaleModel.save(orderSales); await this.orderSaleModel.save(orderSales);
} }
} }
extractNumberFromString(str: string): number { // // extract stren
if (!str) return 0; // extractNumberFromString(str: string): number {
// if (!str) return 0;
const num = parseInt(str, 10); // const num = parseInt(str, 10);
return isNaN(num) ? 0 : num; // return isNaN(num) ? 0 : num;
} // }
/** /**
* 退 * 退
@ -1572,14 +1574,14 @@ export class OrderService {
`; `;
let yooneSql = ` let yooneSql = `
SELECT SELECT
SUM(CASE WHEN os.isYoone = 1 AND os.size = 3 THEN os.quantity ELSE 0 END) AS yoone3Quantity, SUM(CASE WHEN os.brand = 'yoone' AND os.strength = '3mg' THEN os.quantity ELSE 0 END) AS yoone3Quantity,
SUM(CASE WHEN os.isYoone = 1 AND os.size = 6 THEN os.quantity ELSE 0 END) AS yoone6Quantity, SUM(CASE WHEN os.brand = 'yoone' AND os.strength = '6mg' THEN os.quantity ELSE 0 END) AS yoone6Quantity,
SUM(CASE WHEN os.isYoone = 1 AND os.size = 9 THEN os.quantity ELSE 0 END) AS yoone9Quantity, SUM(CASE WHEN os.brand = 'yoone' AND os.strength = '9mg' THEN os.quantity ELSE 0 END) AS yoone9Quantity,
SUM(CASE WHEN os.isYoone = 1 AND os.size = 12 THEN os.quantity ELSE 0 END) AS yoone12Quantity, SUM(CASE WHEN os.brand = 'yoone' AND os.strength = '12mg' THEN os.quantity ELSE 0 END) AS yoone12Quantity,
SUM(CASE WHEN os.isYooneNew = 1 AND os.size = 12 THEN os.quantity ELSE 0 END) AS yoone12QuantityNew, SUM(CASE WHEN os.brand = 'yoone' AND os.strength = '12mg' THEN os.quantity ELSE 0 END) AS yoone12QuantityNew,
SUM(CASE WHEN os.isYoone = 1 AND os.size = 15 THEN os.quantity ELSE 0 END) AS yoone15Quantity, SUM(CASE WHEN os.brand = 'yoone' AND os.strength = '15mg' THEN os.quantity ELSE 0 END) AS yoone15Quantity,
SUM(CASE WHEN os.isYoone = 1 AND os.size = 18 THEN os.quantity ELSE 0 END) AS yoone18Quantity, SUM(CASE WHEN os.brand = 'yoone' AND os.strength = '18mg' THEN os.quantity ELSE 0 END) AS yoone18Quantity,
SUM(CASE WHEN os.isZex = 1 THEN os.quantity ELSE 0 END) AS zexQuantity SUM(CASE WHEN os.brand = 'zex' THEN os.quantity ELSE 0 END) AS zexQuantity
FROM order_sale os FROM order_sale os
INNER JOIN \`order\` o ON o.id = os.orderId INNER JOIN \`order\` o ON o.id = os.orderId
WHERE o.date_paid BETWEEN ? AND ? WHERE o.date_paid BETWEEN ? AND ?

View File

@ -73,16 +73,16 @@ export class StatisticsService {
order_sales_summary AS ( order_sales_summary AS (
SELECT SELECT
orderId, orderId,
SUM(CASE WHEN name LIKE '%zyn%' THEN quantity ELSE 0 END) AS zyn_quantity, SUM(CASE WHEN brand = 'zyn' THEN quantity ELSE 0 END) AS zyn_quantity,
SUM(CASE WHEN name LIKE '%yoone%' THEN quantity ELSE 0 END) AS yoone_quantity, SUM(CASE WHEN brand = 'yoone' THEN quantity ELSE 0 END) AS yoone_quantity,
SUM(CASE WHEN name LIKE '%zex%' THEN quantity ELSE 0 END) AS zex_quantity, SUM(CASE WHEN brand = 'zex' THEN quantity ELSE 0 END) AS zex_quantity,
SUM(CASE WHEN name LIKE '%yoone%' AND isPackage = 1 THEN quantity ELSE 0 END) AS yoone_G_quantity, SUM(CASE WHEN brand = 'yoone' AND isPackage = 1 THEN quantity ELSE 0 END) AS yoone_G_quantity,
SUM(CASE WHEN name LIKE '%yoone%' AND isPackage = 0 THEN quantity ELSE 0 END) AS yoone_S_quantity, SUM(CASE WHEN brand = 'yoone' AND isPackage = 0 THEN quantity ELSE 0 END) AS yoone_S_quantity,
SUM(CASE WHEN name LIKE '%yoone%' AND name LIKE '%3%' THEN quantity ELSE 0 END) AS yoone_3_quantity, SUM(CASE WHEN brand = 'yoone' AND strength = '3mg' THEN quantity ELSE 0 END) AS yoone_3_quantity,
SUM(CASE WHEN name LIKE '%yoone%' AND name LIKE '%6%' THEN quantity ELSE 0 END) AS yoone_6_quantity, SUM(CASE WHEN brand = 'yoone' AND strength = '6mg' THEN quantity ELSE 0 END) AS yoone_6_quantity,
SUM(CASE WHEN name LIKE '%yoone%' AND name LIKE '%9%' THEN quantity ELSE 0 END) AS yoone_9_quantity, SUM(CASE WHEN brand = 'yoone' AND strength = '9mg' THEN quantity ELSE 0 END) AS yoone_9_quantity,
SUM(CASE WHEN name LIKE '%yoone%' AND name LIKE '%12%' THEN quantity ELSE 0 END) AS yoone_12_quantity, SUM(CASE WHEN brand = 'yoone' AND strength = '12mg' THEN quantity ELSE 0 END) AS yoone_12_quantity,
SUM(CASE WHEN name LIKE '%yoone%' AND name LIKE '%15%' THEN quantity ELSE 0 END) AS yoone_15_quantity SUM(CASE WHEN brand = 'yoone' AND strength = '15mg' THEN quantity ELSE 0 END) AS yoone_15_quantity
FROM order_sale FROM order_sale
GROUP BY orderId GROUP BY orderId
), ),
@ -269,16 +269,16 @@ export class StatisticsService {
order_sales_summary AS ( order_sales_summary AS (
SELECT SELECT
orderId, orderId,
SUM(CASE WHEN name LIKE '%zyn%' THEN quantity ELSE 0 END) AS zyn_quantity, SUM(CASE WHEN brand = 'zyn' THEN quantity ELSE 0 END) AS zyn_quantity,
SUM(CASE WHEN name LIKE '%yoone%' THEN quantity ELSE 0 END) AS yoone_quantity, SUM(CASE WHEN brand = 'yoone' THEN quantity ELSE 0 END) AS yoone_quantity,
SUM(CASE WHEN name LIKE '%zex%' THEN quantity ELSE 0 END) AS zex_quantity, SUM(CASE WHEN brand = 'zex' THEN quantity ELSE 0 END) AS zex_quantity,
SUM(CASE WHEN name LIKE '%yoone%' AND isPackage = 1 THEN quantity ELSE 0 END) AS yoone_G_quantity, SUM(CASE WHEN brand = 'yoone' AND isPackage = 1 THEN quantity ELSE 0 END) AS yoone_G_quantity,
SUM(CASE WHEN name LIKE '%yoone%' AND isPackage = 0 THEN quantity ELSE 0 END) AS yoone_S_quantity, SUM(CASE WHEN brand = 'yoone' AND isPackage = 0 THEN quantity ELSE 0 END) AS yoone_S_quantity,
SUM(CASE WHEN name LIKE '%yoone%' AND name LIKE '%3%' THEN quantity ELSE 0 END) AS yoone_3_quantity, SUM(CASE WHEN brand = 'yoone' AND strength = '3mg' THEN quantity ELSE 0 END) AS yoone_3_quantity,
SUM(CASE WHEN name LIKE '%yoone%' AND name LIKE '%6%' THEN quantity ELSE 0 END) AS yoone_6_quantity, SUM(CASE WHEN brand = 'yoone' AND strength = '6mg' THEN quantity ELSE 0 END) AS yoone_6_quantity,
SUM(CASE WHEN name LIKE '%yoone%' AND name LIKE '%9%' THEN quantity ELSE 0 END) AS yoone_9_quantity, SUM(CASE WHEN brand = 'yoone' AND strength = '9mg' THEN quantity ELSE 0 END) AS yoone_9_quantity,
SUM(CASE WHEN name LIKE '%yoone%' AND name LIKE '%12%' THEN quantity ELSE 0 END) AS yoone_12_quantity, SUM(CASE WHEN brand = 'yoone' AND strength = '12mg' THEN quantity ELSE 0 END) AS yoone_12_quantity,
SUM(CASE WHEN name LIKE '%yoone%' AND name LIKE '%15%' THEN quantity ELSE 0 END) AS yoone_15_quantity SUM(CASE WHEN brand = 'yoone' AND strength = '15mg' THEN quantity ELSE 0 END) AS yoone_15_quantity
FROM order_sale FROM order_sale
GROUP BY orderId GROUP BY orderId
), ),
@ -466,16 +466,16 @@ export class StatisticsService {
order_sales_summary AS ( order_sales_summary AS (
SELECT SELECT
orderId, orderId,
SUM(CASE WHEN name LIKE '%zyn%' THEN quantity ELSE 0 END) AS zyn_quantity, SUM(CASE WHEN brand = 'zyn' THEN quantity ELSE 0 END) AS zyn_quantity,
SUM(CASE WHEN name LIKE '%yoone%' THEN quantity ELSE 0 END) AS yoone_quantity, SUM(CASE WHEN brand = 'yoone' THEN quantity ELSE 0 END) AS yoone_quantity,
SUM(CASE WHEN name LIKE '%zex%' THEN quantity ELSE 0 END) AS zex_quantity, SUM(CASE WHEN brand = 'zex' THEN quantity ELSE 0 END) AS zex_quantity,
SUM(CASE WHEN name LIKE '%yoone%' AND isPackage = 1 THEN quantity ELSE 0 END) AS yoone_G_quantity, SUM(CASE WHEN brand = 'yoone' AND isPackage = 1 THEN quantity ELSE 0 END) AS yoone_G_quantity,
SUM(CASE WHEN name LIKE '%yoone%' AND isPackage = 0 THEN quantity ELSE 0 END) AS yoone_S_quantity, SUM(CASE WHEN brand = 'yoone' AND isPackage = 0 THEN quantity ELSE 0 END) AS yoone_S_quantity,
SUM(CASE WHEN name LIKE '%yoone%' AND name LIKE '%3%' THEN quantity ELSE 0 END) AS yoone_3_quantity, SUM(CASE WHEN brand = 'yoone' AND strength = '3mg' THEN quantity ELSE 0 END) AS yoone_3_quantity,
SUM(CASE WHEN name LIKE '%yoone%' AND name LIKE '%6%' THEN quantity ELSE 0 END) AS yoone_6_quantity, SUM(CASE WHEN brand = 'yoone' AND strength = '6mg' THEN quantity ELSE 0 END) AS yoone_6_quantity,
SUM(CASE WHEN name LIKE '%yoone%' AND name LIKE '%9%' THEN quantity ELSE 0 END) AS yoone_9_quantity, SUM(CASE WHEN brand = 'yoone' AND strength = '9mg' THEN quantity ELSE 0 END) AS yoone_9_quantity,
SUM(CASE WHEN name LIKE '%yoone%' AND name LIKE '%12%' THEN quantity ELSE 0 END) AS yoone_12_quantity, SUM(CASE WHEN brand = 'yoone' AND strength = '12mg' THEN quantity ELSE 0 END) AS yoone_12_quantity,
SUM(CASE WHEN name LIKE '%yoone%' AND name LIKE '%15%' THEN quantity ELSE 0 END) AS yoone_15_quantity SUM(CASE WHEN brand = 'yoone' AND strength = '15mg' THEN quantity ELSE 0 END) AS yoone_15_quantity
FROM order_sale FROM order_sale
GROUP BY orderId GROUP BY orderId
), ),