calc_program.js 11 KB

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