系统判断配送限制

This commit is contained in:
2026-07-26 09:59:38 +08:00
parent 19cb312465
commit da21cd3daa
12 changed files with 176 additions and 10 deletions
+11
View File
@@ -3,6 +3,8 @@ import {
calcBenefitAmount,
calcRedeemSettleAmount,
calcLogisticsFeeByBottles,
calcOrderBoxCount,
shouldHoldAutoCourierDispatch,
validateMinPurchase,
validateRedeemAmount,
allocateBenefitCoupons,
@@ -99,6 +101,15 @@ describe('calcLogisticsFeeByBottles', () => {
});
});
describe('shouldHoldAutoCourierDispatch', () => {
it('holds at 10 full boxes (60 bottles)', () => {
expect(shouldHoldAutoCourierDispatch(59)).toBe(false);
expect(shouldHoldAutoCourierDispatch(60)).toBe(true);
expect(shouldHoldAutoCourierDispatch(66)).toBe(true);
expect(calcOrderBoxCount(60)).toBe(10);
});
});
describe('allocateBenefitCoupons', () => {
const coupons = [
{ id: '1', balance: 300, createdAt: 1 },
+24
View File
@@ -95,6 +95,30 @@ export function calcRedeemSettleAmount(amount: number, settlementRate: number):
return Math.round(amount * settlementRate * 100) / 100;
}
/** 箱规默认瓶数(跨城起购 / 物流计价 / 大单拦截) */
export const BOTTLES_PER_BOX = 6;
/** 小飞侠自动推单上限箱数:达到该箱数起拦截,需总部确认后推单或自配送 */
export const XFX_AUTO_DISPATCH_MAX_BOXES = 10;
/** 按箱规向上取整得到箱数 */
export function calcOrderBoxCount(quantity: number, bottlesPerBox = BOTTLES_PER_BOX): number {
const qty = Math.floor(Number(quantity) || 0);
if (qty <= 0 || !(bottlesPerBox > 0)) return 0;
return Math.ceil(qty / bottlesPerBox);
}
/** 是否因大单拦截自动推承运商(默认 ≥10 箱 = 60 瓶) */
export function shouldHoldAutoCourierDispatch(
quantity: number,
options?: { bottlesPerBox?: number; maxBoxes?: number },
): boolean {
const bottlesPerBox = options?.bottlesPerBox ?? BOTTLES_PER_BOX;
const maxBoxes = options?.maxBoxes ?? XFX_AUTO_DISPATCH_MAX_BOXES;
const qty = Math.floor(Number(quantity) || 0);
return qty >= bottlesPerBox * maxBoxes;
}
/** 物流(快递)按瓶计价规则,如小飞侠:2瓶6元、加一瓶+2元、6瓶一箱14元 */
export type LogisticsPricingRule = {
baseBottles: number;
+5
View File
@@ -34,6 +34,11 @@ export interface DeliveryDto {
deliveredAt?: string;
}
/** 大单拦截原因:≥10 箱不自动推小飞侠 */
export const FULFILLMENT_HOLD_REASON_LABELS: Record<string, string> = {
LARGE_ORDER_GE_10_BOXES: '大单≥10箱,待总部确认推单/自配送',
};
export type PartnerProxyOrderProductOption = {
id: string;
name: string;