feat(purchase): 更新采购订单成本计算逻辑
- 更新APP版本号至v0.0.21 - 重构成本项展示逻辑,支持动态渲染orderCostList - 新增多种成本类型展示:公司返点、计提税金、调诚信志远分成 - 修改成本计算方法名:getTotalPackagingCost → getTotalCostItemAmount - 优化成本计算公式,明确区分西瓜采购成本与总采购成本 - 移除冗余的纸箱相关计算方法 - 调整UI布局,改善价格展示区域样式 - 更新利润计算方法:getNetProfit → getShareProfit - 修复人工费工头信息展示逻辑 - 统一成本合计计算入口为getMelonCost1方法
This commit is contained in:
parent
e6a6c3c1c8
commit
8eabf09da5
@ -1,2 +1,2 @@
|
||||
// App 相关常量
|
||||
export const APP_VERSION = "v0.0.20";
|
||||
export const APP_VERSION = "v0.0.21";
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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(
|
||||
|
||||
Loading…
Reference in New Issue
Block a user