calculate_util.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. 'use strict';
  2. ((factory) => {
  3. if (typeof module !== 'undefined') {
  4. const scMathUtil = require('./scMathUtil').getUtil();
  5. module.exports = factory(scMathUtil);
  6. } else {
  7. window.calculateUtil = factory(scMathUtil);
  8. }
  9. })((scMathUtil) => {
  10. function standar(exp) {
  11. //去空格
  12. exp = exp.replace(/\s/g, '');
  13. //( to (
  14. exp = exp.replace(/(/g, '(');
  15. //)to )
  16. exp = exp.replace(/)/g, ')');
  17. //,to ,
  18. exp = exp.replace(/,/g, ',');
  19. //f to F
  20. exp = exp.replace(new RegExp('f', 'g'), 'F');
  21. return exp;
  22. }
  23. /**
  24. * 获取累进办法计算的金额
  25. * @param {Number} baseFee - 基准金额
  26. * @param {String} name - 使用累进计算的基数名称(需要与累进库中的名称匹配)
  27. * @param {Array} progressiveData - 项目的累进数据(property.progressiveInterval)
  28. * @param {Number} decimal - 精度
  29. * @param {Object} deficiency - 不足处理映射 @example: {'路线工程监理费': 20000 } // 不足2万按2万
  30. * @return {Number}
  31. */
  32. function getProgressiveFee(baseFee, name, progressiveData, decimal, deficiency) {
  33. if (!progressiveData) {
  34. throw '该项目不存在累进区间数据';
  35. }
  36. //根据基数名称匹配累进库数据,标准化以免(())等不同导致不匹配
  37. const matchProgressiveData = progressiveData.find(item => standar(item.name) === standar(name));
  38. if (!matchProgressiveData) {
  39. throw `计算基数{${name}}不存在累进区间数据`;
  40. }
  41. // 将原始数据转换成方便处理的数据:[{feeRate: xx, min: 0, max: 200, minOpr: '(', maxOpr: ']'}]
  42. const progression = matchProgressiveData.progression.map(item => {
  43. // item.interval内容: eg (0,200]、[300,500) [1000,+)....
  44. const interval = standar(item.interval);
  45. // ( => 大于 [ => 大于等于 ) => 小于 ] => 小于等于
  46. const minReg = /([\(\[])(\d+)/;
  47. const minMatch = minReg.exec(interval);
  48. if (!minMatch || !minMatch[1] || !minMatch[2]) {
  49. throw `计算基数{${name}}累进区间数据错误`;
  50. }
  51. const minOpr = minMatch[1];
  52. // 后台数据单位为万元,这里转为为元
  53. const min = parseFloat(minMatch[2]) * 10000;
  54. const maxReg = /[\,,]([\d\+]+)([\)\]])/;
  55. const maxMatch = maxReg.exec(interval);
  56. if (!maxMatch || !maxMatch[1] || !maxMatch[2]) {
  57. throw `计算基数{${name}}累进区间数据错误`;
  58. }
  59. const max = maxMatch[1] === '+' ? 'infinity' : parseFloat(maxMatch[1]) * 10000;
  60. const maxOpr = maxMatch[2];
  61. return {
  62. feeRate: item.feeRate,
  63. min,
  64. minOpr,
  65. max,
  66. maxOpr
  67. }
  68. });
  69. progression.sort((a, b) => a.min - b.min);
  70. // 基数所在区间
  71. const withinData = progression.find(item => {
  72. const oprMiddle = item.max === 'infinity' ? '+' : '';
  73. const oprLink = item.minOpr + oprMiddle + item.maxOpr;
  74. switch (oprLink) {
  75. case '()':
  76. return baseFee > item.min && baseFee < item.max;
  77. case '(]':
  78. return baseFee > item.min && baseFee <= item.max;
  79. case '[)':
  80. return baseFee >= item.min && baseFee < item.max;
  81. case '[]':
  82. return baseFee >= item.min && baseFee <= item.max;
  83. case '(+)':
  84. case '(+]':
  85. return baseFee > item.min;
  86. case '[+)':
  87. case '[+]':
  88. return baseFee >= item.min;
  89. default:
  90. return false;
  91. }
  92. });
  93. if (!withinData) {
  94. return 0;
  95. }
  96. // 累进计算
  97. let fee = 0;
  98. //累进之前的区间
  99. for (let i = 0; i < progression.indexOf(withinData); i++) {
  100. const perData = progression[i];
  101. fee += (perData.max - perData.min) * perData.feeRate * 0.01;
  102. }
  103. //累进所在区间
  104. fee = scMathUtil.roundForObj(fee + (baseFee - withinData.min) * withinData.feeRate * 0.01, decimal);
  105. // 不足处理
  106. const deficiencyFee = deficiency && deficiency[name] || 0;
  107. return deficiencyFee
  108. ? fee > 0 && fee < deficiencyFee
  109. ? deficiencyFee
  110. : fee
  111. : fee;
  112. }
  113. /**
  114. * 判断该基数是否包含累进基数
  115. * @param {String} calcBase - 计算基数
  116. * @param {Array} progression - 累进基数名称数组
  117. * @return {Boolean}
  118. */
  119. function isProgressive(calcBase, progression) {
  120. if (typeof calcBase !== 'string' || !progression) {
  121. return false;
  122. }
  123. const reg = /{[^}]+}/g;
  124. const matched = calcBase.match(reg);
  125. if (!matched) {
  126. return false;
  127. }
  128. return matched.some(mStr => progression.some(pStr => `{${pStr}}` === mStr));
  129. }
  130. return {
  131. getProgressiveFee,
  132. isProgressive,
  133. };
  134. });