feat(order): 优化订单处理流程和数据计算逻辑

- 在Step3Success组件中按车次正序排列订单
- 为MadeOption和MarketOption组件添加滚动到顶部功能
- 更新供应商数据结构,添加收款人姓名、银行名称等字段
- 修改TicketUpload组件中的毛重量显示和发票ID初始化
- 优化审批页面中的条件渲染逻辑,避免显示零值
- 更新销售价格计算逻辑,使用总重量替代供应商数量
- 移除废弃的StallWeightCalculator类,整合到SupplierWeightCalculator中
- 修复小数计算精度问题,统一使用两位小数精度
- 添加草帘费成本的开关控制逻辑
This commit is contained in:
shenyifei 2026-01-09 11:18:18 +08:00
parent e6855dba63
commit 9be4076df8
16 changed files with 182 additions and 391 deletions

View File

@ -51,6 +51,13 @@ export default function Step3Success(props: Step3SuccessProps) {
const profitData: ProfitTableRow[] = [];
let includeNext = true;
// orderVOList 根据车次正序
orderVOList.sort((a, b) => {
return (
Number(a.orderVehicle.vehicleNo) - Number(b.orderVehicle?.vehicleNo)
);
});
for (const order of orderVOList) {
// 如果还没有到达当前车次,继续
if (includeNext) {

View File

@ -10,6 +10,7 @@ import { business } from "@/services";
// 定义ref暴露的方法接口
export interface MadeOptionRef {
onAdd: () => void;
scrollToTop: () => void;
}
interface IMadeOptionProps {
@ -45,7 +46,16 @@ export default forwardRef<MadeOptionRef, IMadeOptionProps>(function MadeOption(
const active = Number(value.active);
// 滚动到页面顶部
const scrollToTop = () => {
Taro.pageScrollTo({
scrollTop: 0,
duration: 100,
});
};
const setActive = (active: number) => {
scrollToTop();
onChange({
...value,
active,
@ -251,6 +261,7 @@ export default forwardRef<MadeOptionRef, IMadeOptionProps>(function MadeOption(
return;
}
scrollToTop();
onChange({
...value,
active: 2,
@ -263,10 +274,14 @@ export default forwardRef<MadeOptionRef, IMadeOptionProps>(function MadeOption(
orderSupplierId: generateShortId(),
supplierId: "",
name: "瓜农" + (orderSupplierList.length + 1),
payeeName: "",
idCard: "",
bankName: "",
bankCard: "",
phone: "",
selected: true,
loadingMode: orderSupplierList[selectedIndex].loadingMode,
pricingMethod: orderSupplierList[selectedIndex].pricingMethod,
isPaper: orderSupplierList[selectedIndex].isPaper,
orderPackageList: [],
productId: orderSupplierList[selectedIndex]?.productId,
@ -280,6 +295,7 @@ export default forwardRef<MadeOptionRef, IMadeOptionProps>(function MadeOption(
// 将校验方法暴露给父组件
useImperativeHandle(ref, () => ({
onAdd,
scrollToTop,
}));
async function saveDraft() {
@ -316,7 +332,7 @@ export default forwardRef<MadeOptionRef, IMadeOptionProps>(function MadeOption(
content: "当前采购订单已暂存成功",
});
Taro.redirectTo({
url: purchase.path[orderVO.type].drafts,
url: purchase.path["PRODUCTION_PURCHASE"].drafts,
});
}
},

View File

@ -10,6 +10,7 @@ import purchase from "@/constant/purchase";
// 定义ref暴露的方法接口
export interface MarketOptionRef {
onAdd: () => void;
scrollToTop: () => void;
}
interface IMarketOptionProps {
@ -39,7 +40,15 @@ export default forwardRef<MarketOptionRef, IMarketOptionProps>(
const active = Number(value.active);
// 滚动到页面顶部
const scrollToTop = () => {
Taro.pageScrollTo({
scrollTop: 0,
duration: 100,
});
};
const setActive = (active: number) => {
scrollToTop();
onChange({
...value,
active,
@ -192,6 +201,7 @@ export default forwardRef<MarketOptionRef, IMarketOptionProps>(
return;
}
scrollToTop();
onChange({
...value,
active: 2,
@ -204,11 +214,14 @@ export default forwardRef<MarketOptionRef, IMarketOptionProps>(
orderSupplierId: generateShortId(),
supplierId: "",
name: "档口" + (orderSupplierList.length + 1),
payeeName: "",
idCard: "",
bankName: "",
bankCard: "",
phone: "",
selected: true,
isPaper: orderSupplierList[selectedIndex].isPaper,
loadingMode: orderSupplierList[selectedIndex].loadingMode,
pricingMethod: orderSupplierList[selectedIndex].pricingMethod,
orderPackageList: [],
productId: orderSupplierList[selectedIndex]?.productId,
productName: orderSupplierList[selectedIndex]?.productName,
@ -221,6 +234,7 @@ export default forwardRef<MarketOptionRef, IMarketOptionProps>(
// 将校验方法暴露给父组件
useImperativeHandle(ref, () => ({
onAdd,
scrollToTop,
}));
async function saveDraft() {
@ -252,7 +266,7 @@ export default forwardRef<MarketOptionRef, IMarketOptionProps>(
content: "当前采购订单已暂存成功",
});
Taro.redirectTo({
url: "/pages/purchase/made/drafts",
url: purchase.path["MARKET_PURCHASE"].drafts,
});
}
},

View File

@ -485,10 +485,8 @@ export default forwardRef<OrderVehicleRef, IOrderVehicleProps>(
plate: newVehicle.plate?.split("-")[0]!,
dealerId: newVehicle.dealerId || orderVehicle?.dealerId,
dealerName: newVehicle.dealerName || orderVehicle?.dealerName,
openStrawCurtain: false,
//@ts-ignore
strawCurtainPrice: "",
deliveryTime: dayjs().format("YYYY-MM-DD"),
//@ts-ignore
originalData: originalData || "",
},
orderDealer: {

View File

@ -95,6 +95,14 @@ export default function TicketUpload(props: ITicketUploadProps) {
{supplierVO.netWeight || 0}
</View>
</View>
<View className="flex justify-between text-sm">
<View className="text-neutral-darker text-sm">
</View>
<View className="font-medium text-gray-800">
{supplierVO.grossWeight || 0}
</View>
</View>
<View className="flex justify-between text-sm">
<View className="text-neutral-darker text-sm">
/
@ -167,7 +175,7 @@ export default function TicketUpload(props: ITicketUploadProps) {
...supplierVO!,
invoiceImg: [],
invoiceUpload: false,
invoiceId: 0,
invoiceId: undefined,
});
}}
>
@ -185,7 +193,7 @@ export default function TicketUpload(props: ITicketUploadProps) {
...supplierVO!,
invoiceImg: [],
invoiceUpload: false,
invoiceId: 0,
invoiceId: undefined,
});
Toast.show("toast", {
title: "删除成功",

View File

@ -27,8 +27,8 @@ export default function OrderSupplierPicker(props: IOrderSupplierPickerProps) {
const [orderSupplierList, setOrderSupplierList] = useState<
BusinessAPI.OrderSupplierVO[]
>([]);
// 发票开具人(有开发票资质的瓜农
const [invoiceIssuer, setInvoiceIssuer] = useState<BusinessAPI.SupplierVO>();
// 瓜农
const [supplierVO, setSupplierVO] = useState<BusinessAPI.SupplierVO>();
const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set());
useEffect(() => {
@ -112,7 +112,7 @@ export default function OrderSupplierPicker(props: IOrderSupplierPickerProps) {
<SupplierPicker
type={"FARMER"}
onFinish={(supplierVO) => {
setInvoiceIssuer(supplierVO);
setSupplierVO(supplierVO);
actionRef.current?.reload();
}}
trigger={
@ -120,14 +120,14 @@ export default function OrderSupplierPicker(props: IOrderSupplierPickerProps) {
className={`border-primary flex h-6 items-center rounded-md border-2 px-2.5`}
>
<View className={"text-primary text-xs"}>
{invoiceIssuer?.name || "发票开具人"}
{supplierVO?.name || "瓜农"}
</View>
{invoiceIssuer?.name ? (
{supplierVO?.name ? (
<Icon
name={"circle-xmark"}
size={16}
onClick={(event) => {
setInvoiceIssuer(undefined);
setSupplierVO(undefined);
actionRef.current?.reload();
event.stopPropagation();
}}
@ -390,6 +390,7 @@ export default function OrderSupplierPicker(props: IOrderSupplierPickerProps) {
invoiceUpload: false,
poStates: ["AUDITING", "COMPLETED"],
poType: "PRODUCTION_PURCHASE",
supplierId: supplierVO?.supplierId,
},
});

View File

@ -1,2 +1,2 @@
// App 相关常量
export const APP_VERSION = "v0.0.66";
export const APP_VERSION = "v0.0.69";

View File

@ -251,7 +251,8 @@ export default hocAuth(function Page(props: CommonComponent) {
);
})}
{orderVO.orderDealer?.enableLoss && (
{orderVO.orderDealer?.enableLoss &&
Number(orderVO.orderDealer?.lossAmount) > 0 && (
<View className="cost-item flex flex-col px-3 py-2">
<View className="text-sm text-gray-500"></View>
<View className="font-medium">
@ -260,8 +261,7 @@ export default hocAuth(function Page(props: CommonComponent) {
</View>
)}
{orderVO.orderDealer?.taxProvision &&
orderVO.orderDealer?.taxProvision > 0 && (
{Number(orderVO.orderDealer?.taxProvision || 0) > 0 && (
<View className="cost-item flex flex-col px-3 py-2">
<View className="text-sm text-gray-500"></View>
<View className="font-medium">
@ -270,8 +270,7 @@ export default hocAuth(function Page(props: CommonComponent) {
</View>
)}
{orderVO.orderDealer?.taxSubsidy &&
orderVO.orderDealer?.taxSubsidy > 0 && (
{Number(orderVO.orderDealer?.taxSubsidy || 0) > 0 && (
<View className="cost-item flex flex-col px-3 py-2">
<View className="text-sm text-gray-500"></View>
<View className="font-medium">
@ -280,7 +279,8 @@ export default hocAuth(function Page(props: CommonComponent) {
</View>
)}
{orderVO.orderRebate?.amount && orderVO.orderRebate?.amount > 0 && (
{orderVO.orderRebate &&
Number(orderVO.orderRebate.amount || 0) > 0 && (
<View className="cost-item flex flex-col px-3 py-2">
<View className="text-sm text-gray-500"></View>
<View className="font-medium">
@ -289,8 +289,7 @@ export default hocAuth(function Page(props: CommonComponent) {
</View>
)}
{orderVO.orderDealer?.costDifference &&
orderVO.orderDealer?.costDifference > 0 && (
{Number(orderVO.orderDealer?.costDifference || 0) > 0 && (
<View className="cost-item flex flex-col px-3 py-2">
<View className="text-sm text-gray-500"></View>
<View className="font-medium">

View File

@ -719,6 +719,7 @@ export default hocAuth(function Page(props: CommonComponent) {
})
.filter(Boolean);
console.log("orderVO", orderVO);
return (
<>
<View
@ -861,14 +862,14 @@ export default hocAuth(function Page(props: CommonComponent) {
"text-red-500": personalProfit < 0,
})}
>
{personalProfit || "-"}
{personalProfit || "0"}
</View>
</View>
</View>
<View className="flex justify-between gap-2 border-t border-gray-200 p-2.5">
{auditVO?.type === "REVIEWER_AUDIT" &&
(auditVO.state === "WAITING_AUDIT" ||
auditVO.state === "AUDIT_REJECTED") ? (
{orderVO.state === "AUDITING" &&
(orderVO.auditState === "PENDING_QUOTE_APPROVAL" ||
orderVO.auditState === "BOSS_REJECTED") ? (
<>
<View className={"flex-1"}>
<Button
@ -881,6 +882,10 @@ export default hocAuth(function Page(props: CommonComponent) {
</Button>
</View>
{auditVO &&
auditVO?.type === "REVIEWER_AUDIT" &&
(auditVO.state === "WAITING_AUDIT" ||
auditVO.state === "AUDIT_REJECTED") && (
<View className={"flex-1"}>
<OrderRejectApprove
size={"large"}
@ -892,6 +897,7 @@ export default hocAuth(function Page(props: CommonComponent) {
}}
/>
</View>
)}
<View className={"flex-1"}>
<Button
block

View File

@ -275,6 +275,7 @@ export default hocAuth(function Page(props: CommonComponent) {
value={order as any}
onChange={(orderVO: BusinessAPI.OrderVO) => {
setOrder(orderVO);
orderOptionRef.current?.scrollToTop();
}}
melonFarmerRefs={supplierInfoRefs}
weighRefs={supplierWeighRefs}

View File

@ -3318,7 +3318,7 @@ declare namespace BusinessAPI {
/** 返点单价 */
unitPrice?: number;
/** 返点金额 */
amount?: number;
amount: number;
/** 是否已付款 */
isPaid?: boolean;
};

View File

@ -16,6 +16,10 @@ export class OrderRules {
*
*/
shouldIncludeStrawCurtainCost(): boolean {
if (!this.order.orderDealer?.strawMatCostFlag) {
return false;
}
return !!(
this.order.orderVehicle?.openStrawCurtain &&
this.order.orderVehicle?.strawCurtainPrice

View File

@ -20,7 +20,7 @@ export class DecimalUtils {
* Decimal
*/
static create(value: number | string | Decimal = 0): Decimal {
return new Decimal(value);
return new Decimal(value || 0);
}
/**
@ -69,7 +69,7 @@ export class DecimalUtils {
if (!b || this.create(b).isZero()) {
return defaultValue;
}
return this.create(a).div(b).toNumber();
return this.create(a).div(b).toDecimalPlaces(2).toNumber();
}
/**

View File

@ -74,20 +74,8 @@ export class SalesCalculator {
*
*/
calculateAverageSalesPrice(): number {
if (!this.order.orderSupplierList.length) {
return 0;
}
const totalSalesPrice = this.order.orderSupplierList.reduce(
(total, supplier) => DecimalUtils.add(total, supplier.salePrice || 0),
0,
);
return DecimalUtils.divide(
totalSalesPrice,
this.order.orderSupplierList.length,
0,
);
const totalSalesPrice = this.calculateSalesAmount();
return DecimalUtils.divide(totalSalesPrice, this.calculateTotalWeight(), 0);
}
/**

View File

@ -1,285 +0,0 @@
import { DecimalUtils } from "../core/DecimalUtils";
/**
*
*
*/
export class StallWeightCalculator {
private suppliers: BusinessAPI.OrderSupplier[];
private initialEmptyWeight: number;
private previousTotalWeight: number;
constructor(suppliers: BusinessAPI.OrderSupplier[]) {
this.suppliers = suppliers || [];
this.initialEmptyWeight = this.suppliers[0]?.emptyWeight || 0;
this.previousTotalWeight = this.initialEmptyWeight;
}
/**
*
* @returns
*/
calculate(): BusinessAPI.OrderSupplier[] {
if (!this.suppliers.length) {
return this.suppliers;
}
for (let i = 0; i < this.suppliers.length; i++) {
const supplier = this.suppliers[i];
this.calculateSupplierWeight(supplier, i);
}
return this.suppliers;
}
/**
*
*/
private calculateSupplierWeight(
supplier: BusinessAPI.OrderSupplier,
index: number,
): void {
const isFirstSupplier = index === 0;
const isLastSupplier = supplier.isLast;
// 设置空磅重量
this.setEmptyWeight(supplier, index);
// 计算各类纸箱重量
const weights = this.calculateAllBoxWeights(
supplier.orderPackageList || [],
);
if (!supplier.isPaper) {
// 非纸箱包装的简化计算
this.calculateNonPaperSupplier(supplier, weights.used);
} else {
// 纸箱包装的复杂计算
this.calculatePaperSupplier(
supplier,
weights,
isFirstSupplier,
isLastSupplier,
);
}
// 计算发票金额
this.calculateInvoiceAmount(supplier);
// 更新上一个供应商的总重量
this.previousTotalWeight = supplier.totalWeight || 0;
}
/**
*
*/
private setEmptyWeight(
supplier: BusinessAPI.OrderSupplier,
index: number,
): void {
if (index === 0) {
// 第一个农户保持原有空磅重量
} else {
// 其他农户使用前一个农户的总磅重量
supplier.emptyWeight = this.suppliers[index - 1]?.totalWeight || 0;
}
}
/**
*
*/
private calculateAllBoxWeights(packages: BusinessAPI.OrderPackage[]) {
return {
used: this.calculateBoxWeightByType(packages, "USED"),
extra: this.calculateBoxWeightByType(packages, "EXTRA"),
remain: this.calculateBoxWeightByType(packages, "REMAIN"),
extraUsed: this.calculateBoxWeightByType(packages, "EXTRA_USED"),
};
}
/**
*
*/
private calculateNonPaperSupplier(
supplier: BusinessAPI.OrderSupplier,
usedBoxesWeight: number,
): void {
// 毛重 = (总磅 - 空磅) × 2
supplier.grossWeight = DecimalUtils.multiply(
DecimalUtils.subtract(
supplier.totalWeight || 0,
supplier.emptyWeight || 0,
),
2,
);
// 净重 = 毛重 - 使用纸箱重量
supplier.netWeight = DecimalUtils.subtract(
supplier.grossWeight || 0,
usedBoxesWeight,
);
}
/**
*
*/
private calculatePaperSupplier(
supplier: BusinessAPI.OrderSupplier,
weights: { used: number; extra: number; remain: number; extraUsed: number },
isFirstSupplier: boolean,
isLastSupplier: boolean,
): void {
const weightDiff = isFirstSupplier
? DecimalUtils.subtract(
supplier.totalWeight || 0,
this.initialEmptyWeight,
)
: DecimalUtils.subtract(
supplier.totalWeight || 0,
this.previousTotalWeight,
);
const weightDiffInJin = DecimalUtils.multiply(weightDiff, 2);
if (isFirstSupplier && isLastSupplier) {
// 单个农户情况
supplier.netWeight = DecimalUtils.add(
DecimalUtils.subtract(
DecimalUtils.add(weightDiffInJin, weights.remain),
weights.extraUsed,
),
);
} else if (isLastSupplier) {
// 最后一个农户
supplier.netWeight = DecimalUtils.add(
DecimalUtils.subtract(weightDiffInJin, weights.extraUsed),
weights.remain,
);
} else {
// 中间农户(包括第一个但不是最后一个)
supplier.netWeight = DecimalUtils.subtract(
weightDiffInJin,
weights.extra,
);
}
// 毛重 = 净重 + 本次使用纸箱重量
supplier.grossWeight = DecimalUtils.add(
supplier.netWeight || 0,
weights.used,
);
}
/**
*
*/
private calculateQuoteWeight(supplier: BusinessAPI.OrderSupplier): number {
return supplier.pricingMethod === "BY_GROSS_WEIGHT"
? supplier.grossWeight
: supplier.netWeight;
}
/**
*
*/
private calculateInvoiceAmount(supplier: BusinessAPI.OrderSupplier): void {
supplier.invoiceAmount = DecimalUtils.multiply(
this.calculateQuoteWeight(supplier),
supplier.purchasePrice || 0,
);
}
/**
*
*/
private calculateBoxWeightByType(
packages: BusinessAPI.OrderPackage[],
boxType?: string,
): number {
const filteredPackages = boxType
? packages.filter((pkg) => pkg.boxType === boxType)
: packages;
return filteredPackages.reduce((total, pkg) => {
const weight = DecimalUtils.multiply(
pkg.boxCount || 0,
pkg.boxProductWeight || 0,
);
return DecimalUtils.add(total, weight);
}, 0);
}
/**
*
*/
getSuppliers(): BusinessAPI.OrderSupplier[] {
return this.suppliers;
}
/**
*
*/
getSupplierNetWeight(supplierId: string | number): number {
const supplier = this.suppliers.find((s) => s.supplierId === supplierId);
return supplier?.netWeight || 0;
}
/**
*
*/
getSupplierGrossWeight(supplierId: string | number): number {
const supplier = this.suppliers.find((s) => s.supplierId === supplierId);
return supplier?.grossWeight || 0;
}
/**
*
*/
getTotalNetWeight(): number {
return this.suppliers.reduce((total, supplier) => {
return DecimalUtils.add(total, supplier.netWeight || 0);
}, 0);
}
/**
*
*/
getTotalGrossWeight(): number {
return this.suppliers.reduce((total, supplier) => {
return DecimalUtils.add(total, supplier.grossWeight || 0);
}, 0);
}
/**
*
*/
getTotalInvoiceAmount(): number {
return this.suppliers.reduce((total, supplier) => {
return DecimalUtils.add(total, supplier.invoiceAmount || 0);
}, 0);
}
/**
*
*/
validate(): { isValid: boolean; errors: string[] } {
const errors: string[] = [];
for (const supplier of this.suppliers) {
if ((supplier.netWeight || 0) < 0) {
errors.push(`供应商 ${supplier.name} 的净重为负数`);
}
if ((supplier.grossWeight || 0) < 0) {
errors.push(`供应商 ${supplier.name} 的毛重为负数`);
}
if ((supplier.grossWeight || 0) < (supplier.netWeight || 0)) {
errors.push(`供应商 ${supplier.name} 的毛重小于净重`);
}
}
return {
isValid: errors.length === 0,
errors,
};
}
}

View File

@ -35,7 +35,10 @@ export class SupplierWeightCalculator {
/**
*
*/
private calculateSupplierWeight(supplier: BusinessAPI.OrderSupplier, index: number): void {
private calculateSupplierWeight(
supplier: BusinessAPI.OrderSupplier,
index: number,
): void {
const isFirstSupplier = index === 0;
const isLastSupplier = supplier.isLast;
@ -43,14 +46,21 @@ export class SupplierWeightCalculator {
this.setEmptyWeight(supplier, index);
// 计算各类纸箱重量
const weights = this.calculateAllBoxWeights(supplier.orderPackageList || []);
const weights = this.calculateAllBoxWeights(
supplier.orderPackageList || [],
);
if (!supplier.isPaper) {
// 不带纸箱包装的简化计算
this.calculateNonPaperSupplier(supplier, weights.used);
} else {
// 纸箱包装的复杂计算
this.calculatePaperSupplier(supplier, weights, isFirstSupplier, isLastSupplier);
this.calculatePaperSupplier(
supplier,
weights,
isFirstSupplier,
isLastSupplier,
);
}
// 计算发票金额
@ -63,7 +73,10 @@ export class SupplierWeightCalculator {
/**
*
*/
private setEmptyWeight(supplier: BusinessAPI.OrderSupplier, index: number): void {
private setEmptyWeight(
supplier: BusinessAPI.OrderSupplier,
index: number,
): void {
if (index === 0) {
// 第一个农户保持原有空磅重量
} else {
@ -87,19 +100,25 @@ export class SupplierWeightCalculator {
/**
*
*/
private calculateNonPaperSupplier(supplier: BusinessAPI.OrderSupplier, usedBoxesWeight: number): void {
if (supplier.type === 'FARMER') {
private calculateNonPaperSupplier(
supplier: BusinessAPI.OrderSupplier,
usedBoxesWeight: number,
): void {
if (supplier.type === "FARMER") {
// 毛重 = (总磅 - 空磅) × 2
supplier.grossWeight = DecimalUtils.multiply(
DecimalUtils.subtract(supplier.totalWeight || 0, supplier.emptyWeight || 0),
2
DecimalUtils.subtract(
supplier.totalWeight || 0,
supplier.emptyWeight || 0,
),
2,
);
}
// 净重 = 毛重 - 使用纸箱重量
supplier.netWeight = DecimalUtils.subtract(
supplier.grossWeight || 0,
usedBoxesWeight
usedBoxesWeight,
);
}
@ -110,11 +129,17 @@ export class SupplierWeightCalculator {
supplier: BusinessAPI.OrderSupplier,
weights: { used: number; extra: number; remain: number; extraUsed: number },
isFirstSupplier: boolean,
isLastSupplier: boolean
isLastSupplier: boolean,
): void {
const weightDiff = isFirstSupplier
? DecimalUtils.subtract(supplier.totalWeight || 0, this.initialEmptyWeight)
: DecimalUtils.subtract(supplier.totalWeight || 0, this.previousTotalWeight);
? DecimalUtils.subtract(
supplier.totalWeight || 0,
this.initialEmptyWeight,
)
: DecimalUtils.subtract(
supplier.totalWeight || 0,
this.previousTotalWeight,
);
const weightDiffInJin = DecimalUtils.multiply(weightDiff, 2);
@ -123,37 +148,46 @@ export class SupplierWeightCalculator {
supplier.netWeight = DecimalUtils.add(
DecimalUtils.subtract(
DecimalUtils.add(weightDiffInJin, weights.remain),
weights.extraUsed
)
weights.extraUsed,
),
);
} else if (isLastSupplier) {
// 最后一个农户
supplier.netWeight = DecimalUtils.add(
DecimalUtils.subtract(
weightDiffInJin,
weights.extraUsed
),
weights.remain
DecimalUtils.subtract(weightDiffInJin, weights.extraUsed),
weights.remain,
);
} else {
// 中间农户(包括第一个但不是最后一个)
supplier.netWeight = DecimalUtils.subtract(weightDiffInJin, weights.extra);
supplier.netWeight = DecimalUtils.subtract(
weightDiffInJin,
weights.extra,
);
}
// 毛重 = 净重 + 本次使用纸箱重量
supplier.grossWeight = DecimalUtils.add(
supplier.netWeight || 0,
weights.used
weights.used,
);
}
/**
*
*/
private calculateQuoteWeight(supplier: BusinessAPI.OrderSupplier): number {
console.log("quote weight:", supplier.pricingMethod);
return supplier.pricingMethod === "BY_GROSS_WEIGHT"
? supplier.grossWeight
: supplier.netWeight;
}
/**
*
*/
private calculateInvoiceAmount(supplier: BusinessAPI.OrderSupplier): void {
supplier.invoiceAmount = DecimalUtils.multiply(
supplier.netWeight || 0,
supplier.purchasePrice || 0
this.calculateQuoteWeight(supplier),
supplier.purchasePrice || 0,
);
}
@ -162,16 +196,16 @@ export class SupplierWeightCalculator {
*/
private calculateBoxWeightByType(
packages: BusinessAPI.OrderPackage[],
boxType?: string
boxType?: string,
): number {
const filteredPackages = boxType
? packages.filter(pkg => pkg.boxType === boxType)
? packages.filter((pkg) => pkg.boxType === boxType)
: packages;
return filteredPackages.reduce((total, pkg) => {
const weight = DecimalUtils.multiply(
pkg.boxCount || 0,
pkg.boxProductWeight || 0
pkg.boxProductWeight || 0,
);
return DecimalUtils.add(total, weight);
}, 0);
@ -188,7 +222,7 @@ export class SupplierWeightCalculator {
*
*/
getSupplierNetWeight(supplierId: string | number): number {
const supplier = this.suppliers.find(s => s.supplierId === supplierId);
const supplier = this.suppliers.find((s) => s.supplierId === supplierId);
return supplier?.netWeight || 0;
}
@ -196,7 +230,7 @@ export class SupplierWeightCalculator {
*
*/
getSupplierGrossWeight(supplierId: string | number): number {
const supplier = this.suppliers.find(s => s.supplierId === supplierId);
const supplier = this.suppliers.find((s) => s.supplierId === supplierId);
return supplier?.grossWeight || 0;
}
@ -247,7 +281,7 @@ export class SupplierWeightCalculator {
return {
isValid: errors.length === 0,
errors
errors,
};
}
}