'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, stage, tenderInfo) { this.ctx = ctx; this.stage = stage; this.percentReg = /[0-9]+%/g; this.tenderInfo = tenderInfo; this.decimal = tenderInfo.decimal.pay ? tenderInfo.decimal.payTp : tenderInfo.decimal.tp; } /** * 获取 计算基数 * @returns {Promise} */ async getCalcBase () { if (this.bases) { return; } const bases = await this.ctx.service.stage.getStagePayCalcBase(this.stage, this.tenderInfo); this.bases = bases.sort(function (a, b) { return a.sort - b.sort; // if (a && b) { // return b.code.indexOf(a.code) >= 0 ? 1 : 0; // } else { // return 0; // } }); for (const b of this.bases) { b.reg = new RegExp(b.code, 'igm'); } } calculateTpExpr(pay, first, addRela) { let formula = pay.expr; for (const b of this.bases) { if ((b.code === 'bqwc') && (first && pay.sprice)) { formula = formula.replace(b.reg, this.ctx.helper.sub(addRela.gather_tp, pay.sprice)); } else { 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); } } try { const value = math.eval(formula); return value; } catch(err) { return 0; } } 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); } } try { const value = math.eval(formula); return value; } catch(err) { return 0; } } /** * 计算起扣金额、付(扣)款限额 * * @param {Array} pays - (标段)合同支付数据 */ async calculateStartRangePrice (pays) { await this.getCalcBase(); const order = this.stage.curOrder; for (const p of pays) { // 非本期,本次添加的合同支付项,不允许计算,其中默认添加的合同支付项,归属于第一期原报 if (p.csorder === this.stage.order || (p.csorder === 0 || this.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.stage); const add = {}; if (pre) { add.contract_tp = this.ctx.helper.add(pre.contract_tp, cur.contract_tp); add.qc_tp = this.ctx.helper.add(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.add(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.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) return false; yfPay.tp = 0; for (const p of pays) { if (p.ptype === payType.normal || p.ptype === payType.wc) { if (!p.pause && (!p.sprice || addRela.gather_tp > p.sprice)) { if (p.expr && p.expr !== '') { const first = !(p.pre_tp && !this.ctx.helper.checkZero(p.pre_tp)); const value = this.ctx.helper.round(this.calculateTpExpr(p, first, addRela), this.decimal); if (p.rprice) { if (this.checkDeadline(p, addRela)) { p.tp = this.ctx.helper.sub(p.rprice, p.pre_tp); } else { p.tp = Math.min(this.ctx.helper.sub(p.rprice, p.pre_tp), value); } } else { p.tp = value; } } else if (p.tp && !this.ctx.helper.checkZero(p.tp)) { if (p.rprice) { if (this.checkDeadline(p, addRela)) { p.tp = this.ctx.helper.sub(p.rprice, p.pre_tp); } else { p.tp = Math.min(this.ctx.helper.sub(p.rprice, p.pre_tp), this.ctx.helper.round(p.tp, this.decimal)); } } else { p.tp = this.ctx.helper.round(p.tp, this.decimal); } } } else { p.tp = 0; } // 累加 至 应付 if (p.is_yf) { if (p.minus) { yfPay.tp = this.ctx.helper.sub(yfPay.tp, p.tp); } else { yfPay.tp = this.ctx.helper.add(yfPay.tp, p.tp); } } } p.end_tp = this.ctx.helper.round(this.ctx.helper.add(p.tp, p.pre_tp), this.decimal); } yfPay.end_tp = this.ctx.helper.add(yfPay.tp, yfPay.pre_tp); } async calculateAll(pays) { await this.calculateStartRangePrice(pays); await this.calculate(pays); } } module.exports = PayCalculate;