calc_program.js 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. /**
  2. * Created by CSL on 2017-07-19.
  3. * dispExpr: F8*(L-1); expression: "@('8') * (L-1)";
  4. * 说明:F后跟行号,L替换人工系数值,@后跟ID。用到L的规则必须有labourCoeID属性(反过来不要求),
  5. * 用到费率的规则必须有feeRateID属性,当有该属性时,会自动显示费率值。
  6. */
  7. let billDefaultTemplate = [
  8. {
  9. ID: 1,
  10. serialNo: '一',
  11. code: "A",
  12. name: "定额直接费",
  13. dispExpr: "A1+A2+A3",
  14. statement: "人工费+材料费+机械费",
  15. feeRate: null,
  16. type: 'RationDirect',
  17. memo: ''
  18. },
  19. {
  20. ID: 2,
  21. serialNo: '1',
  22. code: "A1",
  23. name: "人工费",
  24. dispExpr: "H_J",
  25. statement: "合计",
  26. feeRate: 0,
  27. type: 'labour',
  28. memo: ''
  29. },
  30. {
  31. ID: 3,
  32. serialNo: '2',
  33. code: "A2",
  34. name: "材料费",
  35. dispExpr: "H_J",
  36. statement: "合计",
  37. feeRate: 100,
  38. type: 'material',
  39. memo: ''
  40. },
  41. {
  42. ID: 4,
  43. serialNo: '3',
  44. code: "A3",
  45. name: "机械费",
  46. dispExpr: "H_J",
  47. statement: "合计",
  48. feeRate: 0,
  49. type: 'machine',
  50. memo: ''
  51. },
  52. {
  53. ID: 5,
  54. serialNo: '二',
  55. code: "A4",
  56. name: "管理费",
  57. dispExpr: "A",
  58. statement: "定额直接费",
  59. feeRate: 0,
  60. type: 'management',
  61. memo: ''
  62. },
  63. {
  64. ID: 6,
  65. serialNo: '三',
  66. code: "B",
  67. name: "利润",
  68. dispExpr: "A",
  69. statement: "定额直接费",
  70. feeRate: 0,
  71. type: 'profit',
  72. memo: ''
  73. },
  74. {
  75. ID: 7,
  76. serialNo: '四',
  77. code: "C",
  78. name: "风险费用",
  79. dispExpr: "",
  80. statement: "",
  81. feeRate: null,
  82. type: 'risk',
  83. memo: ''
  84. },
  85. {
  86. ID: 8,
  87. serialNo: '',
  88. code: "",
  89. name: "综合单价",
  90. dispExpr: "A+B",
  91. statement: "定额直接费+利润",
  92. feeRate: NaN,
  93. type: 'common',
  94. memo: ''
  95. }
  96. ];
  97. class CalcProgram {
  98. constructor(project){
  99. this.project = project;
  100. this.datas = [];
  101. this.digit = 2;
  102. this.digitDefault = 6;
  103. this.calc = new Calculation();
  104. project.registerModule(ModuleNames.calc_program, this);
  105. };
  106. getSourceType () {
  107. return ModuleNames.calc_program;
  108. };
  109. loadData (datas) {
  110. this.datas = datas;
  111. };
  112. doAfterUpdate (err, data) {
  113. if(!err){
  114. // do
  115. }
  116. };
  117. // 经测试,全部编译一次耗时0.003~0.004秒。耗时基本忽略不计。
  118. compileAllTemps(){
  119. let calcFeeRates = this.project.FeeRate.datas.rates;
  120. let calcLabourCoes = this.project.labourCoe.datas.coes;
  121. let calcTemplates = this.project.calcProgram.datas.templates;
  122. this.calc.compilePublics(calcFeeRates, calcLabourCoes, feeType, rationCalcBase);
  123. for (let ct of calcTemplates){
  124. this.calc.compileTemplate(ct);
  125. };
  126. // 存储费率临时数据,报表用。
  127. if (this.calc.saveForReports.length > 0){
  128. let saveDatas = {};
  129. saveDatas.projectID = projectInfoObj.projectInfo.ID;
  130. saveDatas.calcItems = this.calc.saveForReports;
  131. CommonAjax.post('/calcProgram/saveCalcItems', saveDatas, function (data) {
  132. this.calc.saveForReports = [];
  133. });
  134. };
  135. };
  136. calculate(treeNode){
  137. let me = this;
  138. if (treeNode.sourceType === this.project.Ration.getSourceType()) {
  139. treeNode.data.gljList = this.project.ration_glj.getGljArrByRation(treeNode.data.ID);
  140. }
  141. else if (treeNode.sourceType === this.project.Bills.getSourceType()) {
  142. let rations = this.project.Ration.getBillsSortRation(treeNode.source.getID());
  143. treeNode.data.gljList = this.project.ration_glj.getGatherGljArrByRations(rations);
  144. };
  145. this.calc.calculate(treeNode);
  146. // 存储、刷新本结点、所有父结点
  147. if (treeNode.changed) {
  148. me.saveAndCalcParents(treeNode);
  149. delete treeNode.changed;
  150. };
  151. };
  152. saveAndCalcParents(treeNode) {
  153. if (treeNode.parent) {
  154. projectObj.converseCalculateBills(treeNode.parent);
  155. };
  156. let data = {ID: treeNode.data.ID, projectID: projectObj.project.ID(), fees: treeNode.data.fees};
  157. let newDta = {'updateType': 'ut_update', 'updateData': data};
  158. let newDataArr = [];
  159. newDataArr.push(newDta);
  160. projectObj.project.pushNow('', treeNode.sourceType, newDataArr);
  161. projectObj.mainController.refreshTreeNode([treeNode]);
  162. };
  163. initFees(treeNode){
  164. if (!treeNode.data.fees) {
  165. treeNode.data.fees = [];
  166. treeNode.data.feesIndex = {};
  167. treeNode.changed = true;
  168. };
  169. };
  170. checkFee(treeNode, ftObj){
  171. if (!treeNode.data.feesIndex[ftObj.type]){
  172. let fee = {
  173. 'fieldName': ftObj.type,
  174. 'unitFee': ftObj.unitFee,
  175. 'totalFee': ftObj.totalFee,
  176. 'tenderUnitFee': 0,
  177. 'tenderTotalFee': 0
  178. };
  179. treeNode.data.fees.push(fee);
  180. treeNode.data.feesIndex[ftObj.type] = fee;
  181. treeNode.changed = true;
  182. }
  183. else{
  184. if (treeNode.data.feesIndex[ftObj.type].unitFee != ftObj.unitFee){
  185. treeNode.data.feesIndex[ftObj.type].unitFee = ftObj.unitFee;
  186. treeNode.changed = true;
  187. };
  188. if (treeNode.data.feesIndex[ftObj.type].totalFee != ftObj.totalFee){
  189. treeNode.data.feesIndex[ftObj.type].totalFee = ftObj.totalFee;
  190. treeNode.changed = true;
  191. };
  192. };
  193. };
  194. gatherFeeTypes(treeNode, gatherType){
  195. let me = this;
  196. let rst = [];
  197. if (treeNode.sourceType === this.project.Bills.getSourceType()) {
  198. me.initFees(treeNode);
  199. let objsArr = [];
  200. if (gatherType == CP_GatherType.rations){
  201. objsArr = this.project.Ration.getRationsByNode(treeNode);
  202. }else if (gatherType == CP_GatherType.bills){
  203. objsArr = treeNode.children;
  204. };
  205. for (let ft of feeType) {
  206. let ftObj = {};
  207. ftObj.type = ft.type;
  208. ftObj.name = ft.name;
  209. let uf = 0, tf = 0, tuf = 0, ttf = 0;
  210. for (let item of objsArr) {
  211. let data = {};
  212. if (gatherType == CP_GatherType.rations){
  213. data = item;
  214. }else if (gatherType == CP_GatherType.bills){
  215. data = item.data;
  216. };
  217. if (data.feesIndex && data.feesIndex[ft.type]) {
  218. uf = (uf + parseFloat(data.feesIndex[ft.type].unitFee)).toDecimal(me.digitDefault);
  219. tf = (tf + parseFloat(data.feesIndex[ft.type].totalFee)).toDecimal(me.digitDefault);
  220. tuf = (tuf + parseFloat(data.feesIndex[ft.type].tenderUnitFee)).toDecimal(me.digitDefault);
  221. ttf = (ttf + parseFloat(data.feesIndex[ft.type].tenderTotalFee)).toDecimal(me.digitDefault);
  222. };
  223. };
  224. ftObj.unitFee = uf.toDecimal(me.digit);
  225. ftObj.totalFee = tf.toDecimal(me.digit);
  226. ftObj.tenderUnitFee = tuf.toDecimal(me.digit);
  227. ftObj.tenderTotalFee = ttf.toDecimal(me.digit);
  228. me.checkFee(treeNode, ftObj);
  229. rst.push(ftObj);
  230. };
  231. if (treeNode.changed) {
  232. me.saveAndCalcParents(treeNode);
  233. delete treeNode.changed;
  234. };
  235. };
  236. return rst;
  237. };
  238. getCalcDatas(treeNode){
  239. let me = this;
  240. let rst = [];
  241. let isRation = treeNode.sourceType === me.project.Ration.getSourceType();
  242. let isBill = treeNode.sourceType === me.project.Bills.getSourceType();
  243. let isLeafBill = isBill && treeNode.source.children && treeNode.source.children.length === 0;
  244. let isBillPriceCalc = me.project.projSetting.billsCalcMode === billsPrice;
  245. if (isRation) { // 清单单价计算模式下的叶子清单:取自己的计算程序ID,找到自己的计算程序计算。
  246. me.calculate(treeNode);
  247. rst = treeNode.data.calcTemplate.calcItems;
  248. }
  249. else if (isLeafBill) {
  250. let ct = '';
  251. if (treeNode.children && treeNode.children.length > 0){
  252. if (treeNode.children[0].sourceType == me.project.Ration.getSourceType()){
  253. ct = childrenType.ration;
  254. }
  255. else if (treeNode.children[0].sourceType == me.project.VolumePrice.getSourceType()){
  256. ct = childrenType.volumePrice;
  257. };
  258. }
  259. else{
  260. ct = childrenType.formula;
  261. };
  262. if (ct == childrenType.ration){
  263. if (isBillPriceCalc){ // 清单单价计算模式下的叶子清单:取自己的计算程序ID,找到自己的计算程序计算。
  264. me.calculate(treeNode);
  265. rst = treeNode.data.calcTemplate.calcItems;
  266. }else{ // 前三种计算模式下的叶子清单:汇总定额的计算程序的费用类别
  267. rst = me.gatherFeeTypes(treeNode, CP_GatherType.rations);
  268. };
  269. }else if (ct == childrenType.volumePrice){
  270. rst = [];
  271. }else if (ct == childrenType.formula){
  272. rst = [];
  273. };
  274. }
  275. else if (isBill){ // 父清单:汇总子清单的费用类别
  276. rst = me.gatherFeeTypes(treeNode, CP_GatherType.bills);
  277. };
  278. return rst;
  279. }
  280. }