ERPTurbo_Client/packages/app-client/src/utils/SupplierWeightCalculator.ts
shenyifei 0cb0bab898 feat(app-client): 更新生产环境配置并优化采购模块显示
- 修改 TARO_POSTER_DOMAIN 环境变量,移除 H5 环境特殊处理逻辑
- 在 PurchasePreview 组件中新增“空磅”与“总磅”字段展示
- Weigh 组件中增加表单验证状态的日志输出
- 更新应用版本号从 v0.0.24 到 v0.0.25
- delivery 页面引入 PdfTemplate 并替换原有 Template 类
- create 页面调整 setActive 调用位置并在订单创建流程中设置默认值
- preview 页面将按钮文案由“编辑”改为“上一步”
- audit result 页面文案从“审核”统一为“审批”
- 重构 SupplierWeightCalculator 计算逻辑,修正额外纸箱重量使用字段
- 修复 PurchaseOrderCalculator 中利润计算公式的运算顺序错误
- 移除部分无用 console 日志,保留关键调试信息
2025-11-20 18:42:26 +08:00

190 lines
6.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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);
}
}