tachybase_todo/packages/plugins/@hera/plugin-rental/src/server/services/settlement-service.ts

1109 lines
48 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Db, Service } from '@nocobase/utils';
import Database from '@nocobase/database';
import dayjs from 'dayjs';
import {
AddItemsCategory,
CalcDateType,
ConversionLogics,
Itemcategory,
RulesNumber,
countCource,
} from '../../utils/constants';
import { converDate } from '../../utils/daysUtils';
import { converUnitCount } from '../../utils/unitUtils';
import { Settlement } from '../interfaces/settlement';
import { FeeRule, LeaseRule } from '../interfaces/rule';
import { Record } from '../interfaces/record';
import { recordItems } from '../interfaces/records';
import { formatQuantity } from '../../utils/currencyUtils';
@Service()
export class SettlementService {
@Db()
private db: Database;
async calculate(settlementAbout: Settlement, settlementsId) {
/**
* 租金计算方式
* 0: 计头不计尾
* 1. 计尾不计头
* 2. 计头又计尾
* 3. 不计头不计尾
*/
let createLeasDatas = [];
let createFeesDatas = [];
settlementAbout.contracts.rule_items?.forEach((ruleItem) => {
if (
dayjs(settlementAbout.start_date).isSameOrAfter(ruleItem.start_date, 'day') &&
dayjs(settlementAbout.end_date).isSameOrBefore(ruleItem.end_date, 'day')
) {
// lease_rules 租金规则[]
const lease_rules = ruleItem?.rule.lease_items;
// fee_rules 费用明细
const fee_rules = ruleItem?.rule.fee_item;
// 处理原始数据,适合后续租金数据成
if (settlementAbout.records === null) {
settlementAbout.records = [];
}
// 正常租赁数据
lease_rules?.forEach((rule) => {
if (rule) {
if (rule.products.length) {
rule.products.forEach((productRule) => {
const productCategory = productRule.product_id > RulesNumber ? 'category' : 'product';
settlementAbout.records.forEach((item) => {
//计算正常租赁订单
if (rule.conversion_logic_id === ConversionLogics.ActualWeight) {
if (item.weight_items.length) {
item.weight_items?.forEach((recordItem) => {
if (recordItem) {
if (
productRule.product_id > RulesNumber &&
productRule.product_id - RulesNumber === recordItem.product_category_id
) {
const productName = item.record_items.filter(
(value) => value.product.product_category.id === recordItem.product_category_id,
)[0].product;
const day =
dayjsDays(item.date) < dayjsDays(settlementAbout.start_date)
? getCalcDays(settlementAbout.start_date, settlementAbout.end_date)
: afterDays(
settlementAbout.contracts.calc_type,
item.movement,
item.date,
settlementAbout.end_date,
);
const movement = item.movement === '-1' ? '1' : '-1';
createLeasDatas.push({
settlement_id: settlementsId, //合同ID
movement: item.movement, //出入库状态
date: item.date, //时间
name: productName.name, //名称
label: productName.label, //规格
category: item.category, //费用类别
//租赁天数 历史订单就存开始日期到结束日期 当前订单存储订单日期到结束日期
days: day,
is_excluded: false,
count: recordItem.weight * Number(movement),
unit_price: rule.unit_price * 1000,
amount: recordItem.weight * (rule.unit_price * 1000) * day,
unit_name: '吨',
productCategory,
});
}
}
});
} else {
if (
(productRule.product_id > RulesNumber &&
productRule.product_id - RulesNumber === item.record_items[0]?.product.category_id) ||
productRule.product_id === item.record_items[0]?.product.id
) {
const day =
dayjsDays(item.date) < dayjsDays(settlementAbout.start_date)
? getCalcDays(settlementAbout.start_date, settlementAbout.end_date)
: afterDays(
settlementAbout.contracts.calc_type,
item.movement,
item.date,
settlementAbout.end_date,
);
const movement = item.movement === '-1' ? '1' : '-1';
createLeasDatas.push({
settlement_id: settlementsId, //合同ID
movement: item.movement, //出入库状态
date: item.date, //时间
name: item.record_items[0]?.product.name, //名称
label: item.record_items[0]?.product.label, //规格
category: item.category, //费用类别
//租赁天数 历史订单就存开始日期到结束日期 当前订单存储订单日期到结束日期
days: day,
is_excluded: false,
count: item.weight * Number(movement),
unit_price: rule.unit_price * 1000,
amount: item.weight * (rule.unit_price * 1000) * day,
unit_name: '吨',
productCategory,
});
}
}
} else {
item.record_items?.forEach((recordItem) => {
if (recordItem) {
if (
(productRule.product_id > RulesNumber &&
productRule.product_id - RulesNumber === recordItem.product.category_id) ||
productRule.product_id === recordItem.product.id
) {
const data = {
settlement_id: settlementsId, //合同ID
movement: item.movement, //出入库状态
date: item.date, //时间
name: recordItem.product.name, //名称
label: recordItem.product.label, //规格
category: item.category, //费用类别
//租赁天数 历史订单就存开始日期到结束日期 当前订单存储订单日期到结束日期
days:
dayjsDays(item.date) < dayjsDays(settlementAbout.start_date)
? getCalcDays(settlementAbout.start_date, settlementAbout.end_date)
: afterDays(
settlementAbout.contracts.calc_type,
item.movement,
item.date,
settlementAbout.end_date,
),
is_excluded: false,
productCategory,
};
// 要根据规则计算数量,单价,金额,确定单位
const price = rule.unit_price || 0;
const movement = item.movement === '-1' ? '1' : '-1';
const { count, unit } = ruleCount(rule, item, recordItem);
data['unit_name'] = unit;
data['count'] = count * Number(movement);
data['unit_price'] = price;
data['amount'] = data['count'] * price * (data.days || 0);
createLeasDatas.push(data);
}
}
});
}
//计算有关联产品费用订单
if (rule.product_fee.length) {
if (
dayjs(item.date).isBetween(ruleItem.start_date, ruleItem.end_date, 'day', '[]') &&
dayjs(item.date).isSameOrAfter(settlementAbout.start_date)
) {
rule.product_fee.forEach((rulefee) => {
if (rulefee.fee_product_id) {
const spec = rulefee.product.spec;
const name = rulefee.product.name;
if (rulefee.conversion_logic_id === ConversionLogics.ActualWeight) {
let data;
if (
rulefee.count_source === countCource.outProduct ||
rulefee.count_source === countCource.outItem
) {
if (item.movement === '-1') {
data = recordWeight(rule, item, settlementsId, productRule, rulefee);
if (data) {
data.movement = '-1';
}
}
} else if (
rulefee.count_source === countCource.enterProduct ||
rulefee.count_source === countCource.enterItem
) {
if (item.movement === '1') {
data = recordWeight(rule, item, settlementsId, productRule, rulefee);
if (data) {
data.movement = '1';
}
}
} else {
data = recordWeight(rule, item, settlementsId, productRule, rulefee);
if (data) {
data.movement = '0';
}
}
if (data) {
createFeesDatas.push({ ...data, productCategory });
}
} else {
item.record_items?.forEach((recordItem) => {
if (recordItem) {
if (
productRule.product_id - RulesNumber === recordItem.product.category_id ||
recordItem.product_id === productRule.product_id
) {
let productname;
switch (productCategory) {
case 'category':
productname = recordItem.product.name;
break;
case 'product':
productname = recordItem.product.label;
break;
}
//人工录入
if (rulefee.count_source === countCource.artificial) {
if (rulefee.conversion_logic_id !== ConversionLogics.ActualWeight) {
if (recordItem.record_item_fee_items.length) {
recordItem.record_item_fee_items.forEach((value) => {
if (value.product_id === rulefee.fee_product_id) {
const { count, unit } = ruleCount(
rule,
item,
recordItem,
value.count,
rulefee,
);
createFeesDatas.push({
settlement_id: settlementsId,
date: item.date,
name: productname + '-' + spec,
label: recordItem.product.label + '-' + spec,
category: name,
movement: item.movement,
count: count,
unit_price: rulefee.unit_price,
amount: rulefee.unit_price * count,
unit_name: unit,
is_excluded: value.is_excluded,
productCategory,
});
}
});
}
}
} //出库
else if (
rulefee.count_source === countCource.outProduct ||
rulefee.count_source === countCource.outItem
) {
if (item.movement === '-1') {
const { count, unit } = ruleCount(rule, item, recordItem, '', rulefee);
const recordCount = recordItemsFee(rule, item, recordItem, count, rulefee);
createFeesDatas.push({
settlement_id: settlementsId,
date: item.date,
name: productname + '-' + spec,
label: recordItem.product.label + '-' + spec,
category: name,
movement: '-1',
count: recordCount,
unit_price: rulefee.unit_price,
amount: count * rulefee.unit_price,
unit_name: unit,
is_excluded: false,
productCategory,
});
}
} //入库
else if (
rulefee.count_source === countCource.enterProduct ||
rulefee.count_source === countCource.enterItem
) {
if (item.movement === '1') {
const { count, unit } = ruleCount(rule, item, recordItem, '', rulefee);
const recordCount = recordItemsFee(rule, item, recordItem, count, rulefee);
createFeesDatas.push({
settlement_id: settlementsId,
date: item.date,
name: productname + '-' + spec,
label: recordItem.product.label + '-' + spec,
category: name,
movement: '1',
count: recordCount,
unit_price: rulefee.unit_price,
amount: count * rulefee.unit_price,
unit_name: unit,
is_excluded: false,
productCategory,
});
}
} //出入库
else if (
rulefee.count_source === countCource.product ||
rulefee.count_source === countCource.item
) {
const { count, unit } = ruleCount(rule, item, recordItem, '', rulefee);
const recordCount = recordItemsFee(rule, item, recordItem, count, rulefee);
createFeesDatas.push({
settlement_id: settlementsId,
date: item.date,
name: productname + '-' + spec,
label: recordItem.product.label + '-' + spec,
category: name,
movement: '0',
count: recordCount,
unit_price: rule.unit_price,
amount: count * rule.unit_price,
unit_name: unit,
is_excluded: false,
productCategory,
});
}
}
}
});
}
}
});
}
}
});
});
}
}
});
// 产品产生的费用
fee_rules?.forEach((rule) => {
let conversion = false;
const spec = rule.product.spec;
const name = rule.product.name;
const data = {
settlement_id: settlementsId,
date: dayjs(settlementAbout.end_date).add(1, 'day').add(-1, 'minute'),
name: spec,
label: spec,
category: name,
movement: '0',
count: 0,
unit_price: rule.unit_price,
amount: 0,
unit_name: rule.unit,
is_excluded: false,
};
if (rule.conversion_logic_id === ConversionLogics.ActualWeight) {
settlementAbout.records.forEach((item) => {
if (
dayjs(item.date).isBetween(ruleItem.start_date, ruleItem.end_date, 'day', '[]') &&
dayjs(item.date).isSameOrAfter(settlementAbout.start_date)
) {
if (rule.count_source === countCource.outProduct || rule.count_source === countCource.outItem) {
if (item.movement === '-1') {
data.movement = '-1';
data.count += item.weight_items.length
? item.weight_items.length
? item.weight_items.reduce((sum, curr) => {
return sum + curr.weight;
}, 0)
: 0
: item.weight;
if (item.fee_item.length) {
item.fee_item.forEach((value) => {
if (value.product_id === rule.fee_product_id) {
data.count = value.is_excluded ? data.count - value.count : data.count;
}
});
}
conversion = true;
}
} else if (
rule.count_source === countCource.enterProduct ||
rule.count_source === countCource.enterItem
) {
if (item.movement === '1') {
data.movement = '1';
data.count += item.weight_items.length
? item.weight_items.length
? item.weight_items.reduce((sum, curr) => {
return sum + curr.weight;
}, 0)
: 0
: item.weight;
if (item.fee_item.length) {
item.fee_item.forEach((value) => {
if (value.product_id === rule.fee_product_id) {
data.count = value.is_excluded ? data.count - value.count : data.count;
}
});
}
conversion = true;
}
} else if (rule.count_source === countCource.product || rule.count_source === countCource.item) {
data.count += item.weight_items.length
? item.weight_items.length
? item.weight_items.reduce((sum, curr) => {
return sum + curr.weight;
}, 0)
: 0
: item.weight;
if (item.fee_item.length) {
item.fee_item.forEach((value) => {
if (value.product_id === rule.fee_product_id) {
data.count = value.is_excluded ? data.count - value.count : data.count;
}
});
}
conversion = true;
}
}
});
} else {
//人工录入
if (rule.count_source === countCource.artificial) {
if (
rule.conversion_logic_id !== ConversionLogics.Product &&
rule.conversion_logic_id !== ConversionLogics.ActualWeight &&
rule.conversion_logic_id !== ConversionLogics.ProductWeight
) {
settlementAbout.records?.forEach((item) => {
if (
dayjs(item.date).isBetween(ruleItem.start_date, ruleItem.end_date, 'day', '[]') &&
dayjs(item.date).isSameOrAfter(settlementAbout.start_date)
) {
if (item.fee_item.length) {
item.fee_item.forEach((value) => {
if (value.product_id === rule.fee_product_id) {
data.count = value.is_excluded ? data.count - value.count : data.count + value.count;
data.is_excluded = value.is_excluded;
conversion = true;
}
});
}
}
});
}
} //出库
else if (rule.count_source === countCource.outProduct || rule.count_source === countCource.outItem) {
if (
rule.conversion_logic_id !== ConversionLogics.Keep &&
rule.conversion_logic_id !== ConversionLogics.Product
) {
settlementAbout.records?.forEach((item) => {
if (
dayjs(item.date).isBetween(ruleItem.start_date, ruleItem.end_date, 'day', '[]') &&
dayjs(item.date).isSameOrAfter(settlementAbout.start_date)
) {
if (item.movement === '-1') {
item.record_items?.forEach((recordItem) => {
if (recordItem) {
const { count } = ruleCount(rule, item, recordItem);
data.count += count;
data.movement = '-1';
conversion = true;
}
});
if (item.fee_item.length) {
item.fee_item.forEach((value) => {
if (value.product_id === rule.fee_product_id) {
data.count = value.is_excluded ? data.count - value.count * 1000 : data.count;
}
});
}
}
}
});
}
} //入库
else if (rule.count_source === countCource.enterProduct || rule.count_source === countCource.enterItem) {
if (
rule.conversion_logic_id !== ConversionLogics.Keep &&
rule.conversion_logic_id !== ConversionLogics.Product
) {
settlementAbout.records?.forEach((item) => {
if (
dayjs(item.date).isBetween(ruleItem.start_date, ruleItem.end_date, 'day', '[]') &&
dayjs(item.date).isSameOrAfter(settlementAbout.start_date)
) {
if (item.movement === '1') {
item.record_items?.forEach((recordItem) => {
if (recordItem) {
const { count } = ruleCount(rule, item, recordItem);
data.count += count;
data.movement = '1';
conversion = true;
}
});
if (item.fee_item.length) {
item.fee_item.forEach((value) => {
if (value.product_id === rule.fee_product_id) {
data.count = value.is_excluded ? data.count - value.count * 1000 : data.count;
}
});
}
}
}
});
}
} //出入库
else if (rule.count_source === countCource.product || rule.count_source === countCource.item) {
if (
rule.conversion_logic_id !== ConversionLogics.Keep &&
rule.conversion_logic_id !== ConversionLogics.Product
) {
settlementAbout.records?.forEach((item) => {
if (
dayjs(item.date).isBetween(ruleItem.start_date, ruleItem.end_date, 'day', '[]') &&
dayjs(item.date).isSameOrAfter(settlementAbout.start_date)
) {
item.record_items?.forEach((recordItem) => {
if (recordItem) {
const { count } = ruleCount(rule, item, recordItem);
data.count += count;
data.movement = '0';
conversion = true;
}
});
if (item.fee_item.length) {
item.fee_item.forEach((value) => {
if (value.product_id === rule.fee_product_id) {
data.count = value.is_excluded ? data.count - value.count * 1000 : data.count;
}
});
}
}
});
}
}
}
if (conversion) {
if (
rule.count_source !== countCource.artificial &&
rule.conversion_logic_id !== ConversionLogics.ActualWeight
) {
data.count = data.count / 1000;
}
data.amount = data.count * data.unit_price;
createFeesDatas.push(data);
}
});
}
});
createFeesDatas = createFeesDatas?.filter(Boolean);
createLeasDatas = createLeasDatas?.filter(Boolean);
const createCategoryDatasItem = screenData(createLeasDatas, settlementAbout, 'category');
const createProductDatasItem = screenData(createLeasDatas, settlementAbout, 'product');
const recordsCategoryFeeItem = feeData(createFeesDatas, settlementAbout, 'category');
const recordsProductFeeItem = feeData(createFeesDatas, settlementAbout, 'product');
//本期信息
let createDatas = [
...createCategoryDatasItem.list,
...createProductDatasItem.list,
...recordsCategoryFeeItem,
...recordsProductFeeItem,
];
createDatas.sort((a, b) => {
return new Date(a.date).getTime() - new Date(b.date).getTime();
});
createDatas = createDatas.filter((value) => value.count);
//筛选历史结存
createCategoryDatasItem.history = createCategoryDatasItem.history?.filter((value) => value.count);
createProductDatasItem.history = createProductDatasItem.history?.filter((value) => value.count);
//汇总项信息
const summaryCategoryItems = [];
for (const value in createCategoryDatasItem) {
createCategoryDatasItem[value].forEach((item) => {
if (!summaryCategoryItems.find((value) => value.name === item.name && item.category === '0')) {
summaryCategoryItems.push({
settlement_id: settlementsId,
name: item.name,
count: item.count,
unit_name: item.unit_name,
type: 'category',
});
} else {
summaryCategoryItems.forEach((value) => {
if (value.name === item.name) {
value.count += item.count;
}
});
}
});
}
const summaryProductItems = [];
for (const value in createProductDatasItem) {
createProductDatasItem[value].forEach((item) => {
if (!summaryProductItems.find((value) => value.name === item.name && item.category === '0')) {
summaryProductItems.push({
settlement_id: settlementsId,
name: item.name,
count: item.count,
unit_name: item.unit_name,
type: 'product',
});
} else {
summaryProductItems.forEach((value) => {
if (value.name === item.name) {
value.count += item.count;
}
});
}
});
}
const summaryItems = [...summaryCategoryItems, ...summaryProductItems];
//结算表信息
const summaryPeriod = {
rent: 0.0, //租金
maintenance: 0.0, //维修人工
n_compensate: 0.0, //无物赔偿
h_compensate: 0.0, //有物赔偿
loadfreight: 0.0, //装卸运费
current_expenses: 0.0, //本期费用
tax: 0.0, //税率
accumulate: 0.0, //累计费用
current_collection: 0.0, //本期收款
accumulate_collection: 0.0, //累计收款
status: '2',
};
// 结算表费用
recordsCategoryFeeItem.forEach((value) => {
switch (value.category) {
case Itemcategory.maintenance:
summaryPeriod.maintenance += value.amount;
break;
case Itemcategory.n_compensate:
summaryPeriod.n_compensate += value.amount;
break;
case Itemcategory.h_compensate:
summaryPeriod.h_compensate += value.amount;
break;
case Itemcategory.loadFreight:
summaryPeriod.loadfreight += value.amount;
break;
}
});
settlementAbout.settlement_add_items.forEach((value) => {
switch (value.category) {
case AddItemsCategory.rent:
summaryPeriod.rent += value.amount;
break;
case AddItemsCategory.maintenance:
summaryPeriod.maintenance += value.amount;
break;
case AddItemsCategory.n_compensate:
summaryPeriod.n_compensate += value.amount;
break;
case AddItemsCategory.h_compensate:
summaryPeriod.h_compensate += value.amount;
break;
case AddItemsCategory.loadFreight:
summaryPeriod.loadfreight += value.amount;
break;
}
});
summaryPeriod.rent = createCategoryDatasItem.list.reduce((sum, curr) => sum + curr.amount, summaryPeriod.rent);
summaryPeriod.rent = createCategoryDatasItem.history.reduce((sum, curr) => sum + curr.amount, summaryPeriod.rent);
summaryPeriod.tax = settlementAbout.contracts.tax_included ? 0 : settlementAbout.contracts.tax_rate;
summaryPeriod.current_expenses =
(summaryPeriod.rent +
summaryPeriod.maintenance +
summaryPeriod.n_compensate +
summaryPeriod.h_compensate +
summaryPeriod.loadfreight) *
(summaryPeriod.tax + 1);
const settlement = settlementAbout.settlements?.filter((value) =>
dayjs(value.end_date).isBefore(settlementAbout.start_date),
);
summaryPeriod.accumulate = settlement.length
? settlement.reduce((sum, curr) => sum + curr.current_expenses, summaryPeriod.current_expenses)
: summaryPeriod.current_expenses;
await this.db.sequelize.query(`delete from settlement_items where settlement_id=${settlementsId}`);
await this.db.sequelize.query(`delete from settlement_history_items where settlement_id=${settlementsId}`);
await this.db.sequelize.query(`delete from settlement_summary_items where settlement_id=${settlementsId}`);
//修改结算表数据
await this.db.getRepository('settlements').update({
values: summaryPeriod,
filter: {
id: settlementsId,
},
});
await this.db.getModel('settlement_items').bulkCreate(createDatas);
await this.db.getModel('settlement_history_items').bulkCreate(createCategoryDatasItem.history);
await this.db.getModel('settlement_history_items').bulkCreate(createProductDatasItem.history);
await this.db.getModel('settlement_summary_items').bulkCreate(summaryItems);
}
async settlement(settlementAbout: Settlement, utcOffset) {
const calc = {
start: settlementAbout.start_date, //开始时间
end: settlementAbout.end_date, //结束时间
rent: settlementAbout.rent,
maintenance: settlementAbout.maintenance, //维修人工
n_compensate: settlementAbout.n_compensate, //无物赔偿
h_compensate: settlementAbout.h_compensate, //有物赔偿
loadfreight: settlementAbout.loadfreight, //装卸运费
current_expenses: settlementAbout.current_expenses, //本期费用
tax: settlementAbout.tax, //税率
accumulate: settlementAbout.accumulate, //累计费用
current_collection: settlementAbout.current_collection, //本期收款
accumulate_collection: settlementAbout.accumulate_collection, //累计收款
history: settlementAbout.settlement_history_items, //历史订单
list: settlementAbout.settlement_items, //当前订单
addItems: settlementAbout.settlement_add_items, //人工增补项
summary: settlementAbout.settlement_summary_items, //汇总项
utcOffset: utcOffset,
};
calc.list = calc.list?.filter(Boolean);
const product = await this.db.getRepository('product').find();
calc.list.forEach((value) => {
const filterValue = product.filter((productValue) => {
const productName = value.category !== '0' ? (value.name as string).split('-')[0] : value.name;
return (
productName && (productValue.dataValues.name === productName || productValue.dataValues.label === productName)
);
});
value['productSort'] = filterValue.length ? filterValue[0].dataValues.sort : -1;
});
calc.list?.sort((a, b) => {
return new Date(a.date).getTime() - new Date(b.date).getTime();
});
let sortProduct = [];
let settlementDate = '';
calc.list.forEach((value) => {
const productDate = converDate(value.date, 'YYYY-MM-DD');
if (value.category === '0' || value.name.includes('-')) {
if (productDate === settlementDate) {
sortProduct.sort((a, b) => {
return a.productSort - b.productSort;
});
sortProduct.forEach((item, index) => {
item.date = dayjs(`${productDate} 00:${index}:00`);
});
value.date = dayjs(sortProduct[sortProduct.length - 1].date).add(1, 'minutes');
sortProduct.push(value);
} else {
settlementDate = productDate;
sortProduct = [];
sortProduct.push(value);
}
}
});
calc.list.forEach((value) => {
const productDate = converDate(value.date, 'YYYY-MM-DD');
if ((value.name as string).includes('-')) {
const name = value.name.split('-')[0];
const valueItem = calc.list.filter(
(item) => converDate(item.date, 'YYYY-MM-DD') === productDate && item.name === name,
)[0];
value.date = dayjs(valueItem.date).add(1, 'seconds');
}
});
calc.list?.sort((a, b) => {
return new Date(a.date).getTime() - new Date(b.date).getTime();
});
const contracts = settlementAbout.contracts;
return { calc, contracts };
}
}
/**
* 计算订单实际重量
* @param rule
* @param item
* @param settlementsId
*/
const recordWeight = (rule, item, settlementsId, productRule, rulefee?) => {
const productCategory = productRule.product_id > RulesNumber ? 'category' : 'product';
const spec = rulefee.product.spec;
const name = rulefee.product.name;
if (item.weight_items.length) {
const itemWeight = item.weight_items.filter(
(weightItem) =>
(productRule.product_id > RulesNumber &&
productRule.product_id - RulesNumber === weightItem.product_category_id) ||
productRule.product_id === weightItem.product_category_id,
)[0];
const productsName = item.record_items?.filter(
(value) => value.product.category_id === itemWeight.product_category_id,
)[0].product;
const productName = productCategory === 'category' ? productsName.name : productsName.label;
return {
settlement_id: settlementsId,
date: item.date,
name: productName + '-' + spec,
label: productsName.label + '-' + spec,
category: rulefee ? name : rule.product.name,
movement: item.movement,
count: itemWeight.weight,
unit_price: rulefee.unit_price,
amount: itemWeight.weight * rulefee.unit_price,
unit_name: '吨',
is_excluded: false,
};
} else {
if (
(productRule.product_id > RulesNumber &&
productRule.product_id - RulesNumber === item.record_items[0]?.product.category_id) ||
productRule.product_id === item.record_items[0]?.product.category_id
) {
let count = item.weight;
item.record_items.forEach((recordItem) => {
if (recordItem.record_item_fee_items.length) {
const recordItemFee = recordItem.record_item_fee_items.filter(
(value) => value.product_id === rulefee.fee_product_id,
)[0];
count = recordItemFee.is_excluded ? count - recordItemFee.count : count;
}
});
const productsName = item.record_items[0].product;
const productName = productCategory === 'category' ? productsName.name : productsName.label;
return {
settlement_id: settlementsId,
date: item.date,
name: productName + '-' + spec,
label: productsName.label + '-' + spec,
category: name,
movement: item.movement,
count: count,
unit_price: rulefee.unit_price,
amount: item.weight * rulefee.unit_price,
unit_name: '吨',
is_excluded: false,
};
}
}
};
/**
* 产品规则计算逻辑
* @param rules 规则
* @param item 当前的订单
* @param itemCount 需要计算的订单数量
* @returns count,unit 返回了最后的计算数量和单位
*/
const ruleCount = (rules: FeeRule | LeaseRule, item: Record, recordItem: recordItems, valueCount?, rulefee?) => {
let count, unit;
const itemCount = valueCount ? valueCount : recordItem.count;
const conversion_logic_id = rulefee ? rulefee.conversion_logic_id : rules.conversion_logic_id;
if (conversion_logic_id === ConversionLogics.Product) {
// 换算:2
// 查产品分类,看产品分类是否需要换算
count = recordItem.product.product_category.convertible ? itemCount * recordItem.product.ratio : itemCount;
unit = recordItem.product.product_category.convertible
? recordItem.product.product_category.conversion_unit
: recordItem.product.product_category.unit;
} else if (conversion_logic_id === ConversionLogics.Keep) {
// 不换算:1
count = itemCount;
unit = recordItem.product.product_category.unit;
} else if (conversion_logic_id === ConversionLogics.ProductWeight) {
// 换算4 按照产品表重量
count = itemCount * recordItem.product.weight;
unit = recordItem.product.product_category.unit;
} else {
const rule = rules?.ucl?.weight_items.filter(
(value) =>
value.product_id === recordItem.product_id || value.product_id - RulesNumber === recordItem.product.category_id,
)[0];
// 按重量换算
if (rule && rule.conversion_logic_id === ConversionLogics.Keep) {
// 不换算
count = itemCount * rule.weight;
} else if (rule && rule.conversion_logic_id === ConversionLogics.Product) {
// 换算
count = recordItem.product.product_category.convertible
? itemCount * recordItem.product.ratio * rule.weight
: itemCount;
} else {
count = 0;
}
unit = recordItem.product.product_category.convertible
? recordItem.product.product_category.conversion_unit
: recordItem.product.product_category.unit;
}
unit = rulefee ? rulefee.unit : unit;
const { converCount, converUnit } = converUnitCount(count, unit);
count = converCount;
unit = converUnit;
return { count, unit };
};
/**
* 租金天数计算
* @param { calc_type, movement, date } 租金计算方式,出入库,订单日期
* 2计头计尾出库多加一天
* 3不计头不计尾入库多加一天
* 0计头不计尾出入库都加一天
* 其他情况正常计算天数
* 1计尾不计头正常计算天数
* @returns days 根据租金计算方式返回租借天数
*/
const getCalcDays = (start_date, end_date) => {
// 正常计算date到目前天数
const endDate = dayjs(end_date).startOf('day');
const startDate = dayjs(start_date).startOf('day');
const daysDiff = endDate.diff(startDate, 'day') + 1;
return daysDiff;
};
// 返回天数
const dayjsDays = (date) => {
return dayjs(date).startOf('day');
};
// 结存时间
/**
* 租金天数计算
* @param { calc_type, movement, date } 租金计算方式,出入库,订单日期
* 2计头计尾出库多加一天
* 3不计头不计尾入库多加一天
* 0计头不计尾出入库都加一天
* 其他情况正常计算天数
* 1计尾不计头正常计算天数
* @returns days 根据租金计算方式返回租借天数
*/
const afterDays = (calc_type, movement, start, end) => {
const l = dayjs(end).startOf('day');
const r = dayjs(start).startOf('day');
let ofterDays = l.diff(r, 'day');
switch (calc_type) {
case CalcDateType.countHeads:
ofterDays += 1;
break;
case CalcDateType.countTails:
break;
case CalcDateType.countHT:
if (movement === '-1') {
ofterDays += 1;
}
break;
case CalcDateType.withoutHT:
if (movement === '1') {
ofterDays += 1;
}
break;
}
return ofterDays;
};
const feeData = (data, settlementAbout: Settlement, type) => {
const feeItem = {};
const fee = [];
if (data.length) {
data.forEach((value) => {
let name = value.name;
if (value.productCategory === 'category') {
name = value.name;
} else if (value.productCategory === 'product') {
name = value.label;
}
let listKey = `${value.name}_${value.movement}_${converDate(value.date, 'YYYY-MM-DD')}`;
switch (type) {
case 'category':
listKey = `${value.name}_${value.movement}_${converDate(value.date, 'YYYY-MM-DD')}`;
break;
case 'product':
listKey = `${value.label}_${value.movement}_${converDate(value.date, 'YYYY-MM-DD')}`;
name = value.label;
}
if (!feeItem[listKey]) {
feeItem[listKey] = {
settlement_id: value.settlement_id,
movement: value.movement,
date: value.date,
amount: value.amount,
category: value.category,
count: value.count,
days: 0,
name: name,
unit_name: value.unit_name,
unit_price: value.unit_price,
is_excluded: value.is_excluded,
type: type,
};
} else {
feeItem[listKey].count = feeItem[listKey].count + value.count;
feeItem[listKey].amount = feeItem[listKey].amount + value.amount;
feeItem[listKey].unit_price = isNaN(feeItem[listKey].amount / feeItem[listKey].count)
? 0
: feeItem[listKey].amount / feeItem[listKey].count;
}
});
}
fee.push(...Object.values(feeItem));
return fee;
};
const recordItemsFee = (rule, item, recordItem, count, rulefee) => {
let recordCount = count;
if (recordItem.record_item_fee_items.length) {
const recordItemFee = recordItem.record_item_fee_items.filter(
(value) => value.product_id === rulefee.fee_product_id,
)[0];
if (recordItemFee) {
const { count, unit } = ruleCount(rule, item, recordItem, recordItemFee.count, rulefee);
recordCount = recordItemFee.is_excluded ? recordCount - count : recordCount;
}
}
return recordCount;
};
const formatNumber = (count) => {
const c = formatQuantity(count, 5);
return parseFloat(c.replace(/,/g, ''));
};
/**
* 筛选租赁信息处理条件
* @param data 当前需要处理的订单
* @param settlementAbout 合同中统计的信息
* @returns screenDatas 一个对象中包含了历史订单和当期订单
*/
const screenData = (data, settlementAbout, type) => {
const history = {};
const list = {};
const screenDatas = {
history: [],
list: [],
};
data.forEach((value) => {
let name = value.name;
if (value.productCategory === 'category') {
name = value.name;
} else if (value.productCategory === 'product') {
name = value.label;
}
let listKey = `${name}_${value.movement}_${converDate(value.date, 'YYYY-MM-DD')}`;
let historyKey = `${name}`;
switch (type) {
case 'category':
listKey = `${name}_${value.movement}_${converDate(value.date, 'YYYY-MM-DD')}`;
historyKey = `${name}`;
break;
case 'product':
listKey = `${value.label}_${value.movement}_${converDate(value.date, 'YYYY-MM-DD')}`;
historyKey = `${value.label}`;
name = value.label;
break;
}
if (dayjs(value.date).isBefore(settlementAbout.start_date)) {
if (!history[historyKey]) {
history[historyKey] = {
settlement_id: value.settlement_id,
amount: value.amount,
category: value.category,
count: value.count,
days: getCalcDays(settlementAbout.start_date, settlementAbout.end_date),
name: name,
unit_name: value.unit_name,
unit_price: value.unit_price,
is_excluded: value.is_excluded,
type: type,
};
} else {
history[historyKey].count = formatNumber(history[historyKey].count) + formatNumber(value.count);
history[historyKey].amount = formatNumber(history[historyKey].amount) + formatNumber(value.amount);
history[historyKey].unit_price =
history[historyKey].amount / history[historyKey].count / history[historyKey].days;
}
} else {
if (!list[listKey]) {
list[listKey] = {
settlement_id: value.settlement_id,
movement: value.movement,
date: value.date,
amount: value.amount,
category: value.category,
count: value.count,
days: value.days,
name: name,
unit_name: value.unit_name,
unit_price: value.unit_price,
is_excluded: value.is_excluded,
type: type,
};
} else {
list[listKey].count = formatNumber(list[listKey].count) + formatNumber(value.count);
list[listKey].amount = formatNumber(list[listKey].amount) + formatNumber(value.amount);
list[listKey].unit_price = isNaN(list[listKey].amount / list[listKey].count / list[listKey].days)
? 0
: list[listKey].amount / list[listKey].count / list[listKey].days;
}
}
});
screenDatas['history'].push(...Object.values(history));
screenDatas['list'].push(...Object.values(list));
return screenDatas;
};