calc_util.js 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /**
  2. * Created by Tony on 2017/6/21.
  3. * Modified by CSL, 2017-08-01
  4. */
  5. let executeObj = {
  6. ration: null,
  7. at: function(ID) {
  8. let me = executeObj,
  9. rst = 0;
  10. rst = me.ration.data.calcTemplate.compiledTemplate[ID].unitFee;
  11. rst = parseFloat(rst);
  12. return rst;
  13. },
  14. base: function(calcBaseName) {
  15. let me = executeObj, rst = 0,
  16. base = getRationCalcBase(calcBaseName);
  17. if (base != null) {
  18. let price = 0, tmpSum = 0;
  19. for (let glj of me.ration.data.gljList) {
  20. if (base.gljTypes.indexOf(glj.type) >= 0) {
  21. if (base.calcType == baseCalc){ price = glj["basePrice"];}
  22. else if (base.calcType == adjustCalc){price = glj["adjustPrice"];}
  23. else if (base.calcType == budgetCalc){price = glj["marketPrice"];}
  24. else if (base.calcType == diffCalc){price = glj["marketPrice"] - glj["adjustPrice"];};
  25. };
  26. tmpSum = tmpSum + glj["quantity"] * price;
  27. glj = null;
  28. };
  29. rst = tmpSum;
  30. };
  31. return rst;
  32. }
  33. /* factor: function(factorID) {
  34. let me = executeObj;
  35. let rst = 7.77;
  36. return rst;
  37. }*/
  38. };
  39. class Calculation {
  40. /* init(template, feeRates){
  41. let me = this;
  42. me.template = template;
  43. me.feeRates = feeRates;
  44. me.hasCompiled = false;
  45. };*/
  46. compile(template, feeRates, labourCoes){
  47. let me = this;
  48. template.hasCompiled = false;
  49. template.errs = [];
  50. let private_extract_ID = function(str, idx){
  51. let rst = '', lBracket = 0, rBracket = 0, firstIdx = idx, lastIdx = 0;
  52. for (let i = idx; i < str.length; i++) {
  53. if (str[i] === '(') {
  54. lBracket++;
  55. if (lBracket == 1) firstIdx = i + 1;
  56. }
  57. if (str[i] === ')') {
  58. rBracket++;
  59. if (lBracket == rBracket) {
  60. lastIdx = i - 1;
  61. if (lastIdx > firstIdx) {
  62. if (str[firstIdx] === "'") firstIdx++;
  63. if (str[lastIdx] !== "'") lastIdx++;
  64. if (lastIdx > firstIdx) {
  65. rst = str.slice(firstIdx, lastIdx);
  66. }
  67. }
  68. break;
  69. }
  70. }
  71. }
  72. return rst;
  73. };
  74. let private_parse_ref = function(item, itemIdx){
  75. let idx = item.expression.indexOf('@(', 0);
  76. while (idx >= 0) {
  77. let ID = private_extract_ID(item.expression, idx);
  78. if (ID.length > 0) {
  79. let subItem = template.compiledTemplate[ID];
  80. if (subItem) {
  81. if (subItem.ID !== item.ID) {
  82. private_parse_ref(subItem, template.compiledTemplate[ID + "_idx"]);
  83. } else {
  84. template.errs.push("There exists the self refer ID: " + ID);
  85. }
  86. } else {
  87. template.errs.push("There exists the invalid ID by which could not find the item: " + ID);
  88. console.log('invalid ID: ' + ID);
  89. }
  90. }
  91. idx = item.expression.indexOf('@(', idx + ID.length + 3);
  92. }
  93. if (template.compiledSeq.indexOf(itemIdx) < 0) {
  94. template.compiledSeq.push(itemIdx);
  95. }
  96. };
  97. let private_setup_seq = function(item, itemIdx){
  98. if (template.compiledSeq.indexOf(itemIdx) < 0) {
  99. private_parse_ref(item, itemIdx);
  100. }
  101. };
  102. let private_compile_items = function() {
  103. for (let idx of template.compiledSeq) {
  104. let item = template.calcItems[idx];
  105. item.compiledExpr = item.expression.split('@(').join('$CE.at(');
  106. item.compiledExpr = item.compiledExpr.split('base(').join('$CE.base(');
  107. //item.compiledExpr = item.compiledExpr.split('rate(').join('$CE.rate(');
  108. //item.compiledExpr = item.compiledExpr.split('factor(').join('$CE.factor(');
  109. if (item.labourCoeID){
  110. let lc = me.compiledLabourCoes["LabourCoe_" + item.labourCoeID].coe;
  111. item.dispExpr = item.dispExpr.replace(/L/gi, lc.toString());
  112. item.compiledExpr = item.compiledExpr.replace(/L/gi, lc.toString());
  113. }
  114. }
  115. };
  116. let private_compile_feeFile = function() {
  117. if (feeRates) {
  118. me.compiledFeeRate = {};
  119. for (let rate of feeRates) {
  120. me.compiledFeeRate["feeRate_" + rate.ID] = rate;
  121. }
  122. }
  123. };
  124. let private_compile_labourCoeFile = function() {
  125. if (labourCoes) {
  126. me.compiledLabourCoes = {};
  127. for (let coe of labourCoes) {
  128. me.compiledLabourCoes["LabourCoe_" + coe.ID] = coe;
  129. }
  130. }
  131. };
  132. if (template && template.calcItems && template.calcItems.length > 0) {
  133. template.compiledSeq = [];
  134. template.compiledTemplate = {};
  135. //1. first round -> prepare
  136. private_compile_feeFile();
  137. private_compile_labourCoeFile();
  138. for (let i = 0; i < template.calcItems.length; i++) {
  139. let item = template.calcItems[i];
  140. template.compiledTemplate[item.ID] = item;
  141. template.compiledTemplate[item.ID + "_idx"] = i;
  142. }
  143. //2. second round -> go!
  144. for (let i = 0; i < template.calcItems.length; i++) {
  145. private_setup_seq(template.calcItems[i], i);
  146. }
  147. if (template.errs.length == 0) {
  148. private_compile_items();
  149. template.hasCompiled = true;
  150. } else {
  151. console.log('errors: ' + template.errs.toString());
  152. }
  153. }
  154. };
  155. calculate($RATION){ // 参数$RATION也可以是清单
  156. let me = this;
  157. let template = $RATION.data.calcTemplate;
  158. if ($RATION && template.hasCompiled) {
  159. let $CE = executeObj;
  160. $CE.ration = $RATION;
  161. if (!$RATION.fees) {
  162. $RATION.fees = [];
  163. $RATION.feesIndex = {};
  164. };
  165. for (let idx of template.compiledSeq) {
  166. let calcItem = template.calcItems[idx];
  167. let feeRate = 100; // 100%
  168. // 下面三项用于界面显示。
  169. if (calcItem.feeRateID) {
  170. feeRate = me.compiledFeeRate["feeRate_" + calcItem.feeRateID].rate;
  171. calcItem.feeRate = feeRate;
  172. };
  173. calcItem.unitFee = eval(calcItem.compiledExpr) * feeRate * 0.01; // 如果eval()对清单树有影响,就换成小麦的Expression对象再试
  174. calcItem.totalFee = calcItem.unitFee * 3; // AAAAAA 测试值,因目前定额无数量(保存不上) $RATION.data.Quantity
  175. // 费用同步到定额
  176. // 引入小麦的字段检测后,快速切换定额出现计算卡顿现象,过多的循环造成。这里把她的代码拆出来,减少微循环。
  177. if (!$RATION.feesIndex[calcItem.fieldName]){
  178. let fee = {
  179. 'fieldName': calcItem.fieldName,
  180. 'unitFee': calcItem.unitFee,
  181. 'totalFee': calcItem.totalFee,
  182. 'tenderUnitFee': 0,
  183. 'tenderTotalFee': 0
  184. };
  185. $RATION.fees.push(fee);
  186. $RATION.feesIndex[calcItem.fieldName] = fee;
  187. }
  188. else{
  189. $RATION.feesIndex[calcItem.fieldName].unitFee = calcItem.unitFee;
  190. $RATION.feesIndex[calcItem.fieldName].totalFee = calcItem.totalFee;
  191. }
  192. }
  193. }
  194. }
  195. }
  196. //module.exports = new calculation();