feat(purchase): 更新采购订单成本计算逻辑

- 更新APP版本号至v0.0.21
- 重构成本项展示逻辑,支持动态渲染orderCostList
- 新增多种成本类型展示:公司返点、计提税金、调诚信志远分成
- 修改成本计算方法名:getTotalPackagingCost → getTotalCostItemAmount
- 优化成本计算公式,明确区分西瓜采购成本与总采购成本
- 移除冗余的纸箱相关计算方法
- 调整UI布局,改善价格展示区域样式
- 更新利润计算方法:getNetProfit → getShareProfit
- 修复人工费工头信息展示逻辑
- 统一成本合计计算入口为getMelonCost1方法
This commit is contained in:
shenyifei 2025-11-19 17:37:35 +08:00
parent e6a6c3c1c8
commit 8eabf09da5
3 changed files with 105 additions and 210 deletions

View File

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

View File

@ -5,10 +5,7 @@ import { business } from "@/services";
import { useEffect, useState } from "react";
import { View } from "@tarojs/components";
import { SafeArea } from "@nutui/nutui-react-taro";
import {
PurchaseOrderFinalApprove,
PurchaseOrderRejectFinal,
} from "@/components";
import { PurchaseOrderFinalApprove, PurchaseOrderRejectFinal } from "@/components";
import buildUrl from "@/utils/buildUrl";
import { formatCurrency, formatUnitPrice } from "@/utils/format";
import { PurchaseOrderCalculator } from "@/utils/PurchaseOrderCalculator";
@ -53,7 +50,6 @@ export default hocAuth(function Page(props: CommonComponent) {
}
const calculator = new PurchaseOrderCalculator(purchaseOrderVO);
return (
<>
<View
@ -66,7 +62,7 @@ export default hocAuth(function Page(props: CommonComponent) {
<View className="mb-1 text-center text-sm text-gray-500">
</View>
<View className="text-center">
<View className="flex flex-row gap-2.5 text-center">
<View className="price-highlight text-primary">
{formatUnitPrice(calculator.getAveragePurchasePrice())}
</View>
@ -105,57 +101,62 @@ export default hocAuth(function Page(props: CommonComponent) {
</View>
</View>
)}
<View className="cost-item flex flex-col px-3 py-2">
<View className="text-sm text-gray-500"></View>
{purchaseOrderVO.orderCostList.map((item) => {
return (
<View
className="cost-item flex flex-col px-3 py-2"
key={item.itemId}
>
<View className="text-sm text-gray-500">{item.name}</View>
<View className="font-medium">
{calculator.getTrademarkFee()}
{item.price * item.count}
</View>
</View>
<View className="cost-item flex flex-col px-3 py-2">
<View className="text-sm text-gray-500"></View>
<View className="font-medium">{calculator.getNetSetFee()}</View>
</View>
<View className="cost-item flex flex-col px-3 py-2">
<View className="text-sm text-gray-500"></View>
<View className="font-medium">{calculator.getManualFee()}</View>
{item.name === "人工费" && (
<View className="text-xs text-gray-500">
:{purchaseOrderVO.orderCostList[0].principal}
:
{
purchaseOrderVO.orderCostList.filter(
(item) => item.costType === "HUMAN_COST",
)[0].principal
}
</View>
)}
</View>
);
})}
{purchaseOrderVO.orderDealer?.taxSubsidy && (
<View className="cost-item flex flex-col px-3 py-2">
<View className="text-sm text-gray-500"></View>
<View className="font-medium">
{calculator.getTaxProvisionFee()}
</View>
</View>
<View className="cost-item flex flex-col px-3 py-2">
<View className="text-sm text-gray-500"></View>
<View className="font-medium">300</View>
</View>
<View className="cost-item flex flex-col px-3 py-2">
<View className="text-sm text-gray-500"></View>
<View className="font-medium">800</View>
</View>
<View className="cost-item flex flex-col px-3 py-2">
<View className="text-sm text-gray-500"></View>
<View className="font-medium">200</View>
</View>
<View className="cost-item flex flex-col px-3 py-2">
<View className="text-sm text-gray-500"></View>
<View className="text-sm text-gray-500"></View>
<View className="font-medium">
{purchaseOrderVO.orderDealer?.taxSubsidy}
</View>
</View>
)}
{purchaseOrderVO.orderDealer?.taxProvision && (
<View className="cost-item flex flex-col px-3 py-2">
<View className="text-sm text-gray-500"></View>
<View className="font-medium">
{purchaseOrderVO.orderDealer?.taxSubsidy}
{purchaseOrderVO.orderDealer?.taxProvision}
</View>
</View>
)}
{purchaseOrderVO.orderDealer?.costDifference && (
<View className="cost-item flex flex-col px-3 py-2">
<View className="text-sm text-gray-500"></View>
<View className="font-medium">
{purchaseOrderVO.orderDealer?.costDifference}
</View>
</View>
)}
<View className="cost-total col-span-2 grid grid-cols-2 bg-yellow-50 px-3 py-2">
<View className="flex flex-col">
<View className="text-sm text-gray-500"></View>
<View className="font-bold">{calculator.getTotalCost()}</View>
<View className="font-bold">
{calculator.getMelonCost1()}
</View>
</View>
<View className="flex flex-col">
<View className="text-sm text-gray-500"></View>
@ -170,7 +171,7 @@ export default hocAuth(function Page(props: CommonComponent) {
<View className="flex items-center justify-between">
<View className="text-gray-500"></View>
<View className="profit-highlight text-primary text-3xl">
{calculator.getNetProfit()}
{calculator.getShareProfit()}
</View>
</View>
</View>

View File

@ -25,9 +25,9 @@ export class PurchaseOrderCalculator {
}
/**
* = + + + + +
* = + + + + + + + +
*/
getTotalPackagingCost(): number {
getTotalCostItemAmount(): number {
const costItemsCost = this.purchaseOrderVO.orderCostList.reduce(
(sum, cost) => {
// 先过滤一下
@ -55,59 +55,7 @@ export class PurchaseOrderCalculator {
}
/**
* 西1 = +
*/
getMelonCost1(): number {
const totalPurchaseCost = this.getTotalPurchaseCost();
// 计算运费
const deliveryFee = this.purchaseOrderVO.orderDealer?.freightCostFlag
? this.getDeliveryFee()
: 0;
return new Decimal(totalPurchaseCost).plus(deliveryFee).toNumber();
}
/**
* = +
*/
getTotalCost(): number {
// 计算运费
const deliveryFee = this.purchaseOrderVO.orderDealer?.freightCostFlag
? this.getDeliveryFee()
: 0;
return new Decimal(this.getTotalPurchaseCost())
.plus(deliveryFee)
.toNumber();
}
/**
* = + + + + ()
*/
getTotalPurchaseCost(): number {
return new Decimal(this.getSupplierPurchaseCost())
.plus(this.getTotalPackagingCost())
.plus(this.getTaxSubsidy())
.plus(this.getTaxProvision())
.plus(this.getCostDifference())
.toNumber();
}
/**
* = *
*/
getSalesAmount(): number {
// 计算所有供应商的销售金额总和
return this.purchaseOrderVO.orderSupplierList.reduce((sum, supplier) => {
return new Decimal(sum)
.plus(this.calculateSupplierAmount(supplier))
.toNumber();
}, 0);
}
/**
* = (西+) *
* 西 = (西+) *
*/
getSupplierPurchaseCost(): number {
return this.purchaseOrderVO.orderSupplierList.reduce((sum, supplier) => {
@ -136,21 +84,51 @@ export class PurchaseOrderCalculator {
}
/**
* = /
* = 西 + + + +
*
*/
getSingleCost(): string {
return new Decimal(this.getTotalCost())
.div(this.getTotalWeight() || 1)
.toFixed(2);
getTotalPurchaseCost(): number {
return new Decimal(this.getSupplierPurchaseCost())
.plus(this.getTotalCostItemAmount())
.plus(this.getTaxSubsidy())
.plus(this.getTaxProvision())
.plus(this.getCostDifference())
.toNumber();
}
/**
*
* 西1 = +
*/
getBoxProfit(): number {
const boxSale = this.getBoxSale();
const boxCost = this.getBoxCost();
return new Decimal(boxSale).minus(boxCost).toNumber();
getMelonCost1(): number {
const totalPurchaseCost = this.getTotalPurchaseCost();
// 计算运费
const deliveryFee = this.purchaseOrderVO.orderDealer?.freightCostFlag
? this.getDeliveryFee()
: 0;
return new Decimal(totalPurchaseCost).plus(deliveryFee).toNumber();
}
/**
* = *
*/
getSalesAmount(): number {
// 计算所有供应商的销售金额总和
return this.purchaseOrderVO.orderSupplierList.reduce((sum, supplier) => {
return new Decimal(sum)
.plus(this.calculateSupplierAmount(supplier))
.toNumber();
}, 0);
}
/**
* = /
*/
getSingleCost(): string {
return new Decimal(this.getMelonCost1())
.div(this.getTotalWeight() || 1)
.toFixed(2);
}
/**
@ -197,23 +175,6 @@ export class PurchaseOrderCalculator {
}, 0);
}
/**
*
*/
getBoxCost(): number {
return this.purchaseOrderVO.orderSupplierList.reduce((sum, supplier) => {
return new Decimal(sum)
.plus(
supplier.orderPackageList?.reduce((sum, pkg) => {
return new Decimal(sum)
.plus(new Decimal(pkg.boxCount || 0).mul(pkg.boxCostPrice || 0))
.toNumber();
}, 0) || 0,
)
.toNumber();
}, 0);
}
/**
*
*/
@ -373,88 +334,21 @@ export class PurchaseOrderCalculator {
}
/**
* +
* +
*/
getTotalAmount(): number {
const decimal = new Decimal(this.getSalesAmount());
const includePackingFlag =
this.purchaseOrderVO.orderDealer?.includePackingFlag;
if (includePackingFlag) {
return decimal.plus(this.getTotalPackagingCost()).toNumber();
return decimal.plus(this.getTotalCostItemAmount()).toNumber();
}
return decimal.toNumber();
}
/**
*
*/
getTrademarkFee(): number {
return this.purchaseOrderVO.orderCostList
.filter(
(cost) =>
cost.name === "商标" && cost.costType === "PACKAGING_MATERIALS",
)
.reduce(
(sum, cost) =>
new Decimal(sum)
.plus(new Decimal(cost.price).mul(cost.count))
.toNumber(),
0,
);
}
/**
*
*/
getNetSetFee(): number {
return this.purchaseOrderVO.orderCostList
.filter(
(cost) =>
cost.name === "网套" && cost.costType === "PACKAGING_MATERIALS",
)
.reduce(
(sum, cost) =>
new Decimal(sum)
.plus(new Decimal(cost.price).mul(cost.count))
.toNumber(),
0,
);
}
/**
*
*/
getManualFee(): number {
return this.purchaseOrderVO.orderCostList
.filter((cost) => cost.costType === "HUMAN_COST")
.reduce(
(sum, cost) =>
new Decimal(sum)
.plus(new Decimal(cost.price).mul(cost.count))
.toNumber(),
0,
);
}
/**
*
*/
getTaxProvisionFee(): number {
return this.purchaseOrderVO.orderCostList
.filter(
(cost) => cost.costType === "FIXED_COST" && cost.name === "计提费",
)
.reduce(
(sum, cost) =>
new Decimal(sum)
.plus(new Decimal(cost.price).mul(cost.count))
.toNumber(),
0,
);
}
/**
*
*/
@ -475,7 +369,7 @@ export class PurchaseOrderCalculator {
/**
*
*/
getDefaultTaxProvision() {
getDefaultTaxProvision(): number {
if (this.purchaseOrderVO.orderDealer?.accrualTaxRatio) {
const totalAmount = this.getTotalAmount();
const taxSubsidyValue = this.purchaseOrderVO.orderDealer?.taxSubsidy || 0;
@ -492,9 +386,9 @@ export class PurchaseOrderCalculator {
/**
*
*/
getDefaultTaxSubsidy() {
getDefaultTaxSubsidy(): number {
if (this.purchaseOrderVO.orderDealer?.companyRebateRatio) {
const totalPackagingCost = this.getTotalPackagingCost();
const totalPackagingCost = this.getTotalCostItemAmount();
const salesAmount1 = this.getSalesAmount();
return new Decimal(salesAmount1)
@ -508,7 +402,7 @@ export class PurchaseOrderCalculator {
/**
*
*/
getBoxCount() {
getBoxCount(): number {
return this.purchaseOrderVO.orderSupplierList.reduce((sum, supplier) => {
return new Decimal(sum)
.plus(
@ -523,7 +417,7 @@ export class PurchaseOrderCalculator {
/**
*
*/
getBoxWeight() {
getBoxWeight(): number {
return this.purchaseOrderVO.orderSupplierList.reduce((sum, supplier) => {
return new Decimal(sum)
.plus(