'use strict'; /** * * * @author Mai * @date * @version */ const math = require('mathjs'); const PayConst = require('../const/deal_pay.js'); const payType = PayConst.payType; const deadlineType = PayConst.deadlineType; class PayCalculate { constructor (ctx, decimal) { this.ctx = ctx; this.percentReg = /[0-9]+%/g; this.decimal = decimal.pay ? decimal.payTp : decimal.tp; } /** * 获取 计算基数 * @returns {Promise} */ async getCalcBase () { if (this.bases) { return; } const bases = await this.ctx.service.stage.getStagePayCalcBase(); this.bases = bases.sort(function (a, b) { if (a && b) { return b.code.indexOf(a.code) === -1 ? 1 : -1; } else { return 0; } }); for (const b of this.bases) { b.reg = new RegExp(b.code, 'igm'); } } calculateExpr(expr) { let formula = expr; for (const b of this.bases) { formula = formula.replace(b.reg, b.value); } const percent = formula.match(this.percentReg); if (percent) { for (const p of percent) { const v = math.eval(p.replace('%', '/100')); formula = formula.replace(p, v); } } return math.eval(formula); } /** * 计算起扣金额、付(扣)款限额 * * @param {Array} pays - (标段)合同支付数据 */ async calculateStartRangePrice (pays) { await this.getCalcBase(); const order = this.ctx.stage.curAuditor ? this.ctx.stage.curAuditor.order : 0; for (const p of pays) { // 非本期,本次添加的合同支付项,不允许计算,其中默认添加的合同支付项,归属于第一期原报 if (p.csorder === this.ctx.stage.order || (p.csorder === 0 || this.ctx.stage.order === 1)) { if (p.csaorder === order) { if (!p.sprice && p.sexpr && p.sexpr !== '') { p.sprice = this.ctx.helper.round(this.calculateExpr(p.sexpr), this.decimal); } if (!p.rprice && p.rexpr && p.rexpr !== '') { p.rprice = this.ctx.helper.round(this.calculateExpr(p.rexpr), this.decimal); } } } } } /** * 累计 计量等数据 */ async getAddCalcRela() { // todo 获取截止上期数据 const pre = null; const cur = await this.ctx.service.stageBills.getSumTotalPrice(this.ctx.stage); const add = {}; if (pre) { add.contract_tp = this.ctx.helper.plus(pre.contract_tp, cur.contract_tp); add.qc_tp = this.ctx.helper.plus(pre.qc_tp, cur.qc_tp); } else { add.contract_tp = cur.contract_tp; add.qc_tp = cur.qc_tp; } add.gather_tp = this.ctx.helper.plus(add.contract_tp, add.qc_tp); return add; } /** * 检查是否到达 计提期限 * @param pay */ checkDeadline(pay, addRela) { if (pay.dl_type === deadlineType.tp.value) { const deadlineTp = addRela[pay.dl_tp_type + '_tp']; if (deadlineTp > pay.dl_tp) { return true; } } else if (pay.dl_type === deadlineType.count.value) { return this.ctx.stage.order >= pay.dl_count; } else { return false; } } /** * 计算本期、截止本期金额 * @param {Array} pays - (标段&期)合同支付数据 */ async calculate(pays) { await this.getCalcBase(); const addRela = await this.getAddCalcRela(); const yfPay = pays.find(function (p) { return p.ptype === payType.yf; }); if (!yfPay) { throw '合同支付数据错误'; } yfPay.tp = 0; for (const p of pays) { if (p.ptype === payType.normal || p.ptype === payType.wc) { if (p.expr && p.expr !== '') { const value = this.ctx.helper.round(this.calculateExpr(p.expr), this.decimal); if (!p.pause && (!p.sprice || addRela.gather_tp > p.sprice)) { if (p.rprice) { if (this.checkDeadline(p)) { p.tp = this.ctx.helper.minus(p.rprice, p.pre_total_price); } else { p.tp = Math.min(this.ctx.helper.minus(p.rprice, p.pre_total_price), value); } } else { p.tp = value; } } else { p.tp = null; } } // 累加 至 应付 if (p.is_yf) { if (p.minus) { yfPay.tp = this.ctx.helper.minus(yfPay.tp, p.tp); } else { yfPay.tp = this.ctx.helper.plus(yfPay.tp, p.tp); } } } p.end_tp = this.ctx.helper.round(this.ctx.helper.plus(p.tp, p.pre_tp), this.decimal); } yfPay.end_tp = this.ctx.helper.plus(yfPay.tp, yfPay.pre_tp); } async calculateAll(pays) { await this.calculateStartRangePrice(pays); await this.calculate(pays); } } module.exports = PayCalculate;