@@ -12,7 +12,7 @@ import {
|
||||
mapSkuDto,
|
||||
mapSpecAttrsDto,
|
||||
pickDisplaySku,
|
||||
resolveOrderSku,
|
||||
resolveOrderSale,
|
||||
} from './product-sku.util';
|
||||
|
||||
export type CatalogViewer = {
|
||||
@@ -204,7 +204,7 @@ export class CatalogService {
|
||||
});
|
||||
}
|
||||
|
||||
/** 下单前校验:白名单商品仅全局测试白名单手机号可买;返回 SPU + 解析后的 SKU */
|
||||
/** 下单前校验:白名单商品仅全局测试白名单手机号可买;无 SKU 时回落 SPU 字段 */
|
||||
async assertPurchasable(
|
||||
productId: bigint,
|
||||
viewerPhone?: string | null,
|
||||
@@ -224,8 +224,8 @@ export class CatalogService {
|
||||
throw new BadRequestException('该商品暂不对当前账号开放');
|
||||
}
|
||||
}
|
||||
const sku = resolveOrderSku(product.skus, skuId);
|
||||
return { product, sku };
|
||||
const sale = resolveOrderSale(product, product.skus ?? [], skuId);
|
||||
return { product, sale };
|
||||
}
|
||||
|
||||
async resolveUserPhone(userId: bigint): Promise<string | null> {
|
||||
|
||||
@@ -37,23 +37,79 @@ export function buildSpecText(
|
||||
.join(' / ');
|
||||
}
|
||||
|
||||
/** 下单用销售快照:有可售 SKU 则用 SKU,否则回落 SPU(旧客户端 / 未回填) */
|
||||
export type OrderSaleSnapshot = {
|
||||
skuId: bigint | null;
|
||||
skuCode: string;
|
||||
barcode69: string;
|
||||
specText: string;
|
||||
price: CommonProductSku['price'];
|
||||
benefitAmount: CommonProductSku['benefitAmount'];
|
||||
allowOnSitePickup: boolean;
|
||||
allowOnlinePurchase: boolean;
|
||||
allowCrossCityDelivery: boolean;
|
||||
saleUnit: ProductSaleUnit;
|
||||
bottlesPerUnit: number;
|
||||
};
|
||||
|
||||
export function saleSnapshotFromProduct(product: CommonProductItem): OrderSaleSnapshot {
|
||||
return {
|
||||
skuId: null,
|
||||
skuCode: product.skuCode,
|
||||
barcode69: product.barcode69,
|
||||
specText: product.spec,
|
||||
price: product.price,
|
||||
benefitAmount: product.benefitAmount,
|
||||
allowOnSitePickup: product.allowOnSitePickup,
|
||||
allowOnlinePurchase: product.allowOnlinePurchase,
|
||||
allowCrossCityDelivery: product.allowCrossCityDelivery,
|
||||
saleUnit: 'BOTTLE',
|
||||
bottlesPerUnit: 1,
|
||||
};
|
||||
}
|
||||
|
||||
export function saleSnapshotFromSku(
|
||||
sku: CommonProductSku,
|
||||
product: CommonProductItem,
|
||||
): OrderSaleSnapshot {
|
||||
return {
|
||||
skuId: sku.id,
|
||||
skuCode: sku.skuCode,
|
||||
barcode69: sku.barcode69,
|
||||
specText: sku.specText || product.spec,
|
||||
price: sku.price,
|
||||
benefitAmount: sku.benefitAmount,
|
||||
allowOnSitePickup: sku.allowOnSitePickup,
|
||||
allowOnlinePurchase: sku.allowOnlinePurchase,
|
||||
allowCrossCityDelivery: sku.allowCrossCityDelivery,
|
||||
saleUnit: sku.saleUnit,
|
||||
bottlesPerUnit: sku.bottlesPerUnit > 0 ? sku.bottlesPerUnit : sku.saleUnit === 'BOX' ? BOTTLES_PER_BOX : 1,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析下单 SKU:显式 skuId,或单可售自动回落;多可售且未传则 400。
|
||||
* 现网兼容:
|
||||
* - 不传 skuId:有可售 SKU 用默认/唯一可售;一个都没有则回落 SPU 字段(未回填也能下单)
|
||||
* - 传入 skuId:按 SKU 校验(新客户端选规格)
|
||||
* 不在旧接口上因「无 SKU」或「多规格未选」打断现网下单。
|
||||
*/
|
||||
export function resolveOrderSku(
|
||||
export function resolveOrderSale(
|
||||
product: CommonProductItem,
|
||||
skus: CommonProductSku[],
|
||||
skuId?: string | null,
|
||||
): CommonProductSku {
|
||||
const onSale = skus.filter(isSkuOnSale);
|
||||
): OrderSaleSnapshot {
|
||||
if (skuId) {
|
||||
const found = skus.find((s) => s.id.toString() === String(skuId));
|
||||
if (!found) throw new BadRequestException('规格不存在');
|
||||
if (!isSkuOnSale(found)) throw new BadRequestException('该规格暂不可购买');
|
||||
return found;
|
||||
return saleSnapshotFromSku(found, product);
|
||||
}
|
||||
if (onSale.length === 1) return onSale[0];
|
||||
if (onSale.length === 0) throw new BadRequestException('商品暂无可售规格');
|
||||
throw new BadRequestException('请选择规格');
|
||||
const onSale = skus.filter(isSkuOnSale);
|
||||
if (onSale.length >= 1) {
|
||||
const picked = onSale.find((s) => s.isDefault) ?? onSale[0];
|
||||
return saleSnapshotFromSku(picked, product);
|
||||
}
|
||||
return saleSnapshotFromProduct(product);
|
||||
}
|
||||
|
||||
/** 列表/拍平:优先默认可售 → 最低价可售 → 默认任意 → 任意 */
|
||||
|
||||
Reference in New Issue
Block a user