cc0c0a6ef8
同城 MANUAL/ZZXFX 按小飞侠价规计费,路由查询回退仓配凭证;HQ 配送单补商品、用户和收货地址。门店核销回跳与小程序核销码一并带上。 Co-authored-by: Cursor <cursoragent@cursor.com>
59 lines
1.6 KiB
TypeScript
59 lines
1.6 KiB
TypeScript
import { toBottleQuantity } from '@dukang/domain';
|
|
|
|
const GOODS_NAME_MAX_LEN = 128;
|
|
|
|
export type XfxGoodsInput = {
|
|
productName: string;
|
|
/** SKU 规格快照,如「单瓶 / 整箱」 */
|
|
productSpec?: string | null;
|
|
/** SPU 物理规格,如「500ml | 53度」 */
|
|
physicalSpec?: string | null;
|
|
quantity: number;
|
|
bottlesPerUnit: number;
|
|
};
|
|
|
|
export type XfxGoodsPayload = {
|
|
goodsName: string;
|
|
goodsNum: number;
|
|
};
|
|
|
|
/** 小飞侠创建运单货品:品名+酒精度规格,件数用瓶当量 */
|
|
export function buildXfxGoodsPayload(input: XfxGoodsInput): XfxGoodsPayload {
|
|
const perUnit = input.bottlesPerUnit > 0 ? input.bottlesPerUnit : 1;
|
|
return {
|
|
goodsName: buildXfxGoodsName(input),
|
|
goodsNum: toBottleQuantity(input.quantity, perUnit),
|
|
};
|
|
}
|
|
|
|
function buildXfxGoodsName(input: XfxGoodsInput): string {
|
|
const name = trimSpec(input.productName);
|
|
const physical = trimSpec(input.physicalSpec);
|
|
const skuSpec = trimSpec(input.productSpec);
|
|
|
|
const parts: string[] = [];
|
|
if (name) parts.push(name);
|
|
|
|
if (physical) {
|
|
parts.push(physical);
|
|
if (skuSpec && !isRedundantSpec(physical, skuSpec)) {
|
|
parts.push(skuSpec);
|
|
}
|
|
} else if (skuSpec) {
|
|
parts.push(skuSpec);
|
|
}
|
|
|
|
return parts.join(' ').replace(/\s+/g, ' ').trim().slice(0, GOODS_NAME_MAX_LEN);
|
|
}
|
|
|
|
function trimSpec(raw?: string | null): string {
|
|
return (raw ?? '').trim();
|
|
}
|
|
|
|
function isRedundantSpec(physical: string, skuSpec: string): boolean {
|
|
const a = physical.replace(/\s+/g, '');
|
|
const b = skuSpec.replace(/\s+/g, '');
|
|
if (!b || a === b) return true;
|
|
return a.includes(b) || b.includes(a);
|
|
}
|