Compare commits
7 Commits
792ec5aaf0
...
f4a46bcf72
| Author | SHA1 | Date |
|---|---|---|
|
|
f4a46bcf72 | |
|
|
534cc3f2c7 | |
|
|
d8a3422015 | |
|
|
9d69af03b2 | |
|
|
1657b96694 | |
|
|
0a14a7c1ae | |
|
|
51b59ca176 |
|
|
@ -23,6 +23,10 @@ export class ShipmentBookDTO {
|
|||
@ApiProperty()
|
||||
@Rule(RuleType.string())
|
||||
shipmentPlatform: string;
|
||||
|
||||
@ApiProperty()
|
||||
@Rule(RuleType.string())
|
||||
courierCompany: string;
|
||||
}
|
||||
|
||||
export class ShipmentFeeBookDTO {
|
||||
|
|
@ -30,6 +34,8 @@ export class ShipmentFeeBookDTO {
|
|||
@ApiProperty()
|
||||
shipmentPlatform: string;
|
||||
@ApiProperty()
|
||||
courierCompany: string;
|
||||
@ApiProperty()
|
||||
stockPointId: number;
|
||||
@ApiProperty()
|
||||
sender: string;
|
||||
|
|
|
|||
|
|
@ -247,6 +247,9 @@ export class FreightwavesService {
|
|||
};
|
||||
|
||||
const response = await this.sendRequest<RateTryResponseData>('/shipService/order/rateTry', requestData);
|
||||
if (response.code !== '00000200') {
|
||||
throw new Error(response.msg);
|
||||
}
|
||||
return response.data;
|
||||
}
|
||||
|
||||
|
|
@ -262,7 +265,10 @@ export class FreightwavesService {
|
|||
};
|
||||
|
||||
const response = await this.sendRequest<CreateOrderResponseData>('/shipService/order/createOrder', requestData);
|
||||
return response;
|
||||
if (response.code !== '00000200') {
|
||||
throw new Error(response.msg);
|
||||
}
|
||||
return response.data;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -295,6 +301,9 @@ export class FreightwavesService {
|
|||
};
|
||||
|
||||
const response = await this.sendRequest<ModifyOrderResponseData>('/shipService/order/modifyOrder', requestData);
|
||||
if (response.code !== '00000200') {
|
||||
throw new Error(response.msg);
|
||||
}
|
||||
return response.data;
|
||||
}
|
||||
|
||||
|
|
@ -309,6 +318,9 @@ export class FreightwavesService {
|
|||
partner: this.config.partner,
|
||||
};
|
||||
const response = await this.sendRequest<RefundOrderResponseData>('/shipService/order/refundOrder', requestData);
|
||||
if (response.code !== '00000200') {
|
||||
throw new Error(response.msg);
|
||||
}
|
||||
return response.data;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -464,7 +464,7 @@ export class LogisticsService {
|
|||
}
|
||||
};
|
||||
} catch (error) {
|
||||
if (resShipmentOrder.status === 'SUCCESS') {
|
||||
if (resShipmentOrder?.status === 'SUCCESS') {
|
||||
await this.uniExpressService.deleteShipment(resShipmentOrder.data.tno);
|
||||
}
|
||||
throw new Error(`上游请求错误:${error}`);
|
||||
|
|
@ -733,8 +733,9 @@ export class LogisticsService {
|
|||
if (data.shipmentPlatform === 'freightwaves') {
|
||||
// 根据TMS系统对接说明文档格式化参数
|
||||
const reqBody: any = {
|
||||
shipCompany: 'UPSYYZ7000NEW',
|
||||
partnerOrderNumber: order.siteId + '-' + order.externalOrderId,
|
||||
// shipCompany: 'UPSYYZ7000NEW',
|
||||
shipCompany: data.courierCompany || "",
|
||||
partnerOrderNumber: order.siteId + '-1-' + order.externalOrderId,
|
||||
warehouseId: '25072621030107400060',
|
||||
shipper: {
|
||||
name: data.details.origin.contact_name, // 姓名
|
||||
|
|
@ -798,15 +799,20 @@ export class LogisticsService {
|
|||
};
|
||||
|
||||
resShipmentOrder = await this.freightwavesService.createOrder(reqBody); // 创建订单
|
||||
|
||||
//tms只返回了物流订单号,需要查询一次来获取完整的物流信息
|
||||
const queryRes = await this.freightwavesService.queryOrder({ shipOrderId: resShipmentOrder.shipOrderId }); // 查询订单
|
||||
resShipmentOrder.push(queryRes);
|
||||
return {
|
||||
...resShipmentOrder,
|
||||
...queryRes
|
||||
}
|
||||
}
|
||||
|
||||
return resShipmentOrder;
|
||||
} catch (error) {
|
||||
console.log('物流订单处理失败:', error); // 使用console.log代替this.log
|
||||
throw error;
|
||||
// 处理错误,例如记录日志或抛出异常
|
||||
throw new Error(`物流订单处理失败: ${error}`);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -826,7 +832,8 @@ export class LogisticsService {
|
|||
const address = shipments?.address;
|
||||
// 转换为RateTryRequest格式
|
||||
const r = {
|
||||
shipCompany: 'UPSYYZ7000NEW', // 必填,但ShipmentFeeBookDTO中缺少
|
||||
//shipCompany: 'UPSYYZ7000NEW', // 必填,但ShipmentFeeBookDTO中缺少
|
||||
shipCompany: data.courierCompany || "",
|
||||
partnerOrderNumber: `order-${Date.now()}`, // 必填,使用时间戳生成
|
||||
warehouseId: '25072621030107400060', // 可选,使用stockPointId转换
|
||||
shipper: {
|
||||
|
|
|
|||
|
|
@ -733,19 +733,20 @@ export class OrderService {
|
|||
if (!orderItem.sku) return;
|
||||
|
||||
// 从数据库查询产品,关联查询组件
|
||||
const componentDetails = await this.productService.getComponentDetailFromSiteSku({ sku: orderItem.sku, name: orderItem.name },orderItem.quantity,site);
|
||||
const componentDetails = await this.productService.getComponentDetailFromSiteSku({ sku: orderItem.sku, name: orderItem.name }, site);
|
||||
if(!componentDetails?.length){
|
||||
return
|
||||
}
|
||||
|
||||
const orderSales: OrderSale[] = componentDetails.map(({product, parentProduct, quantity}) => {
|
||||
if (!product) return null
|
||||
console.log('product',product)
|
||||
const attrsObj = this.productService.getAttributesObject(product.attributes)
|
||||
const orderSale = plainToClass(OrderSale, {
|
||||
orderId: orderItem.orderId,
|
||||
siteId: orderItem.siteId,
|
||||
externalOrderItemId: orderItem.externalOrderItemId,// 原始 itemId
|
||||
parentProductId: parentProduct.id, // 父产品 ID 用于统计套餐 如果是单品则不记录
|
||||
parentProductId: parentProduct?.id, // 父产品 ID 用于统计套餐 如果是单品则不记录
|
||||
productId: product.id,
|
||||
isPackage: product.type === 'bundle',// 这里是否是套餐取决于父产品
|
||||
name: product.name,
|
||||
|
|
@ -758,7 +759,7 @@ export class OrderService {
|
|||
flavor: attrsObj?.['flavor']?.name,
|
||||
humidity: attrsObj?.['humidity']?.name,
|
||||
size: attrsObj?.['size']?.name,
|
||||
category: product.category.name,
|
||||
category: product.category?.name,
|
||||
});
|
||||
return orderSale
|
||||
}).filter(v => v !== null)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Inject, Provide } from '@midwayjs/core';
|
||||
import { ILogger, Inject, Logger, Provide } from '@midwayjs/core';
|
||||
import { Context } from '@midwayjs/koa';
|
||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||
import * as fs from 'fs';
|
||||
|
|
@ -38,6 +38,9 @@ import { Site } from '../entity/site.entity';
|
|||
|
||||
@Provide()
|
||||
export class ProductService {
|
||||
@Logger()
|
||||
logger: ILogger; // 注入 Logger 实例
|
||||
|
||||
@Inject()
|
||||
ctx: Context;
|
||||
|
||||
|
|
@ -856,7 +859,7 @@ export class ProductService {
|
|||
// 检查完全相同属性组合是否已存在(避免重复)
|
||||
// 仅当产品类型为 'single' 且有属性时才检查重复
|
||||
if (type === 'single' && resolvedAttributes.length > 0) {
|
||||
const qb = this.productModel.createQueryBuilder('product');
|
||||
const qb = this.productModel.createQueryBuilder('product')
|
||||
resolvedAttributes.forEach((attr, index) => {
|
||||
qb.innerJoin(
|
||||
'product.attributes',
|
||||
|
|
@ -865,8 +868,12 @@ export class ProductService {
|
|||
{ [`attrId${index}`]: attr.id }
|
||||
);
|
||||
});
|
||||
// 添加属性数量的判断,确保产品的属性数量与指定的属性数量相同
|
||||
qb.andWhere('(SELECT COUNT(*) FROM product_attributes_dict_item pad WHERE pad.productId = product.id) = :attrCount', {
|
||||
attrCount: resolvedAttributes.length
|
||||
});
|
||||
const isExist = await qb.getOne();
|
||||
if (isExist) throw new Error('相同产品属性的产品已存在');
|
||||
if (isExist) throw new Error(`相同产品属性的产品已存在,sku 为${isExist?.sku}`);
|
||||
}
|
||||
|
||||
// 创建新产品实例(绑定属性与基础字段)
|
||||
|
|
@ -1778,36 +1785,31 @@ export class ProductService {
|
|||
attributes: attributes.length > 0 ? attributes : undefined,
|
||||
}
|
||||
}
|
||||
isMixedSku(sku: string) {
|
||||
const splitSKu = sku.split('-')
|
||||
const last = splitSKu[splitSKu.length - 1]
|
||||
const second = splitSKu[splitSKu.length - 2]
|
||||
// 这里判断 second 是否是数字
|
||||
return sku.includes('-MX-') || sku.includes('-Mixed-') || /^\d+$/.test(second) && /^\d+$/.test(last)
|
||||
}
|
||||
async getComponentDetailFromSiteSku(siteProduct: { sku: string, name: string }, quantity: number = 1, site: Site): Promise<{ product: Product,parentProduct?: Product, quantity: number }[]> {
|
||||
// 获取库存单品列表
|
||||
async getComponentDetailFromSiteSku(siteProduct: { sku: string, name?: string }, site: Site): Promise<{ product: Product,parentProduct?: Product, quantity: number }[]> {
|
||||
if (!siteProduct.sku) {
|
||||
throw new Error('siteSku 不能为空')
|
||||
}
|
||||
|
||||
const product = await this.getProductBySiteSku(siteProduct.sku, site)
|
||||
const product = await this.getProductBySiteSku(siteProduct.sku, site)
|
||||
|
||||
if (!product) return
|
||||
|
||||
if(!product?.components?.length){
|
||||
return [{
|
||||
product,
|
||||
quantity
|
||||
quantity:1
|
||||
}]
|
||||
}
|
||||
|
||||
return await Promise.all(product.components.map(async comp => {
|
||||
return {
|
||||
product: await this.productModel.findOne({
|
||||
where: { id: comp.productId },
|
||||
where: { sku: comp.sku },
|
||||
relations: ['category', 'attributes', 'attributes.dict', 'components']
|
||||
}),
|
||||
parentProduct: product, // 这里得记录一下他的爸爸用来记录
|
||||
quantity: comp.quantity * quantity,
|
||||
quantity: comp.quantity,
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
|
@ -2074,7 +2076,7 @@ export class ProductService {
|
|||
errors.push({ identifier: '' + rec.sku, error: `产品${rec?.sku}导入失败:${e?.message || String(e)}` });
|
||||
}
|
||||
}
|
||||
|
||||
this.logger.debug(`导入 ${records.length} 条记录,成功创建 ${created} 条,更新 ${updated} 条,失败 ${errors.length} 条,错误详情:${JSON.stringify(errors)}`);
|
||||
return { total: records.length, processed: records.length - errors.length, created, updated, errors };
|
||||
}
|
||||
|
||||
|
|
@ -2132,11 +2134,6 @@ export class ProductService {
|
|||
component.sku = product.sku;
|
||||
component.quantity = 1;
|
||||
product.components = [component];
|
||||
} else {
|
||||
// 混装商品返回持久化的 SKU 组成
|
||||
product.components = await this.productStockComponentModel.find({
|
||||
where: { productId: product.id },
|
||||
});
|
||||
}
|
||||
|
||||
return product;
|
||||
|
|
|
|||
Loading…
Reference in New Issue