feat(purchase): 优化采购订单成本计算逻辑

- 新增 `belong` 字段以支持成本归属区分
- 修改运费类型从 OTHER_TYPE 转为 LOGISTICS_TYPE,并细化为主运费与短驳费
- 调整草帘费、付瓜农定金的处理方式,增强类型校验
- 重构损耗金额计算方法并整合进成本计算器
- 更新订单成本项筛选条件,排除特定费用如“付瓜农定金”
- 增强角色权限控制及页面跳转逻辑,适配多角色入口
- 修复成本列表初始化和匹配逻辑,确保数据一致性
- 调整 UI 显示文本,例如将“公司返点”改为“损耗金额”
- 导入新增的 orderCost 模块用于订单成本接口请求
- 类型定义调整,统一使用字符串数组代替数字数组
- 修正部分组件中不必要的 useEffect 和状态初始化逻辑
This commit is contained in:
shenyifei 2025-12-17 12:02:32 +08:00
parent 72a0e06da6
commit ab1c16f283
20 changed files with 535 additions and 248 deletions

View File

@ -141,9 +141,9 @@ export default function CostCreate(props: AddCostComponentProps) {
price: amount || 0,
unit: selectedCost.unit || "元",
count: 1, // 总数为1因为我们将所有费用项目合并到一个OrderCost中
costItemIds: selectedItems.map((item) => item.costItemId),
costItemIds: selectedItems.map((item) => item.costItemId) || [],
type: type,
principal: "",
belong: selectedCost.belong,
selected: true,
};

View File

@ -159,8 +159,11 @@ export default function CostList(props: {
if (
orderCost.name === "空箱费" ||
orderCost.name === "纸箱费" ||
orderCost.name === "运费" ||
orderCost.name === "草帘费"
orderCost.name === "主运费" ||
orderCost.name === "短驳费" ||
orderCost.name === "付瓜农定金" ||
(orderCost.name === "草帘费" &&
orderCost.type === "LOGISTICS_TYPE")
) {
return <></>;
}

View File

@ -62,6 +62,7 @@ export default forwardRef<OrderCostRef, IOrderCostProps>(
count: 1,
price: item.price || 0,
unit: item.unit || "元",
belong: item.belong,
});
orderCostMap.set(item.costId, {
@ -74,6 +75,7 @@ export default forwardRef<OrderCostRef, IOrderCostProps>(
count: 1,
price: item.price || 0,
unit: item.unit || "元",
belong: item.belong,
});
}
});
@ -100,6 +102,7 @@ export default forwardRef<OrderCostRef, IOrderCostProps>(
count: 1,
price: item.price || 0,
unit: item.unit || "元",
belong: item.belong,
});
}
});

View File

@ -17,6 +17,7 @@ import { Icon } from "@/components";
export default function BasicInfoSection(props: {
purchaseOrderVO: BusinessAPI.PurchaseOrderVO;
onChange?: (purchaseOrderVO: BusinessAPI.PurchaseOrderVO) => void;
costList: BusinessAPI.CostVO[];
readOnly?: boolean;
}) {
const { purchaseOrderVO, onChange, readOnly } = props;
@ -28,6 +29,16 @@ export default function BasicInfoSection(props: {
const endDate = new Date(startDate.getTime() + 86400000 * 10);
const [show, setShow] = useState(false);
// 主运费
const mainCost = props.costList.find(
(cost) => cost.type === "LOGISTICS_TYPE" && cost.name === "主运费",
);
// 短驳费
const shortCost = props.costList.find(
(cost) => cost.type === "LOGISTICS_TYPE" && cost.name === "短驳费",
);
const formatter = (type: string, option: PickerOption) => {
switch (type) {
case "year":
@ -185,6 +196,38 @@ export default function BasicInfoSection(props: {
...orderVehicle,
priceType: value,
},
orderCostList: purchaseOrderVO.orderCostList.map((orderCost) => {
if (orderCost.type === "LOGISTICS_TYPE") {
if (
orderCost.name === "短驳费" &&
value === "MAIN_FREIGHT" &&
mainCost
) {
return {
...orderCost,
costId: mainCost.costId,
name: mainCost.name,
belong: mainCost.belong,
unit: mainCost.unit || orderCost.unit || "元",
};
}
if (
orderCost.name === "主运费" &&
value === "SHORT_TRANSPORT" &&
shortCost
) {
return {
...orderCost,
costId: shortCost.costId,
name: shortCost.name,
belong: shortCost.belong,
unit: shortCost.unit || orderCost.unit || "元",
};
}
}
return orderCost;
}),
};
onChange(updatedOrder);
}

View File

@ -1,4 +1,3 @@
import { useEffect } from "react";
import { Text, View } from "@tarojs/components";
import { PurchaseOrderCalculator } from "@/utils";
import { PriceEditor } from "@/components";
@ -12,24 +11,6 @@ export default function ProductionLossSection(props: {
const { purchaseOrderVO, onChange, readOnly, calculator } = props;
const orderDealer = purchaseOrderVO.orderDealer;
// 主状态 - 用于显示在页面上的值
const displayLossAmount =
orderDealer?.lossAmount || calculator.getDefaultLossAmount();
useEffect(() => {
if (!orderDealer?.lossAmount) {
const defaultValue = calculator.getDefaultLossAmount();
// 更新父组件的状态
onChange?.({
...purchaseOrderVO,
orderDealer: {
...orderDealer,
lossAmount: defaultValue,
},
});
}
}, []);
return (
<View className={"flex flex-col gap-2.5"}>
{/* 卡片形式展示返点信息 */}
@ -40,7 +21,12 @@ export default function ProductionLossSection(props: {
<View className="flex">
<PriceEditor
value={displayLossAmount}
value={
orderDealer.lossAmount === null ||
orderDealer.lossAmount === undefined
? calculator.getLossAmount()
: orderDealer.lossAmount
}
onSave={(newValue) => {
// 更新父组件的状态
onChange?.({

View File

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

View File

@ -186,7 +186,7 @@ const quickActionMap = {
icon: "print",
iconColor: "var(--color-yellow-600)",
bgColorClass: "bg-yellow-100",
path: "/pages/delivery/list",
path: "/pages/delivery/all",
},
// {
// id: "dailyExpense",
@ -240,7 +240,7 @@ const quickActionMap = {
icon: "print",
iconColor: "var(--color-yellow-600)",
bgColorClass: "bg-yellow-100",
path: "/pages/delivery/list",
path: "/pages/delivery/all",
},
// {
// id: "dailyExpense",

View File

@ -176,6 +176,8 @@ export default hocAuth(function Page(props: CommonComponent) {
</View>
<View className={"py-2.5"}>
<View className={"flex flex-row justify-end gap-2"}>
{shipOrderVO.state !== "DRAFT" &&
shipOrderVO.state !== "WAIT_SHIPMENT" && (
<Button
type={"primary"}
size={"small"}
@ -192,6 +194,7 @@ export default hocAuth(function Page(props: CommonComponent) {
>
</Button>
)}
</View>
</View>
</View>

View File

@ -31,18 +31,23 @@ export default hocAuth(function Page(props: CommonComponent) {
};
const init = async (user: AuthAPI.UserVO) => {
let platformId = "1991353387274342401";
const {
data: { data: employeeVO },
} = await auth.user.userEmployee({
employeeShowQry: {
userId: user.userId,
platformId: "1991353387274342401",
platformId: platformId,
},
});
if (employeeVO) {
setEmployeeVO(employeeVO);
setUserRoleVOList(employeeVO.userRoleList);
setUserRoleVOList(
employeeVO.userRoleList?.filter(
(item) => item.platformId === platformId,
),
);
let userRoleVO = Taro.getStorageSync("userRoleVO");
if (!userRoleVO) {

View File

@ -54,6 +54,9 @@ export default hocAuth(function Page(props: CommonComponent) {
let totalCost: number;
const totalWeight = calculator.getTotalWeight();
const shouldIncludeFreightCost = calculator
.getRules()
.shouldIncludeFreightCost();
// 判断采购成本是否包含运费,包含运费说明已经加过一次了
if (calculator.getRules().shouldIncludeFreightCost()) {
@ -112,9 +115,14 @@ export default hocAuth(function Page(props: CommonComponent) {
{formatCurrency(calculator.getSupplierPurchaseCost())}
</View>
</View>
{purchaseOrderVO.orderCostList.map((item) => {
{purchaseOrderVO.orderCostList
.filter((item) => {
return (
item.price * item.count > 0 && item.name !== "付瓜农定金"
);
})
.map((item) => {
return (
item.price * item.count > 0 && (
<View
className="cost-item flex flex-col px-3 py-2"
key={item.costId}
@ -130,14 +138,14 @@ export default hocAuth(function Page(props: CommonComponent) {
</View>
)}
</View>
)
);
})}
{purchaseOrderVO.orderDealer?.taxSubsidy && (
{purchaseOrderVO.orderDealer?.enableLoss && (
<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}
{purchaseOrderVO.orderDealer?.lossAmount}
</View>
</View>
)}
@ -151,6 +159,15 @@ export default hocAuth(function Page(props: CommonComponent) {
</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">
{purchaseOrderVO.orderDealer?.taxSubsidy}
</View>
</View>
)}
{purchaseOrderVO.orderDealer?.costDifference && (
<View className="cost-item flex flex-col px-3 py-2">
<View className="text-sm text-gray-500"></View>
@ -162,7 +179,10 @@ export default hocAuth(function Page(props: CommonComponent) {
<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="text-sm text-gray-500">
{shouldIncludeFreightCost ? "包含运费" : "不包含运费"}
</View>
<View className="font-bold">{totalCost} </View>
</View>
<View className="flex flex-col">

View File

@ -559,22 +559,6 @@ export default hocAuth(function Page(props: CommonComponent) {
return item;
});
// 计提费
const orderCost = purchaseOrderVO?.orderCostList.find(
(item) => item.name === "计提费" && item.type === "OTHER_TYPE",
);
if (orderCost) {
await business.cost
.listCost({
costListQry: {
status: true,
},
})
.then(({ data: { data: costList } }) => {
setCostList(costList || []);
});
} else {
const {
data: { data: costList },
} = await business.cost.listCost({
@ -585,60 +569,99 @@ export default hocAuth(function Page(props: CommonComponent) {
setCostList(costList || []);
const cost = costList?.find(
const cost1 = costList?.find(
(cost) => cost.name === "计提费" && cost.type === "OTHER_TYPE",
);
const orderCost1 = purchaseOrderVO?.orderCostList?.find(
(cost) => cost.name === "计提费" && cost.type === "OTHER_TYPE",
);
if (cost) {
if (!orderCost1 && cost1) {
purchaseOrderVO.orderCostList.push({
orderCostId: generateShortId(),
costId: cost.costId || "",
name: cost.name || "",
price: cost.price || 0,
unit: cost.unit || "元",
costId: cost1.costId || "",
name: cost1.name || "",
price: cost1.price || 0,
unit: cost1.unit || "元",
count: 1,
type: "OTHER_TYPE",
costItemIds: [],
principal: "",
belong: cost1.belong,
selected: true,
});
}
}
const cost1 = purchaseOrderVO?.orderCostList?.find(
(cost) => cost.name === "运费" && cost.type === "OTHER_TYPE",
const costName =
purchaseOrderVO?.orderVehicle.priceType === "SHORT_TRANSPORT"
? "短驳费"
: "主运费";
const cost2 = costList?.find(
(cost) => cost.name === costName && cost.type === "LOGISTICS_TYPE",
);
const orderCost2 = purchaseOrderVO?.orderCostList?.find(
(cost) => cost.name === costName && cost.type === "LOGISTICS_TYPE",
);
// 加运费
if (purchaseOrderVO.orderVehicle.price && !cost1) {
if (purchaseOrderVO.orderVehicle.price && !orderCost2 && cost2) {
purchaseOrderVO.orderCostList.push({
orderCostId: generateShortId(),
costId: "",
name: "运费",
costId: cost2.costId || "",
name: cost2.name || "",
price: purchaseOrderVO.orderVehicle.price,
unit: "元",
unit: cost2.unit || "元",
count: 1,
type: "OTHER_TYPE",
type: "LOGISTICS_TYPE",
costItemIds: [],
principal: "",
belong: cost2.belong,
selected: true,
});
}
const cost2 = purchaseOrderVO?.orderCostList?.find(
(cost) => cost.name === "草帘费" && cost.type === "OTHER_TYPE",
const cost3 = costList?.find(
(cost) => cost.name === "草帘费" && cost.type === "LOGISTICS_TYPE",
);
const orderCost3 = purchaseOrderVO?.orderCostList?.find(
(cost) => cost.name === "草帘费" && cost.type === "LOGISTICS_TYPE",
);
// 加草帘
if (purchaseOrderVO.orderVehicle.openStrawCurtain && !cost2) {
if (
purchaseOrderVO.orderVehicle.openStrawCurtain &&
!orderCost3 &&
cost3
) {
purchaseOrderVO.orderCostList.push({
orderCostId: generateShortId(),
costId: "",
name: "草帘费",
costId: cost3.costId || "",
name: cost3.name || "",
price: purchaseOrderVO.orderVehicle.strawCurtainPrice!,
unit: "元",
unit: cost3.unit || "元",
count: 1,
type: "OTHER_TYPE",
type: "LOGISTICS_TYPE",
costItemIds: [],
principal: "",
belong: cost3.belong,
selected: true,
});
}
const cost4 = costList?.find(
(cost) => cost.name === "付瓜农定金" && cost.type === "PRODUCTION_TYPE",
);
const orderCost4 = purchaseOrderVO?.orderCostList?.find(
(cost) => cost.name === "付瓜农定金" && cost.type === "PRODUCTION_TYPE",
);
if (!orderCost4 && cost4) {
const calculator = new PurchaseOrderCalculator(purchaseOrderVO);
purchaseOrderVO.orderCostList.push({
orderCostId: generateShortId(),
costId: cost4.costId || "",
name: cost4.name || "",
price: calculator.getDepositAmount(),
unit: cost4.unit || "元",
count: 1,
type: "PRODUCTION_TYPE",
costItemIds: [],
belong: cost4.belong,
selected: true,
});
}

View File

@ -117,9 +117,9 @@ export default hocAuth(function Page(props: CommonComponent) {
// 如果订单状态不是草稿,则跳转到预览页面
if (
purchaseOrder.state !== "DRAFT" &&
purchaseOrder.state !== "REJECTED" &&
userRoleVO.slug === "origin-entry"
purchaseOrder.state !== "REJECTED"
) {
if (userRoleVO.slug === "origin-entry") {
Taro.redirectTo({
url: buildUrl("/pages/purchase/enter/preview", {
orderId: purchaseOrder.orderId,
@ -127,6 +127,23 @@ export default hocAuth(function Page(props: CommonComponent) {
});
return;
}
if (userRoleVO.slug === "reviewer") {
Taro.redirectTo({
url: buildUrl("/pages/purchase/audit/audit", {
orderId: purchaseOrder.orderId,
}),
});
return;
}
if (userRoleVO.slug === "boss") {
Taro.redirectTo({
url: buildUrl("/pages/purchase/approval/audit", {
orderId: purchaseOrder.orderId,
}),
});
return;
}
}
setPurchaseOrder(purchaseOrder);
const orderSupplierList1 = purchaseOrder.orderSupplierList as any;
@ -158,6 +175,20 @@ export default hocAuth(function Page(props: CommonComponent) {
...purchaseOrder,
active,
orderSupplierList: orderSupplierList1,
orderCostList: purchaseOrder.orderCostList?.map((item) => {
return {
...item,
selected: true,
};
}),
orderCostItemList: purchaseOrder.orderCostItemList?.map(
(item) => {
return {
...item,
selected: true,
};
},
),
});
}
})

View File

@ -100,7 +100,7 @@ declare namespace AuthAPI {
/** 用户ID */
userId: string;
/** 角色ID */
roleIdList: number[];
roleIdList: string[];
/** 角色信息 */
userRoleList?: UserRoleVO[];
};
@ -195,7 +195,7 @@ declare namespace AuthAPI {
type RoleMenuTreeQry = {
/** 角色权限 */
roleId?: number[];
roleId?: string[];
/** 平台ID */
platformId: string;
};
@ -329,7 +329,7 @@ declare namespace AuthAPI {
/** 备注 */
remark?: string;
/** 客户标签 */
labelId?: number[];
labelId?: string[];
/** 用户ID */
userId: string;
};

View File

@ -32,6 +32,7 @@ import * as agreement from "./agreement";
import * as role from "./role";
import * as permission from "./permission";
import * as extraction from "./extraction";
import * as orderCost from "./orderCost";
export default {
user,
@ -64,4 +65,5 @@ export default {
role,
permission,
extraction,
orderCost,
};

View File

@ -0,0 +1,23 @@
// @ts-ignore
/* eslint-disable */
import request from "../request";
/** 订单成本项列表 GET /operation/pageOrderCost */
export async function pageOrderCost(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: BusinessAPI.pageOrderCostParams,
options?: { [key: string]: any },
) {
return request<BusinessAPI.PageResponseOrderCostVO>(
"/operation/pageOrderCost",
{
method: "GET",
params: {
...params,
orderCostPageQry: undefined,
...params["orderCostPageQry"],
},
...(options || {}),
},
);
}

View File

@ -104,7 +104,7 @@ declare namespace BusinessAPI {
/** 品牌图片URL */
image?: string;
/** 纸箱规格ID */
specIds?: number[];
specIds?: string[];
/** 备注 */
remark?: string;
/** 状态1_启用0_禁用 */
@ -175,7 +175,7 @@ declare namespace BusinessAPI {
/** 品牌图片URL */
image?: string;
/** 纸箱规格ID */
specIds?: number[];
specIds?: string[];
/** 备注 */
remark?: string;
/** 状态1_启用0_禁用 */
@ -192,7 +192,7 @@ declare namespace BusinessAPI {
/** 品牌图片URL */
image?: string;
/** 纸箱规格ID */
specIds?: number[];
specIds?: string[];
/** 备注 */
remark?: string;
/** 状态1_启用0_禁用 */
@ -892,14 +892,15 @@ declare namespace BusinessAPI {
type CostCreateCmd = {
/** 费用ID */
costId: string;
/** 费用类型1_辅料类型2_人工类型3_产地类型4_其他类型 */
/** 费用类型1_辅料类型2_人工类型3_产地类型4_其他类型5_物流类型 */
type:
| "MATERIAL_TYPE"
| "ARTIFICIAL_TYPE"
| "PRODUCTION_TYPE"
| "OTHER_TYPE";
/** 费用归属1_工头2_产地 */
belong: "NONE_TYPE" | "WORKER_TYPE" | "PRODUCTION_TYPE";
| "OTHER_TYPE"
| "LOGISTICS_TYPE";
/** 费用归属0_无归属1_工头2_产地3_司机 */
belong: "NONE_TYPE" | "WORKER_TYPE" | "PRODUCTION_TYPE" | "DRIVER_TYPE";
/** 费用名称 */
name: string;
/** 单价 */
@ -913,7 +914,7 @@ declare namespace BusinessAPI {
/** 状态1_启用0_禁用 */
status: boolean;
/** 成本项ID */
costItemIds?: number[];
costItemIds?: string[];
};
type CostDestroyCmd = {
@ -1054,14 +1055,15 @@ declare namespace BusinessAPI {
status?: boolean;
/** 费用ID */
costId?: string;
/** 费用类型1_辅料类型2_人工类型3_产地类型4_其他类型 */
/** 费用类型1_辅料类型2_人工类型3_产地类型4_其他类型5_物流类型 */
type?:
| "MATERIAL_TYPE"
| "ARTIFICIAL_TYPE"
| "PRODUCTION_TYPE"
| "OTHER_TYPE";
/** 费用归属1_工头2_产地 */
belong?: "NONE_TYPE" | "WORKER_TYPE" | "PRODUCTION_TYPE";
| "OTHER_TYPE"
| "LOGISTICS_TYPE";
/** 费用归属0_无归属1_工头2_产地3_司机 */
belong?: "NONE_TYPE" | "WORKER_TYPE" | "PRODUCTION_TYPE" | "DRIVER_TYPE";
};
type CostPageQry = {
@ -1081,14 +1083,15 @@ declare namespace BusinessAPI {
status?: boolean;
/** 费用ID */
costId?: string;
/** 费用类型1_辅料类型2_人工类型3_产地类型4_其他类型 */
/** 费用类型1_辅料类型2_人工类型3_产地类型4_其他类型5_物流类型 */
type?:
| "MATERIAL_TYPE"
| "ARTIFICIAL_TYPE"
| "PRODUCTION_TYPE"
| "OTHER_TYPE";
/** 费用归属1_工头2_产地 */
belong?: "NONE_TYPE" | "WORKER_TYPE" | "PRODUCTION_TYPE";
| "OTHER_TYPE"
| "LOGISTICS_TYPE";
/** 费用归属0_无归属1_工头2_产地3_司机 */
belong?: "NONE_TYPE" | "WORKER_TYPE" | "PRODUCTION_TYPE" | "DRIVER_TYPE";
offset?: number;
};
@ -1102,14 +1105,15 @@ declare namespace BusinessAPI {
type CostUpdateCmd = {
/** 费用ID */
costId: string;
/** 费用类型1_辅料类型2_人工类型3_产地类型4_其他类型 */
/** 费用类型1_辅料类型2_人工类型3_产地类型4_其他类型5_物流类型 */
type:
| "MATERIAL_TYPE"
| "ARTIFICIAL_TYPE"
| "PRODUCTION_TYPE"
| "OTHER_TYPE";
/** 费用归属1_工头2_产地 */
belong: "NONE_TYPE" | "WORKER_TYPE" | "PRODUCTION_TYPE";
| "OTHER_TYPE"
| "LOGISTICS_TYPE";
/** 费用归属0_无归属1_工头2_产地3_司机 */
belong: "NONE_TYPE" | "WORKER_TYPE" | "PRODUCTION_TYPE" | "DRIVER_TYPE";
/** 费用名称 */
name: string;
/** 单价 */
@ -1123,7 +1127,7 @@ declare namespace BusinessAPI {
/** 状态1_启用0_禁用 */
status: boolean;
/** 成本项ID */
costItemIds?: number[];
costItemIds?: string[];
};
type CostVO = {
@ -1134,9 +1138,10 @@ declare namespace BusinessAPI {
| "MATERIAL_TYPE"
| "ARTIFICIAL_TYPE"
| "PRODUCTION_TYPE"
| "OTHER_TYPE";
/** 费用归属1_工头2_产地 */
belong: "NONE_TYPE" | "WORKER_TYPE" | "PRODUCTION_TYPE";
| "OTHER_TYPE"
| "LOGISTICS_TYPE";
/** 费用归属0_无归属1_工头2_产地3_司机 */
belong: "NONE_TYPE" | "WORKER_TYPE" | "PRODUCTION_TYPE" | "DRIVER_TYPE";
/** 费用名称 */
name: string;
/** 单价 */
@ -1150,7 +1155,7 @@ declare namespace BusinessAPI {
/** 状态1_启用0_禁用 */
status: boolean;
/** 项目id集合 */
costItemIds?: number[];
costItemIds?: string[];
/** 创建时间 */
createdAt?: string;
/** 项目列表 */
@ -1214,6 +1219,10 @@ declare namespace BusinessAPI {
companyRebateRatio?: number;
/** 是否可调整比例 */
shareAdjusted?: boolean;
/** 是否开启损耗 */
enableLoss?: boolean;
/** 损耗金额 */
lossAmount?: number;
};
type DealerDestroyCmd = {
@ -1532,6 +1541,10 @@ declare namespace BusinessAPI {
companyRebateRatio?: number;
/** 是否可调整比例 */
shareAdjusted?: boolean;
/** 是否开启损耗 */
enableLoss?: boolean;
/** 损耗金额 */
lossAmount?: number;
/** 发货单模板 */
deliveryTemplate?: string;
};
@ -1577,6 +1590,10 @@ declare namespace BusinessAPI {
companyRebateRatio?: number;
/** 是否可调整比例 */
shareAdjusted?: boolean;
/** 是否开启损耗 */
enableLoss?: boolean;
/** 损耗金额 */
lossAmount?: number;
};
type DealerWarehouseCreateCmd = {
@ -1819,7 +1836,7 @@ declare namespace BusinessAPI {
/** 登录密码 */
password: string;
/** 角色ID */
roleId: number[];
roleId: string[];
};
type EmployeeDestroyCmd = {
@ -1912,7 +1929,7 @@ declare namespace BusinessAPI {
/** 用户ID */
userId: string;
/** 角色ID */
roleIdList: number[];
roleIdList: string[];
/** 角色信息 */
userRoleList?: UserRoleVO[];
};
@ -2238,7 +2255,7 @@ declare namespace BusinessAPI {
/** 平台id */
platformId: string;
/** 角色Id */
roleId?: number[];
roleId?: string[];
/** 是否隐藏 */
hideInMenu?: boolean;
/** 权限Id */
@ -2311,7 +2328,7 @@ declare namespace BusinessAPI {
/** 平台id */
platformId: string;
/** 角色Id */
roleId?: number[];
roleId?: string[];
/** 是否隐藏 */
hideInMenu?: boolean;
/** 权限Id */
@ -2639,18 +2656,19 @@ declare namespace BusinessAPI {
unit: string;
/** 数量 */
count: number;
/** 费用归属:1_工头2_产地 */
belong?: "NONE_TYPE" | "WORKER_TYPE" | "PRODUCTION_TYPE";
/** 费用归属:0_无归属1_工头2_产地3_司机 */
belong?: "NONE_TYPE" | "WORKER_TYPE" | "PRODUCTION_TYPE" | "DRIVER_TYPE";
/** 负责人 */
principal?: string;
/** 费用类型1_辅料类型2_人工类型3_产地类型4_其他类型 */
/** 费用类型1_辅料类型2_人工类型3_产地类型4_其他类型5_物流类型 */
type:
| "MATERIAL_TYPE"
| "ARTIFICIAL_TYPE"
| "PRODUCTION_TYPE"
| "OTHER_TYPE";
| "OTHER_TYPE"
| "LOGISTICS_TYPE";
/** 关联项目id */
costItemIds?: number[];
costItemIds?: string[];
/** 是否选中 */
selected: boolean;
};
@ -2680,6 +2698,82 @@ declare namespace BusinessAPI {
selected: boolean;
};
type OrderCostPageQry = {
pageSize?: number;
pageIndex?: number;
orderBy?: string;
orderDirection?: string;
groupBy?: string;
needTotalCount?: boolean;
/** 自定义字段key */
customFieldKey?: string;
/** 自定义字段value */
customFieldValue?: string;
/** 备注 */
remark?: string;
/** 状态1_启用0_禁用 */
status?: boolean;
/** 订单ID */
orderId?: string;
/** 订单ID */
costId?: string;
/** 供应商id */
supplierId?: string;
/** 订单状态 */
poStates?: (
| "DRAFT"
| "WAITING_AUDIT"
| "COMPLETED"
| "REJECTED"
| "CLOSED"
)[];
/** 是否支付 */
isPaid?: boolean;
offset?: number;
};
type OrderCostVO = {
/** 记录ID */
orderCostId: string;
/** 订单ID */
orderId?: string;
/** 费用Id */
costId: string;
/** 成本项目名称 */
name: string;
/** 单价 */
price: number;
/** 单位 */
unit: string;
/** 数量 */
count: number;
/** 费用归属0_无归属1_工头2_产地3_司机 */
belong?: "NONE_TYPE" | "WORKER_TYPE" | "PRODUCTION_TYPE" | "DRIVER_TYPE";
/** 负责人 */
principal?: string;
/** 费用类型1_辅料类型2_人工类型3_产地类型4_其他类型5_物流类型 */
type:
| "MATERIAL_TYPE"
| "ARTIFICIAL_TYPE"
| "PRODUCTION_TYPE"
| "OTHER_TYPE"
| "LOGISTICS_TYPE";
/** 关联项目id */
costItemIds?: string[];
/** 创建时间 */
createdAt: string;
/** 车辆信息 */
orderVehicle: OrderVehicle;
/** 采购订单状态: 0_草稿1_审核中2_已完成3_已驳回4_已关闭 */
poState?: "DRAFT" | "WAITING_AUDIT" | "COMPLETED" | "REJECTED" | "CLOSED";
/** 公司信息 */
orderCompany: OrderCompany;
/** 采购订单信息 */
purchaseOrderVO: PurchaseOrderVO;
/** 是否付款 */
isPaid?: boolean;
};
type OrderDealer = {
/** 记录ID */
orderDealerId?: string;
@ -3102,26 +3196,32 @@ declare namespace BusinessAPI {
/** 产品名称 */
productName?: string;
/** 关联费用id */
costIds?: number[];
costIds?: string[];
/** 成本模板 */
costTemplate?: string;
/** 是否已付定金 */
isDepositPaid?: boolean;
/** 定金金额 */
depositAmount?: number;
/** 是否付款 */
isPaid?: boolean;
/** 采购订单包装箱信息 */
orderPackageList?: OrderPackage[];
/** 采购订单车辆信息 */
orderVehicle?: OrderVehicle;
/** 采购订单公司信息 */
orderCompany?: OrderCompany;
/** 是否选中 */
selected: boolean;
/** 采购订单状态: 0_草稿1_审核中2_已完成3_已驳回4_已关闭 */
poState?: "DRAFT" | "WAITING_AUDIT" | "COMPLETED" | "REJECTED" | "CLOSED";
/** 创建时间 */
createdAt?: string;
};
type OrderSupplierBatchInvoiceUploadCmd = {
/** 供应商ID列表 */
orderSupplierIdList: number[];
orderSupplierIdList: string[];
/** 是否上传票证 */
invoiceUpload?: boolean;
/** 发票照片 */
@ -3161,6 +3261,8 @@ declare namespace BusinessAPI {
| "REJECTED"
| "CLOSED"
)[];
/** 是否支付 */
isPaid?: boolean;
offset?: number;
};
@ -3179,6 +3281,8 @@ declare namespace BusinessAPI {
isDepositPaid?: boolean;
/** 定金金额 */
depositAmount?: number;
/** 是否付款 */
isPaid?: boolean;
/** 装车模式 1_搭架子+网垫2_纸箱+胶带+木隔板 */
loadingMode?: "FRAME_WITH_NET" | "BOX_WITH_TAPE";
};
@ -3189,65 +3293,71 @@ declare namespace BusinessAPI {
/** 订单ID */
orderId: string;
/** 供应商ID */
supplierId?: string;
supplierId: string;
/** 供应商姓名 */
name?: string;
name: string;
/** 身份证号 */
idCard?: string;
idCard: string;
/** 银行卡号 */
bankCard?: string;
bankCard: string;
/** 手机号 */
phone?: string;
phone: string;
/** 微信二维码 */
wechatQr?: string;
wechatQr: string;
/** 是否最后一家 */
isLast?: boolean;
isLast: boolean;
/** 空磅是否包含纸箱 */
isPaper?: boolean;
isPaper: boolean;
/** 产品id */
productId?: string;
productId: string;
/** 产品名称 */
productName?: string;
/** 装车模式 1_搭架子+网垫2_纸箱+胶带+木隔板 */
loadingMode?: "FRAME_WITH_NET" | "BOX_WITH_TAPE";
productName: string;
/** 装车模式1_搭架子+网垫2_纸箱+胶带+木隔板 */
loadingMode: "FRAME_WITH_NET" | "BOX_WITH_TAPE";
/** 空车重量(kg) */
emptyWeight?: number;
emptyWeight: number;
/** 总重量(kg) */
totalWeight?: number;
totalWeight: number;
/** 毛重(斤) */
grossWeight?: number;
grossWeight: number;
/** 净重(斤) */
netWeight?: number;
netWeight: number;
/** 采购单价(元&#x2F;斤) */
purchasePrice?: number;
purchasePrice: number;
/** 销售单价(元&#x2F;斤) */
salePrice?: number;
salePrice: number;
/** 报价方式1_按毛重报价2_按净重报价 */
pricingMethod?: boolean;
pricingMethod: "BY_GROSS_WEIGHT" | "BY_NET_WEIGHT";
/** 发票金额 */
invoiceAmount?: number;
invoiceAmount: number;
/** 是否已付定金 */
isDepositPaid?: boolean;
isDepositPaid: boolean;
/** 定金金额 */
depositAmount?: number;
depositAmount: number;
/** 是否付款 */
isPaid: boolean;
/** 空车照片 */
emptyWeightImg?: string;
emptyWeightImg: string;
/** 满载照片 */
totalWeightImg?: string;
totalWeightImg: string;
/** 是否上传票证 */
invoiceUpload?: boolean;
invoiceUpload: boolean;
/** 发票照片 */
invoiceImg?: UploadFileItem[];
invoiceImg: UploadFileItem[];
/** 是否上传合同 */
contractUpload?: boolean;
contractUpload: boolean;
/** 合同照片 */
contractImg?: UploadFileItem[];
contractImg: UploadFileItem[];
/** 创建时间 */
createdAt?: string;
createdAt: string;
/** 车辆信息 */
orderVehicle?: OrderVehicle;
orderVehicle: OrderVehicle;
/** 采购订单状态: 0_草稿1_审核中2_已完成3_已驳回4_已关闭 */
poState?: "DRAFT" | "WAITING_AUDIT" | "COMPLETED" | "REJECTED" | "CLOSED";
/** 公司信息 */
orderCompany: OrderCompany;
/** 采购订单信息 */
purchaseOrderVO: PurchaseOrderVO;
};
type OrderVehicle = {
@ -3360,6 +3470,10 @@ declare namespace BusinessAPI {
materialPageQry: MaterialPageQry;
};
type pageOrderCostParams = {
orderCostPageQry: OrderCostPageQry;
};
type pageOrderShipParams = {
orderShipPageQry: OrderShipPageQry;
};
@ -3605,6 +3719,19 @@ declare namespace BusinessAPI {
totalPages?: number;
};
type PageResponseOrderCostVO = {
success?: boolean;
errCode?: string;
errMessage?: string;
totalCount?: number;
pageSize?: number;
pageIndex?: number;
data?: OrderCostVO[];
empty?: boolean;
notEmpty?: boolean;
totalPages?: number;
};
type PageResponseOrderShipVO = {
success?: boolean;
errCode?: string;
@ -3840,7 +3967,7 @@ declare namespace BusinessAPI {
/** 产品名称 */
name: string;
/** 关联成本费用id */
costIds?: number[];
costIds?: string[];
/** 成本模板 */
costTemplate?: string;
/** 备注 */
@ -3907,7 +4034,7 @@ declare namespace BusinessAPI {
/** 产品名称 */
name: string;
/** 关联成本费用id */
costIds?: number[];
costIds?: string[];
/** 成本模板 */
costTemplate?: string;
/** 备注 */
@ -3932,7 +4059,7 @@ declare namespace BusinessAPI {
/** 状态1_启用0_禁用 */
status: boolean;
/** 成本ID集合 */
costIds?: number[];
costIds?: string[];
/** 成本费用 */
costVOList?: CostVO[];
/** 成本模板 */
@ -4090,7 +4217,7 @@ declare namespace BusinessAPI {
status?: boolean;
/** 采购订单ID */
orderId?: string;
/** 发货订单ID */
/** 采购订单发货ID */
orderShipId?: string;
};
@ -4235,7 +4362,7 @@ declare namespace BusinessAPI {
/** 角色详情 */
description?: string;
/** 角色id */
menuId: number[];
menuId: string[];
};
type RoleDestroyCmd = {
@ -4257,7 +4384,7 @@ declare namespace BusinessAPI {
/** 角色编号 */
roleId?: string;
/** 应用角色Id */
roleIdList?: number[];
roleIdList?: string[];
/** 平台Id */
platformId?: string;
/** 平台Id */
@ -4304,7 +4431,7 @@ declare namespace BusinessAPI {
/** 角色详情 */
description?: string;
/** 角色id */
menuId: number[];
menuId: string[];
/** 角色ID */
roleId: string;
};
@ -4325,9 +4452,9 @@ declare namespace BusinessAPI {
/** 平台 */
platformVO?: PlatformVO;
/** 权限列表 */
permissionId: number[];
permissionId: string[];
/** 菜单列表 */
menuId: number[];
menuId: string[];
/** 创建时间 */
createdAt: string;
};
@ -4992,7 +5119,7 @@ declare namespace BusinessAPI {
/** 备注 */
remark?: string;
/** 客户标签 */
labelId?: number[];
labelId?: string[];
};
type UserDestroyCmd = {
@ -5014,7 +5141,7 @@ declare namespace BusinessAPI {
/** 状态1_启用0_禁用 */
status?: boolean;
/** 用户ID */
userIdList?: number[];
userIdList?: string[];
/** 用户名 */
name?: string;
};
@ -5057,9 +5184,9 @@ declare namespace BusinessAPI {
/** 是否是管理员 */
isAdmin?: boolean;
/** 会员id列表 */
userIdList?: number[];
userIdList?: string[];
/** 排除的用户id列表 */
excludeUserIdList?: number[];
excludeUserIdList?: string[];
/** 小区id */
communityId?: number;
offset?: number;
@ -5069,7 +5196,7 @@ declare namespace BusinessAPI {
/** 用户ID */
userId: string;
/** 角色ID */
roleIdList?: number[];
roleIdList?: string[];
/** 是否覆盖 */
cover: boolean;
};
@ -5114,7 +5241,7 @@ declare namespace BusinessAPI {
/** 备注 */
remark?: string;
/** 客户标签 */
labelId?: number[];
labelId?: string[];
/** 用户ID */
userId: string;
};

View File

@ -233,14 +233,7 @@ export class PurchaseOrderCalculator {
*
*/
getLossAmount(): number {
return this.profitCalculator.calculateLossAmount();
}
/**
*
*/
getDefaultLossAmount(): number {
return this.profitCalculator.getDefaultLossAmount();
return this.costCalculator.calculateLossAmount();
}
// ==================== 包装相关计算 ====================
@ -325,7 +318,14 @@ export class PurchaseOrderCalculator {
/**
*
*/
getDepositAmount(supplier: BusinessAPI.OrderSupplier): number {
getDepositAmount(): number {
return this.costCalculator.getDepositAmount();
}
/**
*
*/
getSupplierDepositAmount(supplier: BusinessAPI.OrderSupplier): number {
return this.getSupplierCalculator(supplier).getDepositAmount();
}

View File

@ -97,12 +97,14 @@ export class CostCalculator {
const otherCosts = this.calculateTotalCosts();
const taxSubsidy = this.calculateTaxSubsidy();
const taxProvision = this.calculateTaxProvision();
const lossAmount = this.calculateLossAmount();
let totalCost = DecimalUtils.add(
melonCost,
otherCosts,
taxSubsidy,
taxProvision,
lossAmount,
);
if (this.rules.shouldIncludeFreightCost() && !withoutFreight) {
@ -135,15 +137,23 @@ export class CostCalculator {
*/
private shouldIncludeCost(cost: BusinessAPI.OrderCost): boolean {
// 运费需要特殊判断
if (cost.name === "运费") {
if (
(cost.name === "主运费" || cost.name === "短驳费") &&
cost.type === "LOGISTICS_TYPE"
) {
return this.rules.shouldIncludeFreightCost();
}
// 草帘费需要特殊判断
if (cost.name === "草帘费") {
if (cost.name === "草帘费" && cost.type === "LOGISTICS_TYPE") {
return this.rules.shouldIncludeStrawCurtainCost();
}
// 付瓜农定金不需要计算
if (cost.name === "付瓜农定金" && cost.type === "PRODUCTION_TYPE") {
return false;
}
return true;
}
@ -180,17 +190,44 @@ export class CostCalculator {
*/
getFreightCost(): number {
return (
this.order.orderCostList.find((cost) => cost.name === "运费")?.price || 0
this.order.orderCostList.find(
(cost) =>
cost.type === "LOGISTICS_TYPE" &&
(cost.name === "主运费" || cost.name === "短驳费"),
)?.price || 0
);
}
/**
*
*/
getDepositAmount(): number {
return this.order.orderSupplierList.reduce((total, supplier) => {
if (!supplier.isDepositPaid) {
return total;
}
return DecimalUtils.add(total, supplier.depositAmount || 0);
}, 0);
}
/**
*
*/
getStrawCurtainCost(): number {
return (
this.order.orderCostList.find((cost) => cost.name === "草帘费")?.price ||
0
this.order.orderCostList.find(
(cost) => cost.name === "草帘费" && cost.type === "LOGISTICS_TYPE",
)?.price || 0
);
}
/**
*
*/
calculateLossAmount(): number {
if (!this.rules.shouldEnableLoss()) {
return 0;
}
return this.order.orderDealer?.lossAmount || 0;
}
}

View File

@ -21,14 +21,15 @@ export class ProfitCalculator {
/**
* 西
* = - - 西 -
* = - - 西 - -
*/
calculateMelonGrossProfit(): number {
const marketPrice = this.salesCalculator.calculateMarketPrice();
const baseCost = this.costCalculator.calculateBaseCost();
const taxSubsidy = this.costCalculator.calculateTaxSubsidy();
const taxProvision = this.costCalculator.calculateTaxProvision();
return DecimalUtils.subtract(marketPrice, taxSubsidy, baseCost, taxProvision);
const lossAmount = this.costCalculator.calculateLossAmount();
return DecimalUtils.subtract(marketPrice, taxSubsidy, baseCost, taxProvision, lossAmount);
}
/**
@ -114,24 +115,4 @@ export class ProfitCalculator {
getPersonalRebate(): number {
return this.order.orderRebate?.amount || 0;
}
/**
*
*/
calculateLossAmount(): number {
if (!this.rules.shouldEnableLoss()) {
return 0;
}
return this.order.orderDealer?.lossAmount || 0;
}
/**
*
*/
getDefaultLossAmount(): number {
if (this.rules.shouldEnableLoss()) {
return this.calculateLossAmount();
}
return 0;
}
}

File diff suppressed because one or more lines are too long