calculate_util.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  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. * @return {Number}
  30. */
  31. function getProgressiveFee(baseFee, name, progressiveData, decimal) {
  32. if (!progressiveData) {
  33. throw '该项目不存在累进区间数据';
  34. }
  35. //根据基数名称匹配累进库数据,标准化以免(())等不同导致不匹配
  36. const matchProgressiveData = progressiveData.find(item => standar(item.name) === standar(name));
  37. if (!matchProgressiveData) {
  38. throw `计算基数{${name}}不存在累进区间数据`;
  39. }
  40. // 将原始数据转换成方便处理的数据:[{feeRate: xx, min: 0, max: 200, minOpr: '(', maxOpr: ']'}]
  41. const progression = matchProgressiveData.progression.map(item => {
  42. // item.interval内容: eg (0,200]、[300,500) [1000,+)....
  43. const interval = standar(item.interval);
  44. // ( => 大于 [ => 大于等于 ) => 小于 ] => 小于等于
  45. const minReg = /([\(\[])(\d+)/;
  46. const minMatch = minReg.exec(interval);
  47. if (!minMatch || !minMatch[1] || !minMatch[2]) {
  48. throw `计算基数{${name}}累进区间数据错误`;
  49. }
  50. const minOpr = minMatch[1];
  51. // 后台数据单位为万元,这里转为为元
  52. const min = parseFloat(minMatch[2]) * 10000;
  53. const maxReg = /[\,,]([\d\+]+)([\)\]])/;
  54. const maxMatch = maxReg.exec(interval);
  55. if (!maxMatch || !maxMatch[1] || !maxMatch[2]) {
  56. throw `计算基数{${name}}累进区间数据错误`;
  57. }
  58. const max = maxMatch[1] === '+' ? 'infinity' : parseFloat(maxMatch[1]) * 10000;
  59. const maxOpr = maxMatch[2];
  60. return {
  61. feeRate: item.feeRate,
  62. min,
  63. minOpr,
  64. max,
  65. maxOpr
  66. }
  67. });
  68. progression.sort((a, b) => a.min - b.min);
  69. // 基数所在区间
  70. const withinData = progression.find(item => {
  71. const oprMiddle = item.max === 'infinity' ? '+' : '';
  72. const oprLink = item.minOpr + oprMiddle + item.maxOpr;
  73. switch (oprLink) {
  74. case '()':
  75. return baseFee > item.min && baseFee < item.max;
  76. case '(]':
  77. return baseFee > item.min && baseFee <= item.max;
  78. case '[)':
  79. return baseFee >= item.min && baseFee < item.max;
  80. case '[]':
  81. return baseFee >= item.min && baseFee <= item.max;
  82. case '(+)':
  83. case '(+]':
  84. return baseFee > item.min;
  85. case '[+)':
  86. case '[+]':
  87. return baseFee >= item.min;
  88. default:
  89. return false;
  90. }
  91. });
  92. if (!withinData) {
  93. return 0;
  94. }
  95. // 累进计算
  96. let fee = 0;
  97. //累进之前的区间
  98. for (let i = 0; i < progression.indexOf(withinData); i++) {
  99. const perData = progression[i];
  100. fee += (perData.max - perData.min) * perData.feeRate * 0.01;
  101. }
  102. //累进所在区间
  103. fee += (baseFee - withinData.min) * withinData.feeRate * 0.01;
  104. return scMathUtil.roundForObj(fee, decimal);
  105. }
  106. return {
  107. getProgressiveFee,
  108. };
  109. });