- 修改 TARO_POSTER_DOMAIN 环境变量,移除 H5 环境特殊处理逻辑 - 在 PurchasePreview 组件中新增“空磅”与“总磅”字段展示 - Weigh 组件中增加表单验证状态的日志输出 - 更新应用版本号从 v0.0.24 到 v0.0.25 - delivery 页面引入 PdfTemplate 并替换原有 Template 类 - create 页面调整 setActive 调用位置并在订单创建流程中设置默认值 - preview 页面将按钮文案由“编辑”改为“上一步” - audit result 页面文案从“审核”统一为“审批” - 重构 SupplierWeightCalculator 计算逻辑,修正额外纸箱重量使用字段 - 修复 PurchaseOrderCalculator 中利润计算公式的运算顺序错误 - 移除部分无用 console 日志,保留关键调试信息
190 lines
6.2 KiB
TypeScript
190 lines
6.2 KiB
TypeScript
import { Decimal } from "decimal.js";
|
||
|
||
/**
|
||
* 农户重量计算器类
|
||
* 用于计算每个农户的净重和毛重,并赋值到原数据中
|
||
*/
|
||
export class SupplierWeightCalculator {
|
||
private suppliers: BusinessAPI.OrderSupplier[];
|
||
|
||
constructor(suppliers: BusinessAPI.OrderSupplier[]) {
|
||
this.suppliers = suppliers;
|
||
this.init();
|
||
}
|
||
|
||
/**
|
||
* 初始化计算规则
|
||
*/
|
||
private init() {
|
||
Decimal.set({
|
||
precision: 20,
|
||
rounding: 0, // 向下舍入(更保守的计算方式)
|
||
toExpNeg: -7,
|
||
toExpPos: 21,
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 计算所有农户的重量信息
|
||
* @returns {Array} 包含净重、毛重和空磅的农户数据
|
||
*/
|
||
calculate(): BusinessAPI.OrderSupplier[] {
|
||
if (!this.suppliers || this.suppliers.length === 0) {
|
||
return this.suppliers;
|
||
}
|
||
|
||
// 使用第一个瓜农的空磅重量作为初始空磅重量
|
||
const initialEmptyWeight = this.suppliers[0].emptyWeight || 0;
|
||
let previousTotalWeight = initialEmptyWeight; // 上一个农户的总磅重量(kg)
|
||
|
||
for (let i = 0; i < this.suppliers.length; i++) {
|
||
const supplier = this.suppliers[i];
|
||
const isFirstSupplier = i === 0;
|
||
const isLastSupplier = supplier.isLast;
|
||
|
||
// 设置空磅重量(第一个农户使用自己的空磅重量,其他使用前一个农户的总磅重量)
|
||
if (isFirstSupplier) {
|
||
// 第一个农户的空磅重量已经是正确的
|
||
} else {
|
||
supplier.emptyWeight = this.suppliers[i - 1].totalWeight || 0;
|
||
}
|
||
|
||
// 计算本次使用纸箱的总重量(斤)
|
||
const usedBoxesWeight = new Decimal(
|
||
this.calculateBoxesTotalWeight(supplier.orderPackageList || [], "USED"),
|
||
)
|
||
.add(
|
||
this.calculateBoxesTotalWeight(
|
||
supplier.orderPackageList || [],
|
||
"OWN",
|
||
),
|
||
)
|
||
.toNumber();
|
||
|
||
// 计算额外配送的已使用纸箱总重量(斤)
|
||
const extraUsedBoxesWeight = this.calculateBoxesTotalWeight(
|
||
supplier.orderPackageList || [],
|
||
"EXTRA_USED",
|
||
);
|
||
|
||
if (!supplier.isPaper) {
|
||
// 如果不是纸箱包装,直接使用原始重量(kg转斤)
|
||
supplier.grossWeight = new Decimal(supplier.totalWeight || 0)
|
||
.sub(supplier.emptyWeight || 0)
|
||
.mul(2)
|
||
.toNumber();
|
||
|
||
supplier.netWeight = new Decimal(supplier.grossWeight || 0)
|
||
.sub(usedBoxesWeight)
|
||
.sub(extraUsedBoxesWeight)
|
||
.toNumber();
|
||
|
||
previousTotalWeight = supplier.totalWeight;
|
||
supplier.invoiceAmount = new Decimal(supplier.netWeight || 0)
|
||
.mul(supplier.purchasePrice || 0)
|
||
.toNumber();
|
||
continue;
|
||
}
|
||
|
||
// 计算额外配送的纸箱总重量(斤)
|
||
const extraBoxesWeight = this.calculateBoxesTotalWeight(
|
||
supplier.orderPackageList || [],
|
||
"EXTRA",
|
||
);
|
||
|
||
// 计算车上剩余纸箱(斤)
|
||
const remainingBoxesWeight = this.calculateBoxesTotalWeight(
|
||
supplier.orderPackageList || [],
|
||
"REMAIN",
|
||
);
|
||
|
||
if (isFirstSupplier && isLastSupplier) {
|
||
// 既是第一个也是最后一个瓜农(单个瓜农情况)- 优先使用最后一个瓜农算法
|
||
// 净重 = (总磅 - 空磅) * 2 + 剩余空箱子重量 - 已使用额外纸箱重量
|
||
supplier.netWeight = new Decimal(supplier.totalWeight || 0)
|
||
.sub(initialEmptyWeight)
|
||
.mul(2)
|
||
.add(remainingBoxesWeight)
|
||
.sub(extraUsedBoxesWeight)
|
||
.toNumber();
|
||
// 毛重 = 净重 + 本次使用纸箱重量
|
||
supplier.grossWeight = new Decimal(supplier.netWeight || 0)
|
||
.add(usedBoxesWeight)
|
||
.toNumber();
|
||
} else if (isLastSupplier) {
|
||
// 最后一个农户(根据isLast标识判断)
|
||
// 净重 = (总磅 - 前一个总磅) * 2 + 剩余空箱子重量 - 已使用额外纸箱重量
|
||
supplier.netWeight = new Decimal(supplier.totalWeight || 0)
|
||
.sub(previousTotalWeight)
|
||
.mul(2)
|
||
.add(remainingBoxesWeight)
|
||
.sub(extraUsedBoxesWeight)
|
||
.toNumber();
|
||
// 毛重 = 净重 + 本次使用纸箱重量
|
||
supplier.grossWeight = new Decimal(supplier.netWeight || 0)
|
||
.add(usedBoxesWeight)
|
||
.toNumber();
|
||
} else if (isFirstSupplier) {
|
||
// 第一个农户(但不是最后一个)
|
||
// 净重 = (总磅 - 空磅) * 2 - 额外纸箱重量
|
||
supplier.netWeight = new Decimal(supplier.totalWeight || 0)
|
||
.sub(initialEmptyWeight)
|
||
.mul(2)
|
||
.sub(extraBoxesWeight)
|
||
.toNumber();
|
||
// 毛重 = 净重 + 本次使用纸箱重量
|
||
supplier.grossWeight = new Decimal(supplier.netWeight || 0)
|
||
.add(usedBoxesWeight)
|
||
.toNumber();
|
||
} else {
|
||
// 中间农户
|
||
// 净重 = (总磅 - 前一个总磅) * 2 - 额外纸箱重量
|
||
supplier.netWeight = new Decimal(supplier.totalWeight || 0)
|
||
.sub(previousTotalWeight)
|
||
.mul(2)
|
||
.sub(extraBoxesWeight)
|
||
.toNumber();
|
||
// 毛重 = 净重 + 本次使用纸箱重量
|
||
supplier.grossWeight = new Decimal(supplier.netWeight || 0)
|
||
.add(usedBoxesWeight)
|
||
.toNumber();
|
||
}
|
||
|
||
previousTotalWeight = supplier.totalWeight || 0;
|
||
supplier.invoiceAmount = new Decimal(supplier.netWeight || 0)
|
||
.mul(supplier.purchasePrice || 0)
|
||
.toNumber();
|
||
}
|
||
|
||
return this.suppliers;
|
||
}
|
||
|
||
/**
|
||
* 计算纸箱的总重量(斤)
|
||
* @param {Array} orderPackageList - 包装信息列表
|
||
* @param {string} boxType - 箱子类型 ('USED' 或 'EXTRA',不传则计算所有)
|
||
* @returns {number} 总重量(斤)
|
||
*/
|
||
private calculateBoxesTotalWeight(
|
||
orderPackageList: BusinessAPI.OrderPackage[],
|
||
boxType?: any,
|
||
): number {
|
||
if (!orderPackageList) return 0;
|
||
|
||
let filteredPackages = orderPackageList;
|
||
if (boxType) {
|
||
filteredPackages = orderPackageList.filter(
|
||
(pkg) => pkg.boxType === boxType,
|
||
);
|
||
}
|
||
|
||
return filteredPackages.reduce((sum, pkg) => {
|
||
// 纸箱重量单位是斤,直接使用
|
||
const boxWeight = pkg.boxProductWeight || 0;
|
||
return new Decimal(sum)
|
||
.add(new Decimal(pkg.boxCount || 0).mul(boxWeight))
|
||
.toNumber();
|
||
}, 0);
|
||
}
|
||
}
|