diff --git a/packages/plugins/@hera/plugin-rental/src/client/custom-components/RecordSummary.tsx b/packages/plugins/@hera/plugin-rental/src/client/custom-components/RecordSummary.tsx index fb21dae47..b31d018da 100644 --- a/packages/plugins/@hera/plugin-rental/src/client/custom-components/RecordSummary.tsx +++ b/packages/plugins/@hera/plugin-rental/src/client/custom-components/RecordSummary.tsx @@ -10,14 +10,14 @@ import React from 'react'; import _ from 'lodash'; import { formatCurrency, formatQuantity } from '../../utils/currencyUtils'; import { useCachedRequest, useLeaseItems } from '../hooks'; -export const RecordSummary = observer((props) => { +import { RecordItems } from '../../interfaces/records'; +export const RecordSummary = observer((props): any => { const form = useForm(); const contractPlanId = form.values.contract_plan?.id; const inContractPlanId = form.values.in_contract_plan?.id; const outContractPlanId = form.values.out_contract_plan?.id; const leaseData = form.values.price_items; - const recordWeight = form.values.weight; const reqWeightRules = useCachedRequest({ resource: 'weight_rules', action: 'list', @@ -33,297 +33,112 @@ export const RecordSummary = observer((props) => { pageSize: 99999, }, }); + //合同方案 const { data: leaseItems } = useLeaseItems(contractPlanId); const { data: inLeaseItems } = useLeaseItems(inContractPlanId); const { data: outLeaseItems } = useLeaseItems(outContractPlanId); + if (!reqProduct.data) { + return ''; + } const allPrice = { - key: '1', name: '总金额', total: 0, unit: '', }; const weight = { - key: '2', name: '理论重量', total: 0, unit: '吨', }; + const priceWeight = { + name: '理论重量', + total: 0, + unit: '吨', + }; + const contractWeight = { + name: '理论重量', + total: 0, + unit: '吨', + }; + const outContractWeight = { + name: '理论重量', + total: 0, + unit: '吨', + }; + + // 基础小结 const summaryProduct = {}; - // 处理除实际重量的情况 + // 合同小结/入库合同小结 + const contractSummary = {}; + // 出库合同小结 + const outContractSummary = {}; + // 报价小结 + const quoteSummary = {}; form.values.items?.forEach((element) => { - // 1.获取产品的分类数据信息 + if (!element.product || !element.count) return; + // 获取产品的分类数据信息 const productCategory = reqProduct.data.data?.find( (product) => product.category_id === element.product?.category_id, )?.category; - if (productCategory) { - let summary, summaryUnit; - if (productCategory && productCategory.convertible) { - summary = (element.count || 0) * element.product?.ratio; - summaryUnit = productCategory.conversion_unit; - } else { - summary = element.count || 0; - summaryUnit = productCategory.unit; + if (!productCategory) return; + element.product.category = productCategory; + // 基础小结 + const { calc } = summary(element, null, null); + weight.total += calc.weight / 1000; + calcProductCount(summaryProduct, calc, productCategory); + // 合同小结(租赁出入库单/租赁直发单) + + if (form.values.category === RecordCategory.lease || form.values.category === RecordCategory.lease2lease) { + if (form.values.category === RecordCategory.lease && !leaseItems) return; + if (form.values.category === RecordCategory.lease2lease && !inLeaseItems) return; + const in_contract = form.values.category === RecordCategory.lease ? leaseItems.data : inLeaseItems.data; + const { ruleCalc } = summary(element, in_contract, reqWeightRules); + contractWeight.total += ruleCalc.weight / 1000; + calcProductCount(contractSummary, ruleCalc, productCategory); + if (form.values.category === RecordCategory.lease2lease && outLeaseItems) { + // 还需要生成出库合同小结 + const out_contract = outLeaseItems.data; + const { ruleCalc } = summary(element, out_contract, reqWeightRules); + outContractWeight.total += ruleCalc.weight / 1000; + calcProductCount(outContractSummary, ruleCalc, productCategory); } - weight.total += ((element.count || 0) * element.product?.weight) / 1000; - if (!element.product) return; - if (summaryProduct[element.product.category_id]) { - summaryProduct[element.product.category_id].total += summary; - } else { - summaryProduct[element.product.category_id] = { - name: productCategory.name, - total: summary, - unit: summaryUnit, + } + // 采购出入库/采购直发小结 + if (form.values.category === RecordCategory.purchase || form.values.category === RecordCategory.purchase2lease) { + const priceRules = leaseData?.map((rule) => { + return { + conversion_logic_id: rule.conversion_logic.id, + products: rule.product, + unit_price: rule.unit_price, }; + }); + const { ruleCalc } = summary(element, priceRules, reqWeightRules); + priceWeight.total += ruleCalc.weight / 1000; + allPrice.total += ruleCalc.price; + calcProductCount(quoteSummary, ruleCalc, productCategory); + if (form.values.category === RecordCategory.purchase2lease && inLeaseItems) { + const in_contract = inLeaseItems.data; + const { ruleCalc } = summary(element, in_contract, null); + contractWeight.total += ruleCalc.weight / 1000; + calcProductCount(contractSummary, ruleCalc, productCategory); } } }); - // 入库合同方案小结 - const contractSummary = {}; - // 出库合同方案小结 - const outContractSummary = {}; - // 报价方案小结 - const leaseSummary = {}; - // 计价数量的计算 - const contractSummaryWeight = { - key: '0', - name: '理论重量', - total: 0, - unit: '吨', - }; - if ( - (form.values.category === RecordCategory.lease || form.values.category === RecordCategory.lease2lease) && - (leaseItems || inLeaseItems) - ) { - form.values.items?.forEach((element) => { - const productCategory = reqProduct.data.data?.find( - (product) => product.category_id === element.product?.category_id, - )?.category; - // 合同方案 - const in_contract = form.values.category === RecordCategory.lease ? leaseItems.data : inLeaseItems.data; - const contractPlain = in_contract.find((item) => - item.products.find( - (product) => product.id - 99999 === element.product?.category_id || product.id === element.product?.id, - ), - ); - // 计算合同方案的理论重量 - const weightItem = calcTheoreticalWeight(element, reqWeightRules, contractPlain); - contractSummaryWeight.total += weightItem; - const res = subtotal(contractPlain, element, productCategory, reqWeightRules); - if (res) { - if (!contractSummary[element.product?.category_id]) { - contractSummary[element.product?.category_id] = { - name: productCategory?.name, - total: 0, - unit: res.unit, - }; - } - contractSummary[element.product?.category_id] = { - name: productCategory?.name, - total: (contractSummary[element.product?.category_id].total += res.count), - unit: res.unit, - }; - } - }); - } - const leaseSummaryWeight = { - key: '0', - name: '理论重量', - total: 0, - unit: '吨', - }; - const leaseSummaryPrice = { - key: '99', - name: '总金额', - total: 0, - unit: '', - }; - // 基本小结要带金额,报价小结也要带金额 - if (form.values.category === RecordCategory.purchase || form.values.category === RecordCategory.purchase2lease) { - form.values.items?.forEach((element) => { - const productCategory = reqProduct.data.data?.find( - (product) => product.category_id === element.product?.category_id, - )?.category; - const rule = leaseData?.find( - (rule) => - rule.product?.category_id === element.product?.category_id || rule.product?.id === element.product?.id, - ); - if (rule) { - rule.conversion_logic_id = rule.conversion_logic.id; - const res = subtotal(rule, element, productCategory, reqWeightRules); - const price = calcLeasePriceSum(element, rule, productCategory, recordWeight); - leaseSummaryPrice.total += price; - // 计算合同方案的理论重量 - const weightItem = calcTheoreticalWeight(element, reqWeightRules, rule); - leaseSummaryWeight.total += weightItem; - if (res) { - if (!leaseSummary[element.product?.category_id]) { - leaseSummary[element.product?.category_id] = { - name: productCategory?.name, - total: 0, - unit: res.unit, - }; - } - leaseSummary[element.product?.category_id] = { - name: productCategory?.name, - total: (leaseSummary[element.product?.category_id].total += res.count), - unit: res.unit, - }; - } - } - }); - } - if (form.values.category === RecordCategory.purchase2lease && inLeaseItems) { - // 出现两次purchase2lease,上面处理报价小结,此处处理入库合同小结 - form.values.items?.forEach((element) => { - const productCategory = reqProduct.data.data?.find( - (product) => product.category_id === element.product?.category_id, - )?.category; - const contractPlain = inLeaseItems.data.find((item) => - item.products.find( - (product) => product.id - 99999 === element.product?.category_id || product.id === element.product?.id, - ), - ); - const weightItem = calcTheoreticalWeight(element, reqWeightRules, contractPlain); - contractSummaryWeight.total += weightItem; - const res = subtotal(contractPlain, element, productCategory, reqWeightRules); - if (res) { - if (!contractSummary[element.product?.category_id]) { - contractSummary[element.product?.category_id] = { - name: productCategory?.name, - total: 0, - unit: res.unit, - }; - } - contractSummary[element.product?.category_id] = { - name: productCategory?.name, - total: (contractSummary[element.product?.category_id].total += res.count), - unit: res.unit, - }; - } - }); - } - const outContractSummaryWeight = { - key: '0', - name: '理论重量', - total: 0, - unit: '吨', - }; - if (form.values.category === RecordCategory.lease2lease && outLeaseItems) { - // 此判断出现两次,上面处理入库小结,此处要处理出库小结 - form.values.items?.forEach((element) => { - const productCategory = reqProduct.data.data?.find( - (product) => product.category_id === element.product?.category_id, - )?.category; - const contractPlain = outLeaseItems.data.find((item) => - item.products.find( - (product) => product.id - 99999 === element.product?.category_id || product.id === element.product?.id, - ), - ); - const weightItem = calcTheoreticalWeight(element, reqWeightRules, contractPlain); - outContractSummaryWeight.total += weightItem; - const res = subtotal(contractPlain, element, productCategory, reqWeightRules); - if (res) { - if (!outContractSummary[element.product?.category_id]) { - outContractSummary[element.product?.category_id] = { - name: productCategory?.name, - total: 0, - unit: res.unit, - }; - } - outContractSummary[element.product?.category_id] = { - name: productCategory?.name, - total: (outContractSummary[element.product?.category_id].total += res.count), - unit: res.unit, - }; - } - }); - } - // 常规小结 - const items = []; - for (const key in summaryProduct) { - if (Object.prototype.hasOwnProperty.call(summaryProduct, key)) { - const element = summaryProduct[key]; - items.push({ ...element, key: key }); - } - } - const result = - form.values.category === RecordCategory.purchase || form.values.category === RecordCategory.purchase2lease - ? [weight, ...items, allPrice] - : [weight, ...items]; - const value = result - .map((item) => { - if (!item.total) return; - return { - label: item.name, - children:

{item.unit ? formatQuantity(item.total, 2) + item.unit : formatCurrency(item.total, 2)}

, - }; - }) - .filter(Boolean); - - // 合同小结/入库合同小结(租赁单,使用合同 租赁直发单,使用入库合同) - const inContract = []; - for (const key in contractSummary) { - if (Object.prototype.hasOwnProperty.call(contractSummary, key)) { - const element = contractSummary[key]; - inContract.push({ ...element, key: key }); - } - } - inContract.unshift(contractSummaryWeight); - const inContractvalue = inContract - .map((item) => { - if (!item.total) return; - return { - label: item.name, - children:

{item.unit ? formatQuantity(item.total, 2) + item.unit : formatCurrency(item.total, 2)}

, - }; - }) - .filter(Boolean); - - // 出库合同小结 - const outContract = []; - for (const key in outContractSummary) { - if (Object.prototype.hasOwnProperty.call(outContractSummary, key)) { - const element = outContractSummary[key]; - outContract.push({ ...element, key: key }); - } - } - outContract.unshift(outContractSummaryWeight); - const outContractvalue = outContract - .map((item) => { - if (!item.total) return; - return { - label: item.name, - children:

{item.unit ? formatQuantity(item.total, 2) + item.unit : formatCurrency(item.total, 2)}

, - }; - }) - .filter(Boolean); - - // 报价小结 - const lease = []; - for (const key in leaseSummary) { - if (Object.prototype.hasOwnProperty.call(leaseSummary, key)) { - const element = leaseSummary[key]; - lease.push({ ...element, key: key }); - } - } - lease.unshift(leaseSummaryWeight); - lease.push(leaseSummaryPrice); - const leasevalue = lease - .map((item) => { - if (!item.total) return; - return { - label: item.name, - children:

{item.unit ? formatQuantity(item.total, 2) + item.unit : formatCurrency(item.total, 2)}

, - }; - }) - .filter(Boolean); + summaryProduct['0'] = weight; + contractSummary['0'] = contractWeight; + outContractSummary['0'] = outContractWeight; + quoteSummary['0'] = priceWeight; + quoteSummary['999'] = allPrice; const resultItems = [ - { label: '基础', value: value }, - { label: '报价', value: leasevalue }, - { label: '出库合同', value: outContractvalue }, - { label: form.values.category === RecordCategory.lease ? '合同' : '入库合同', value: inContractvalue }, + { label: '基础', value: transDescriptions(Object.values(summaryProduct)) }, + { label: '报价', value: transDescriptions(Object.values(quoteSummary)) }, + { label: '出库合同', value: transDescriptions(Object.values(outContractSummary)) }, + { + label: form.values.category === RecordCategory.lease ? '合同' : '入库合同', + value: transDescriptions(Object.values(contractSummary)), + }, ]; const trans: any[] = resultItems @@ -358,88 +173,110 @@ RecordSummary.displayName = 'RecordSummary'; RecordSummary[KEY_CUSTOM_COMPONENT_TYPE] = CUSTOM_COMPONENT_TYPE_FORM_ITEM; RecordSummary[KEY_CUSTOM_COMPONENT_LABEL] = '记录单 - 小结'; -const subtotal = (rule: any, itemData: any, productCategory: any, reqWeightRules: any) => { - let count: number; - let unit: string; - if (rule?.conversion_logic_id === ConversionLogics.Keep) { - count = itemData.count; - unit = productCategory.unit; - } else if (rule?.conversion_logic_id === ConversionLogics.Product) { - count = productCategory.convertible ? itemData.count * itemData.product.ratio : itemData.count; - unit = productCategory.convertible ? productCategory.conversion_unit : productCategory.unit; - } else if (rule?.conversion_logic_id === ConversionLogics.ProductWeight) { - count = (itemData.count * itemData.product.weight) / 1000; - unit = '吨'; - } else if (rule?.conversion_logic_id === ConversionLogics.ActualWeight) { - count = 0; - unit = '吨'; +/** 计算小结 + * @param event RecordItem 订单项,record_item + */ +const summary = (event: RecordItems, rules: any[], ruleWeight: any) => { + // 1. 没有规则直接默认产品表换算逻辑 + const calc = { + name: '', + count: 0, + weight: 0, + unit: '', + }; + const ruleCalc = { + name: '', + count: 0, + weight: 0, + unit: '', + price: 0, + }; + const category = event.product.category; + const convertiblen = category.convertible; + if (!rules) { + const count = convertiblen ? event.count * event.product.ratio : event.count; + const unit = convertiblen ? category.conversion_unit : category.unit; + calc.name = category.name; + calc.count = count; + calc.unit = unit; + calc.weight = event.product.weight; } else { - // 查询重量规则 - const weightRule = reqWeightRules.data.data.find( - (weight_item) => - weight_item.logic_id === rule?.conversion_logic_id && - (weight_item.product_id === itemData.product?.id || - weight_item.product_id === itemData.product?.category_id + 99999), + // 2. 存在规则(实际重量情况不计算) + const plain = rules.find((item) => + // 处理报价跟合同不同数据结构问题 [].flat() + [item.products] + .flat() + .find((product) => product?.id - 99999 === event.product.category_id || product.id === event.product.id), ); - if (!weightRule) return; - if (weightRule.conversion_logic_id === ConversionLogics.Keep) { - count = ((itemData.count || 0) * weightRule.weight) / 1000; - unit = '吨'; - } else if (weightRule.conversion_logic_id === ConversionLogics.Product) { - const sacl = productCategory.convertible ? itemData.product.ratio : 1; - count = ((itemData.count || 0) * sacl * weightRule.weight) / 1000; - unit = '吨'; - } - } - return { count, unit }; -}; - -/** - * 理论重量计算(普通情况除外) - */ -const calcTheoreticalWeight = (itemData: any, rule: any, contractPlain: any) => { - if (!contractPlain) return 0; - const weightRule = rule.data.data.find( - (weightRule) => - weightRule.product_id === itemData.product?.id || weightRule.product_id - 99999 === itemData.product?.category_id, - ); - if (weightRule?.weight && itemData?.count) { - return (weightRule.weight * itemData.count) / 1000; - } else { - return 0; - } -}; - -/** - * 报价金额小结 - */ -const calcLeasePriceSum = (itemData: any, priceRules: any, productCategory: any, reqWeightRules: any) => { - let price = 0; - if (priceRules.conversion_logic_id === ConversionLogics.Keep) { - price = itemData.count * priceRules.unit_price; - } else if (priceRules.conversion_logic_id === ConversionLogics.Product) { - if (productCategory.convertible) { - price = itemData.count * priceRules.unit_price * itemData.product?.ratio; + if (!plain) return { ruleCalc }; + ruleCalc.name = category.name; + if (plain.conversion_logic_id === ConversionLogics.Keep) { + ruleCalc.count = event.count; + ruleCalc.unit = category.unit; + } else if (plain.conversion_logic_id === ConversionLogics.Product) { + const count = convertiblen ? event.count * event.product.ratio : event.count; + const unit = convertiblen ? category.conversion_unit : category.unit; + ruleCalc.count = count; + ruleCalc.unit = unit; + } else if (plain.conversion_logic_id === ConversionLogics.ProductWeight) { + ruleCalc.count = (event.count * event.product.weight) / 1000; + ruleCalc.unit = '吨'; + } else if (plain.conversion_logic_id === ConversionLogics.ActualWeight) { + ruleCalc.count = 0; + ruleCalc.unit = '吨'; } else { - price = itemData.count * priceRules.unit_price; + const weightRule = ruleWeight.data?.data?.find( + (item) => + (item.product_id === event.product.id || item.product_id - 99999 === event.product.category_id) && + item.logic_id === plain.conversion_logic_id, + ); + if (weightRule) { + if (weightRule.conversion_logic_id === ConversionLogics.Keep) { + ruleCalc.count = (event.count * weightRule.weight) / 1000; + ruleCalc.unit = '吨'; + } else if (weightRule.conversion_logic_id === ConversionLogics.Product) { + ruleCalc.count = convertiblen + ? (event.count * event.product.ratio * weightRule.weight) / 1000 + : (event.count * weightRule.weight) / 1000; + ruleCalc.unit = '吨'; + } + ruleCalc.weight = ruleCalc.count * 1000; + ruleCalc.price = ruleCalc.count * plain.unit_price; + } } - } else if (priceRules.conversion_logic_id === ConversionLogics.ProductWeight) { - price = itemData.count * (itemData.product?.weight || 1); - } else if (priceRules.conversion_logic_id === ConversionLogics.ActualWeight) { - price = 0; - } else { - const weightRule = reqWeightRules.data.data.find( - (weight_item) => - weight_item.logic_id === priceRules.conversion_logic_id && - (weight_item.product_id === itemData.product?.id || - weight_item.product_id === itemData.product?.category_id + 99999), - ); - if (!weightRule) return; - if (weightRule.conversion_logic_id === ConversionLogics.Keep) { - price = itemData.count * weightRule.weight; - } else if (weightRule.conversion_logic_id === ConversionLogics.Product) { - price = itemData.count * weightRule.weight * itemData.product?.ratio; + if (plain.conversion_logic_id <= 4) { + ruleCalc.price = ruleCalc.count * plain.unit_price; + ruleCalc.weight = event.product.weight * event.count; } } - return price; + + return { calc, ruleCalc }; +}; + +/** + * 产品数量汇总方法 + */ +const calcProductCount = (summary: any, calc: any, category: any) => { + if (summary[category.id]) { + summary[category.id].total += calc.count; + } else { + summary[category.id] = { + name: calc.name, + total: calc.count, + unit: calc.unit, + }; + } +}; + +const transDescriptions = (data) => { + const values = data.map((item: any, index) => { + if (item.total) { + return { + key: index, + label: item.name, + children: item.name === '总金额' ? formatCurrency(item.total, 2) : formatQuantity(item.total, 3) + item.unit, + }; + } + }); + return values.filter(Boolean); }; diff --git a/packages/plugins/@hera/plugin-rental/src/server/services/record-service.ts b/packages/plugins/@hera/plugin-rental/src/server/services/record-service.ts index f09eb4705..5fa09a915 100644 --- a/packages/plugins/@hera/plugin-rental/src/server/services/record-service.ts +++ b/packages/plugins/@hera/plugin-rental/src/server/services/record-service.ts @@ -66,7 +66,7 @@ export class RecordService { if (!values) return; // 触发打印更新次数跳过 if (values?.print_count) return; - if (values?.category === RecordCategory.lease && values.contrac) { + if (values?.category === RecordCategory.lease && values.contract) { const dateObject = values.date; // 结束时间添加一天,新系统选择时间都是以当天0点开始,但是导入的数据存在不是以0点开始比如2023-12-21:03.000……,提醒结算单的时间可能为2023-12-21:00.000…… const settlement = await this.db.sequelize.query( @@ -288,7 +288,12 @@ export class RecordService { feeItems.push({ product: product.dataValues, count: element.count }); } } - productArr.push({ product: product.dataValues, count: porduct_item.count, fee_items: feeItems }); + productArr.push({ + product: product.dataValues, + count: porduct_item.count, + fee_items: feeItems, + comment: porduct_item.comments, + }); } recordData['items'] = productArr; // 处理购销单定价 @@ -581,8 +586,8 @@ export class RecordService { return allPrice / 1000; } else if (rule.conversion_logic.id === ConversionLogics.ActualWeight) { // 根据产品找分组实际重量 - const weightDate = weight_items.find( - (item) => item.products?.find((product) => product?.id === rule.product.id - 99999), + const weightDate = weight_items.find((item) => + item.products?.find((product) => product?.id === rule.product.id - 99999), ); if (weightDate) { const allPrice = weightDate.weight * rule.unit_price;