installation_fee.js 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768
  1. /**
  2. * Created by zhang on 2018/1/31.
  3. */
  4. var installation_fee = {
  5. createNew: function (project) {
  6. // 用户定义private方法
  7. var tools = {};
  8. // 所有通过this访问的属性,都不应在此单元外部进行写入操作
  9. var installation_fee = function (proj) {
  10. // this.project = proj;
  11. this.datas = [];
  12. var sourceType = ModuleNames.installation_fee;
  13. this.getSourceType = function () {
  14. return sourceType;
  15. }
  16. proj.registerModule(ModuleNames.installation_fee, this);
  17. };
  18. // prototype用于定义public方法
  19. installation_fee.prototype.loadData = function (datas) {
  20. this.datas = datas;
  21. };
  22. installation_fee.prototype.getInstallationFeeByLibID=function(libID){
  23. return _.find(this.datas,{'libID':libID});
  24. };
  25. installation_fee.prototype.getInstallationFeeByID=function(ID){
  26. return _.find(this.datas,{'ID':ID});
  27. };
  28. installation_fee.prototype.getFeeRuleByFeeItem = function (feeItem) {
  29. let installFee = projectObj.project.installation_fee.getInstallationFeeByLibID(feeItem.libID);
  30. let impacRules = _.filter(installFee.feeRule,{'feeItemId':feeItem.ID});
  31. return impacRules;
  32. };
  33. installation_fee.prototype.getFeeRuleBySection = function (section) {
  34. let installFee = projectObj.project.installation_fee.getInstallationFeeByLibID(section.libID);
  35. let impacRules = _.filter(installFee.feeRule,{'sectionId':section.ID});
  36. return impacRules;
  37. };
  38. installation_fee.prototype.getInstallSectionsByfeeItemID=function(libID,feeItemId){
  39. let installationFee = this.getInstallationFeeByLibID(libID);
  40. let installSections = _.filter(installationFee.installSection,{'feeItemId':feeItemId});
  41. return installSections;
  42. };
  43. installation_fee.prototype.getFeeItemByID = function(libID,ID){
  44. let installFee = projectObj.project.installation_fee.getInstallationFeeByLibID(libID);
  45. return _.find(installFee.installFeeItem,{'ID':ID});
  46. };
  47. installation_fee.prototype.getInstallSectionByID = function(libID,ID){
  48. let installFee = projectObj.project.installation_fee.getInstallationFeeByLibID(libID);
  49. return _.find(installFee.installSection,{'ID':ID});
  50. };
  51. installation_fee.prototype.getFeeRuleBySectionID=function(libID,sectionId){
  52. let installationFee = this.getInstallationFeeByLibID(libID);
  53. let feeRules = _.filter(installationFee.feeRule,{'sectionId':sectionId});
  54. return feeRules;
  55. };
  56. installation_fee.prototype.getFeeRuleByID = function (libID,feeRuleID) {
  57. let installationFee = this.getInstallationFeeByLibID(libID);
  58. return _.find(installationFee.feeRule,{'ID':feeRuleID});
  59. };
  60. installation_fee.prototype.updateFeeItem = function(doc,libID,feeItemID,cleanPosition,callback){
  61. let me = this,ration_install=projectObj.project.ration_installation;
  62. let feeItem = me.getFeeItemByID(libID,feeItemID);
  63. let temFeeItem = _.cloneDeep(feeItem);//暂时不更新缓存
  64. let updateData = [];
  65. let cleanRules = [];
  66. let rationInstallations = [];
  67. for(let d_key in doc){
  68. temFeeItem[d_key] = doc[d_key]
  69. }
  70. updateData.push(me.getFeeItemUpdateData(libID,feeItemID,doc));
  71. let sections = me.getInstallSectionsByfeeItemID(libID,feeItemID);
  72. for (let s of sections){
  73. if(temFeeItem.isCal == 1){//勾选记取的时候要同步更新对应的定额安装费
  74. me.getRIUpdateDataBySectionUpdate(s.ID,s.feeRuleId,rationInstallations);//生成受影响的定额安装增加费并加入到数组中
  75. }else {//取消打勾时清空对应的定额安装费的规则项
  76. me.getRIUpdateDataBySectionUpdate(s.ID,"",rationInstallations);//生成受影响的定额安装增加费并加入到数组中
  77. }
  78. }
  79. if(cleanPosition==true){//如果要清除记取位置
  80. let [dataArray,impacRules] = installationFeeObj.getFeeRuleUpdateDataByFeeItem(feeItem,{code: "",ID:''});
  81. updateData = updateData.concat(dataArray);
  82. cleanRules = impacRules;
  83. }
  84. $.bootstrapLoading.start();
  85. me.submitInstallationUpdate(updateData,rationInstallations,function (data) {
  86. //更新缓存
  87. for(let d_key in doc){
  88. feeItem[d_key] = doc[d_key]
  89. }
  90. for(let ir of cleanRules){//清除记取位置
  91. ir.position = "";
  92. ir.billID = "";
  93. }
  94. if(callback){
  95. callback();
  96. }
  97. $.bootstrapLoading.end();
  98. });
  99. };
  100. installation_fee.prototype.getRIUpdateDataBySectionUpdate = function (sectionID,newRuleID,rationInstallations) {
  101. let ration_install=projectObj.project.ration_installation;
  102. let ris = ration_install.getBySectionID(sectionID);
  103. for(let ri of ris){
  104. if(ri.unifiedSetting==1&&ri.ruleId!=newRuleID){//勾选按统一设置并且费率规则选择的不一样
  105. rationInstallations.push({ID:ri.ID,doc:{'ruleId':newRuleID}});
  106. }
  107. }
  108. };
  109. installation_fee.prototype.updateFeeRule = function (doc,libID,feeRuleID,callback) {
  110. let me = this;
  111. let itemUpdateData = null;
  112. let feeItem=null;
  113. let ruleUpdateData=null;
  114. let updateData = [];
  115. let feeRule = me.getFeeRuleByID(libID,feeRuleID);
  116. if(feeRule){
  117. if(doc){//如果有需要更新的属性
  118. ruleUpdateData = me.getFeeRuleUpdateData(libID,feeRuleID,doc);
  119. updateData.push(ruleUpdateData);
  120. if(doc.hasOwnProperty("billID")){//改变了选取位置后如果与费用项里的位置不一致的话要清空费用项的选取位置
  121. feeItem = me.getFeeItemByID(libID,feeRule.feeItemId);
  122. if(feeItem.position!=''&&feeItem.billID!=doc.billID){
  123. itemUpdateData = me.getFeeItemUpdateData(libID,feeItem.ID,{position: "", billID:""});
  124. updateData.push(itemUpdateData);
  125. }
  126. }
  127. $.bootstrapLoading.start();
  128. me.submitInstallationUpdate(updateData,null,function (data) {
  129. //更新缓存
  130. let isFeeItemUpdate = false;
  131. if(itemUpdateData){
  132. feeItem.position ="";
  133. feeItem.billID = "";
  134. isFeeItemUpdate= true;
  135. }
  136. for(let ukey in doc){
  137. feeRule[ukey]=doc[ukey];
  138. }
  139. if(callback){//回调
  140. callback(isFeeItemUpdate);
  141. }
  142. $.bootstrapLoading.end();
  143. });
  144. }
  145. }else {
  146. if(callback){
  147. callback(false);
  148. }
  149. }
  150. };
  151. installation_fee.prototype.getFeeRuleUpdateData = function (libID,feeRuleID,doc) {
  152. let installationFee = this.getInstallationFeeByLibID(libID);
  153. let updateData = {
  154. ID:installationFee.ID,
  155. itemID:feeRuleID,
  156. type:"feeRule",
  157. doc:doc
  158. };
  159. return updateData;
  160. };
  161. installation_fee.prototype.getSectionUpdateData = function (libID,sectionID,doc) {
  162. let installationFee = this.getInstallationFeeByLibID(libID);
  163. let updateData = {
  164. ID:installationFee.ID,
  165. itemID:sectionID,
  166. type:"installSection",
  167. doc:doc
  168. };
  169. return updateData;
  170. };
  171. installation_fee.prototype.getFeeItemUpdateData = function (libID,itemID,doc) {
  172. let installationFee = this.getInstallationFeeByLibID(libID);
  173. let updateData = {
  174. ID:installationFee.ID,
  175. itemID:itemID,
  176. type:'installFeeItem',
  177. doc:doc
  178. };
  179. return updateData;
  180. };
  181. installation_fee.prototype.updateInstallation = function (updateData,callback) {
  182. let me = this;
  183. me.submitInstallationUpdate(updateData,null,function (data) {
  184. for(let u of updateData){
  185. let insFee = me.getInstallationFeeByID(u.ID);
  186. let item = _.find(insFee[u.type],{'ID':u.itemID})
  187. if(item){
  188. for(let key in u.doc){
  189. item[key] = u.doc[key] ;
  190. }
  191. }
  192. }
  193. if(callback){
  194. callback(data);
  195. }
  196. });
  197. };
  198. installation_fee.prototype.submitInstallationUpdate = function (updateData,rationInstallations,callback) {
  199. if(updateData){
  200. let data = {'projectID':projectInfoObj.projectInfo.ID,'updateData':updateData};
  201. if(rationInstallations){//是否附带更新定额安装费
  202. data['rationInstallations'] = rationInstallations;
  203. }
  204. CommonAjax.post('/installation/updateInstallationFee',data,function (data) {
  205. //更新定额安装费的缓存
  206. if(rationInstallations){
  207. for(let ri of rationInstallations){
  208. let c_ri = project.ration_installation.getByID(ri.ID);
  209. if(c_ri){
  210. for(let rkey in ri.doc){
  211. c_ri[rkey] = ri.doc[rkey];
  212. }
  213. }
  214. }
  215. }
  216. callback(data);
  217. })
  218. }
  219. };
  220. installation_fee.prototype.calcInstallationFee=function(callback){
  221. let project = projectObj.project,me = this;
  222. let engineering = projectInfoObj.projectInfo.property.engineering;
  223. let installSetting = projectInfoObj.projectInfo.property.installSetting;
  224. let rationInstallation = project.ration_installation;
  225. let BXs = project.Bills.getAllBXs();//取所有补项
  226. let allBillsDatas = _.sortBy(_.cloneDeep(project.Bills.datas),'code');//取所有清单信息,用来查找清单信息和存放中间过程产生的清单
  227. let rationKeyMap={};//安装子目关联表
  228. let newBills = [];
  229. let billSerialMap = {};
  230. let FBMap = {};//保存分部下对应的补项
  231. let usedBXMap = {};//有使用到的补项
  232. let startTime = +new Date();
  233. if(!projectObj.project.isInstall()){//如果不是安装工程,则不用计算
  234. if(callback) callback(false);
  235. return;
  236. }
  237. for(let bx of BXs){//把补项放入映射表中
  238. FBMap[bx.ParentID] = bx;
  239. }
  240. for(let d of me.datas){
  241. for(let item of d.installFeeItem){
  242. if(item.isCal == 1){ //勾选了记取的费用项
  243. let rule_ration_map = {};//费用规则定额映射表;
  244. let ra_installs = rationInstallation.getCalcRIByItemID(d.libID,item.ID);//取所有有效的定额安装增加费
  245. for(let ri of ra_installs){
  246. let rationNode = project.mainTree.getNodeByID(ri.rationID);
  247. if(rationNode){
  248. if(rule_ration_map[ri.ruleId]){
  249. rule_ration_map[ri.ruleId].push(rationNode.data);
  250. }else {
  251. rule_ration_map[ri.ruleId] = [rationNode.data];
  252. }
  253. }
  254. }
  255. for(let ruleIDKey in rule_ration_map){
  256. calcEachRule(item,d.libID,ruleIDKey,rule_ration_map[ruleIDKey],rationKeyMap,newBills);
  257. }
  258. }
  259. }
  260. }
  261. let updateData = {
  262. bills:{
  263. delete:[],
  264. add:newBills
  265. },
  266. ration:{//定额更新只有更新对应的工料机数据
  267. delete:[],
  268. update:[],
  269. add:[]
  270. },
  271. userID: userID
  272. };
  273. let oldITypeRations = _.cloneDeep(project.Ration.getAllInstallTypeRation())//取所有旧的安装增加费定额-没有用的要删除
  274. let oldRationMap = {}, deleteRationNodes = [], deleteBillsNodes = [],reCalBillIDS = [];
  275. let isChange = newBills.length>0;//记录数据是否发生了改变;
  276. for(let o of oldITypeRations){//过滤出要删除的定额 - 同时对应的父项也要重新更新计算
  277. if(rationKeyMap[o.installationKey]==undefined){
  278. updateData.ration.delete.push(o);
  279. let d_node = project.mainTree.getNodeByID(o.ID);
  280. if(d_node){
  281. deleteRationNodes.push(d_node);
  282. reCalBillIDS.push(o.billsItemID);
  283. isChange = true;
  284. }
  285. }
  286. oldRationMap[o.installationKey] = o;
  287. }
  288. for(let inKey in rationKeyMap){
  289. if(oldRationMap[inKey]){//存在,则更新就可以了
  290. if(checkRation(oldRationMap[inKey],rationKeyMap[inKey])){//检查是否需要更新
  291. updateData.ration.update.push(oldRationMap[inKey]);
  292. isChange = true;
  293. }
  294. }else {
  295. updateData.ration.add.push(rationKeyMap[inKey]);
  296. isChange = true;
  297. }
  298. }
  299. for(let tem_bx of BXs){//过滤要删除的 自动生成的补项
  300. if(tem_bx.code&&tem_bx.code.startsWith('BAZF')&& usedBXMap[tem_bx.ParentID]==undefined){
  301. updateData.bills.delete.push(tem_bx);
  302. let b_node = project.mainTree.getNodeByID(tem_bx.ID);
  303. if(b_node){
  304. deleteBillsNodes.push(b_node);
  305. isChange = true;
  306. }
  307. }
  308. }
  309. if(isChange == true){
  310. $.bootstrapLoading.start();
  311. CommonAjax.post("/project/calcInstallationFee",updateData,function (data) {
  312. //提交后台成功后所做的操作,删除要先删除定额,再删除清单,添加要先添加清单再添加定额
  313. project.ration_glj.addDatasToList(data.add);//添加插入的定额
  314. let calRations = [];
  315. for(let ur of data.update){
  316. let glj = project.ration_glj.getDataByID(ur.ID);
  317. glj.quantity = ur.quantity;
  318. glj.rationItemQuantity = ur.rationItemQuantity;
  319. }
  320. let selectedNode = projectObj.project.mainTree.selected;
  321. //对树节点的操作并删除、添加清单、删除添加定额、删除对应的定额工料机缓存
  322. TREE_SHEET_HELPER.massOperationSheet(projectObj.mainController.sheet, function () {
  323. deleteOldNodes(deleteRationNodes,deleteBillsNodes);
  324. calRations = addNewNodes(updateData);
  325. });
  326. for(let u of updateData.ration.update){
  327. let unode = projectObj.project.mainTree.findNode(u.ID);
  328. unode?calRations.push(unode):'';
  329. }
  330. if(reCalBillIDS.length > 0){
  331. reCalBillIDS = _.uniq(reCalBillIDS);
  332. for(let bID of reCalBillIDS){
  333. let bnode = projectObj.project.mainTree.findNode(bID);
  334. bnode?calRations.push(bnode):''; //现在计算程序支持同时传入清单和定额了,所以能放一起
  335. }
  336. }
  337. setTreeSelection(selectedNode);
  338. let endTime = +new Date();
  339. console.log(`计算安装增加费时间——${endTime - startTime}`);
  340. projectObj.project.projectGLJ.loadData(function () {
  341. cbTools.refreshFormulaNodes();
  342. if(callback){
  343. callback(true,calRations);
  344. }
  345. $.bootstrapLoading.end();
  346. });
  347. });
  348. }else {
  349. if(callback) callback(false);
  350. }
  351. function addNewNodes(updateData) {
  352. let controller = projectObj.mainController;
  353. let Bill = project.Bills;
  354. let newAddNode = [];
  355. let newRationNodes = [];
  356. for(let nb of updateData.bills.add){
  357. let newSource = Bill.tree.insertByData(nb, nb.ParentID, -1, true);
  358. let newNode = project.mainTree.insert(nb.ParentID, -1, newSource.data.ID);
  359. newNode.source = newSource;
  360. newNode.sourceType = Bill.getSourceType();
  361. newNode.data = newSource.data;
  362. controller.sheet.addRows(newNode.serialNo(), 1);
  363. controller.sheet.showRow(newNode.serialNo(), GC.Spread.Sheets.VerticalPosition.center);
  364. newAddNode.push(newNode);
  365. Bill.datas.push(nb);
  366. }
  367. for(let nr of updateData.ration.add){
  368. let newNode = project.mainTree.insert(nr.billsItemID, -1, nr.ID);
  369. newNode.source = nr;
  370. newNode.sourceType = project.Ration.getSourceType();
  371. newNode.data = nr;
  372. controller.sheet.addRows(newNode.serialNo(), 1);
  373. controller.sheet.showRow(newNode.serialNo(), GC.Spread.Sheets.VerticalPosition.center);
  374. newAddNode.push(newNode);
  375. newRationNodes.push(newNode);
  376. project.Ration.datas.push(nr);
  377. }
  378. TREE_SHEET_HELPER.refreshTreeNodeData(controller.setting, controller.sheet, newAddNode, false);
  379. return newRationNodes;
  380. }
  381. function deleteOldNodes(deleteRationNodes,deleteBillsNodes) {
  382. let controller = projectObj.mainController, project = projectObj.project;
  383. let Bill = project.Bills, Ration = project.Ration,ration_glj = project.ration_glj;
  384. for(let rd of deleteRationNodes){
  385. controller.sheet.deleteRows(rd.serialNo(),1);
  386. controller.tree.delete(rd);
  387. Ration.removeByID(rd.getID());
  388. ration_glj.deleteByRation(rd.data);
  389. }
  390. for(let bd of deleteBillsNodes){
  391. controller.sheet.deleteRows(bd.serialNo(),1);
  392. controller.tree.delete(bd);
  393. Bill.tree.delete(bd.source);
  394. Bill.removeByID(bd.getID());
  395. }
  396. }
  397. function setTreeSelection(oldSelect) {
  398. let controller = projectObj.mainController;
  399. let sel = controller.sheet.getSelections()[0];
  400. if(controller.tree.getNodeByID(oldSelect.getID())){//如果旧选中节点还存在
  401. controller.sheet.setSelection(oldSelect.serialNo(),sel.col,sel.rowCount,sel.colCount);
  402. controller.setTreeSelected(oldSelect)
  403. }else {//选中节点已被删除,自动选中新的节点
  404. controller.setTreeSelected(controller.tree.items[sel.row]);
  405. }
  406. }
  407. function checkRation(oldRation,newRation) {//检查定额是否需要更新
  408. let gljs = project.ration_glj.getGljByRationID(oldRation.ID);
  409. let modify = false;
  410. let gljList =[];
  411. for(let g of gljs){
  412. if(g.quantity != newRation.glj[g.code].quantity){//消耗量不一样,需重新修改
  413. let tem ={
  414. ID:g.ID,
  415. projectID:g.projectID,
  416. quantity :newRation.glj[g.code].quantity,
  417. rationItemQuantity:newRation.glj[g.code].rationItemQuantity
  418. };
  419. gljList.push(tem);
  420. modify = true;
  421. }
  422. }
  423. oldRation.glj = gljList;
  424. return modify;
  425. }
  426. function calcEachRule(item,libID,ruleID,rations,rationKeyMap,newBills) {
  427. let rule = me.getFeeRuleByID(libID,ruleID);
  428. let pre_key = libID+item.ID+item.feeType+ruleID;
  429. if(item.feeType == '子目费用'){
  430. for(let r of rations){//在定额的同级新增一条
  431. let billItemID = r.billsItemID;
  432. let nextID = -1;
  433. let newRationData = createNewRationData(billItemID,nextID,rule);
  434. let [labourQuantity,materialQuantity,machineQuantity] = calcQuantity(rule,r);
  435. newRationData = setGljQuantity(newRationData,labourQuantity,materialQuantity,machineQuantity);
  436. let installationKey = pre_key+billItemID;
  437. newRationData['installationKey'] = installationKey;
  438. if(rationKeyMap[installationKey]){//如果已经存在,则工料机消耗量累加起来
  439. sumGLJquantity(rationKeyMap[installationKey],labourQuantity,materialQuantity,machineQuantity);
  440. }else {
  441. rationKeyMap[installationKey] = newRationData;//在映射表中添加
  442. }
  443. }
  444. }else if(item.feeType == '措施费用'){//措施费用时,则在记取位置选择的清单下新增安装子目。
  445. allInOne(item,rule,rations,newBills,pre_key,rationKeyMap);
  446. }else if(item.feeType=='分项费用'){
  447. if(installSetting==undefined||installSetting=="0"){//选择了“整个项目统一计取”,则在记取位置选择的分项下新增安装子目
  448. allInOne(item,rule,rations,newBills,pre_key,rationKeyMap);
  449. }else {//选择了每个分部单独记取
  450. calcEveryFB(item,rule,rations,newBills,pre_key,rationKeyMap);
  451. }
  452. }
  453. }
  454. function sumGLJquantity(ration,labourQuantity,materialQuantity,machineQuantity) {
  455. let gljDecimal = getDecimal('glj.quantity');
  456. let sumLabour = scMathUtil.roundForObj(ration.glj['RGFTZ'].quantity,gljDecimal)+labourQuantity;
  457. let sumMaterial = scMathUtil.roundForObj(ration.glj['CLFTZ'].quantity,gljDecimal)+materialQuantity;
  458. let sumMachine = scMathUtil.roundForObj(ration.glj['JXFTZ'].quantity,gljDecimal)+machineQuantity;
  459. ration.glj['RGFTZ'].quantity =scMathUtil.roundToString(sumLabour,gljDecimal);
  460. ration.glj['RGFTZ'].rationItemQuantity = scMathUtil.roundToString(sumLabour,gljDecimal);
  461. ration.glj['CLFTZ'].quantity = scMathUtil.roundToString(sumMaterial,gljDecimal);
  462. ration.glj['CLFTZ'].rationItemQuantity = scMathUtil.roundToString(sumMaterial,gljDecimal);
  463. ration.glj['JXFTZ'].quantity = scMathUtil.roundToString(sumMachine,gljDecimal);
  464. ration.glj['JXFTZ'].rationItemQuantity = scMathUtil.roundToString(sumMachine,gljDecimal);
  465. }
  466. function calcEveryFB(item,rule,rations,newBills,pre_key,rationKeyMap) {
  467. let parentMap = {};
  468. for(let r of rations){//先归类
  469. let rationNode = project.mainTree.getNodeByID(r.ID);
  470. if(rationNode){
  471. if(parentMap[rationNode.parent.parent.getID()]){
  472. parentMap[rationNode.parent.parent.getID()].push(r)
  473. }else {
  474. parentMap[rationNode.parent.parent.getID()] = [r];
  475. }
  476. }
  477. }
  478. for(let billID_key in parentMap){
  479. let gljDecimal = getDecimal('glj.quantity');
  480. let tem_rations = parentMap[billID_key];
  481. let BXNodeData;
  482. if(FBMap[billID_key]){//查看有没有对应的补项,如果没有,新增一个
  483. BXNodeData = FBMap[billID_key];
  484. }else {//新增一个
  485. BXNodeData = {
  486. projectID: parseInt(project.ID()),
  487. ParentID:billID_key,
  488. NextSiblingID:-1,
  489. name:'安装增加费',
  490. unit:'元',
  491. quantity:'1',
  492. type:billType.BX
  493. };
  494. BXNodeData.ID = uuid.v1();
  495. BXNodeData.code = getBXCode("BAZF",usedBXMap);
  496. FBMap[billID_key] = BXNodeData;
  497. newBills.push(BXNodeData);
  498. }
  499. usedBXMap[billID_key] = BXNodeData;//记录有用到的补项,最后没有用到的要删除
  500. let newRationData = createNewRationData(BXNodeData.ID,-1,rule);
  501. let labourSum = 0,materialSum =0,machineSum = 0;
  502. for(let ra of tem_rations){//措施费用的情况下,多条定额生成一条安装子目
  503. let [tem_labourQuantity,tem_materialQuantity,tem_machineQuantity] = calcQuantity(rule,ra);
  504. labourSum =scMathUtil.roundForObj(labourSum+tem_labourQuantity,gljDecimal);
  505. materialSum= scMathUtil.roundForObj(materialSum+tem_materialQuantity,gljDecimal);
  506. machineSum = scMathUtil.roundForObj(machineSum+tem_machineQuantity,gljDecimal);
  507. }
  508. newRationData = setGljQuantity(newRationData,labourSum,materialSum,machineSum);
  509. let installationKey = pre_key+BXNodeData.ID;
  510. newRationData['installationKey'] = installationKey;
  511. rationKeyMap[installationKey] = newRationData;//在映射表中添加
  512. }
  513. }
  514. function getBXCode(code,BXMap) {//自动生成物补项编号加001、002等后缀
  515. let codes = [];
  516. let i = 1;
  517. let newCode = '';
  518. for(let key in BXMap){
  519. codes.push(BXMap[key].code);
  520. }
  521. while (true){
  522. newCode = code + seqString(i,3);
  523. if(codes.indexOf(newCode)==-1){
  524. break;
  525. }
  526. i++;
  527. }
  528. return newCode;
  529. }
  530. function allInOne(item,rule,rations,newBills,pre_key,rationKeyMap) {//统一设置
  531. let billData = getBillNodeData(item,rule,newBills);//取对应的清单或生成一个新的清单数据
  532. let newRationData = createNewRationData(billData.ID,-1,rule);
  533. let gljDecimal = getDecimal('glj.quantity');
  534. let labourSum = 0,materialSum =0,machineSum = 0;
  535. for(let r of rations){//措施费用的情况下,多条定额生成一条安装子目
  536. let [tem_labourQuantity,tem_materialQuantity,tem_machineQuantity] = calcQuantity(rule,r);
  537. labourSum =scMathUtil.roundForObj(labourSum+tem_labourQuantity,gljDecimal);
  538. materialSum= scMathUtil.roundForObj(materialSum+tem_materialQuantity,gljDecimal);
  539. machineSum = scMathUtil.roundForObj(machineSum+tem_machineQuantity,gljDecimal);
  540. }
  541. newRationData = setGljQuantity(newRationData,labourSum,materialSum,machineSum);
  542. let installationKey = pre_key+billData.ID;
  543. newRationData['installationKey'] = installationKey;
  544. rationKeyMap[installationKey] = newRationData;//在映射表中添加
  545. }
  546. function setGljQuantity(rationData,labourQuantity,materialQuantity,machineQuantity) {
  547. let gljDecimal = getDecimal('glj.quantity');
  548. rationData.glj['RGFTZ'].quantity = scMathUtil.roundToString(labourQuantity,gljDecimal);
  549. rationData.glj['RGFTZ'].rationItemQuantity = scMathUtil.roundToString(labourQuantity,gljDecimal);
  550. rationData.glj['CLFTZ'].quantity = scMathUtil.roundToString(materialQuantity,gljDecimal);
  551. rationData.glj['CLFTZ'].rationItemQuantity = scMathUtil.roundToString(materialQuantity,gljDecimal);
  552. rationData.glj['JXFTZ'].quantity = scMathUtil.roundToString(machineQuantity,gljDecimal);
  553. rationData.glj['JXFTZ'].rationItemQuantity = scMathUtil.roundToString(machineQuantity,gljDecimal);
  554. return rationData;
  555. }
  556. function createNewRationData(billItemID,nextID,rule) {
  557. let br = project.Ration.getBillsSortRation(billItemID);
  558. let serialNo = 0;
  559. if(billSerialMap[billItemID]){
  560. serialNo = billSerialMap[billItemID]+1
  561. }else {
  562. serialNo = br.length > 0 ? br[br.length - 1].serialNo + 1 : 1;
  563. billSerialMap[billItemID] = serialNo;
  564. }
  565. serialNo = br.length > 0 ? br[br.length - 1].serialNo + 1 : 1;
  566. let newRationData = project.Ration.getTempRationData(project.Ration.getNewRationID(), billItemID, serialNo, rationType.install);
  567. newRationData = setNewRationProperty(newRationData,nextID,rule);
  568. return newRationData;
  569. }
  570. function getBillNodeData(item,rule,newBills) {
  571. let billData = null;
  572. let billID = null;
  573. if(rule.billID&&rule.billID!=""){
  574. billData = getBillsByID(rule.billID);
  575. billID = rule.billID;
  576. }
  577. if(!billData){
  578. billData = getBillsByCode(rule.position);
  579. if(!billData){//如果按ID和按code都找不到清单的话,自动生成一个
  580. let newBillData = project.Bills.getNewInstallBillData(rule.position,billID,item.feeType);
  581. if(item.feeType == '措施费用'){
  582. newBillData.type = billType.BILL;
  583. }else if(item.feeType == '分项费用'){
  584. newBillData.type = billType.FX;
  585. }
  586. newBills.push(newBillData);
  587. allBillsDatas.push(newBillData);
  588. return newBillData;
  589. }
  590. }
  591. return billData;
  592. }
  593. function getBillsByID(billID){
  594. return _.find(allBillsDatas,{"ID":billID});
  595. }
  596. function getBillsByCode(code){
  597. return _.find(allBillsDatas, function(b) {
  598. if(b.code&&b.code.indexOf(code)!=-1){
  599. return true;
  600. }else {
  601. return false;
  602. }
  603. })
  604. }
  605. function calcQuantity(rule,ration) {//计算单条定额的三个消耗量
  606. let gljDecimal = getDecimal('glj.quantity');
  607. let labourQuantity = 0, materialQuantity = 0, machineQuantity = 0;
  608. let labour = rule.labour?rule.labour*0.01:0;
  609. let material = rule.material?rule.material*0.01:0;
  610. let machine = rule.machine?rule.machine*0.01:0;
  611. let feeRate = rule.feeRate?rule.feeRate*0.01:0;
  612. if(rule.base=='分别按人材机乘系数'){//'分别按人材机乘系数','人工','材料','机械'
  613. labourQuantity = scMathUtil.roundForObj(parseFloat(project.Ration.getLabourTotalFee(ration))*parseFloat(labour),gljDecimal);
  614. materialQuantity = scMathUtil.roundForObj(parseFloat(project.Ration.getMaterialTotalFee(ration))*parseFloat(material),gljDecimal);
  615. machineQuantity = scMathUtil.roundForObj(parseFloat(project.Ration.getMachineTotalFee(ration))*parseFloat(machine),gljDecimal);
  616. }else {
  617. let base = 0;
  618. if(rule.base=='人工'){
  619. base = parseFloat(project.Ration.getLabourTotalFee(ration))*parseFloat(feeRate);
  620. }else if(rule.base=='材料'){
  621. base = parseFloat(project.Ration.getMaterialTotalFee(ration))*parseFloat(feeRate);
  622. }else if(rule.base=='机械'){
  623. base = parseFloat(project.Ration.getMachineTotalFee(ration))*parseFloat(feeRate);
  624. }
  625. labourQuantity = scMathUtil.roundForObj(base*parseFloat(labour),gljDecimal);
  626. materialQuantity = scMathUtil.roundForObj(base*parseFloat(material),gljDecimal);
  627. machineQuantity = scMathUtil.roundForObj(base*parseFloat(machine),gljDecimal);
  628. }
  629. return [labourQuantity,materialQuantity,machineQuantity];
  630. }
  631. function setNewRationProperty(data,nextID,rule) {
  632. data.code = rule.code;
  633. data.name = rule.rule;
  634. data.unit = '元';
  635. data.quantity = '1';
  636. data.contain ='1';
  637. data.nextID = nextID;
  638. data.glj = {
  639. 'RGFTZ':{
  640. rationID:data.ID,
  641. billsItemID:data.billsItemID,
  642. shortName:project.projectGLJ.getShortNameByID(gljType.LABOUR),
  643. GLJID:-1,
  644. projectID:data.projectID,
  645. code:'RGFTZ',
  646. original_code:'RGFTZ',
  647. name:'人工费调整',
  648. specs:'',
  649. unit:'元',
  650. type:gljType.LABOUR,
  651. basePrice:1,
  652. adjCoe:null,
  653. from:'std',
  654. repositoryId:-1,
  655. quantity:'0',
  656. rationItemQuantity:'0'
  657. },
  658. 'CLFTZ':{
  659. rationID:data.ID,
  660. billsItemID:data.billsItemID,
  661. shortName:project.projectGLJ.getShortNameByID(gljType.GENERAL_MATERIAL),
  662. GLJID:-1,
  663. projectID:data.projectID,
  664. code:'CLFTZ',
  665. original_code:'CLFTZ',
  666. name:'材料费调整',
  667. specs:'',
  668. unit:'元',
  669. type:gljType.GENERAL_MATERIAL,
  670. basePrice:1,
  671. adjCoe:null,
  672. from:'std',
  673. repositoryId:-1,
  674. quantity:'0',
  675. rationItemQuantity:'0'
  676. },
  677. 'JXFTZ':{
  678. rationID:data.ID,
  679. billsItemID:data.billsItemID,
  680. shortName:project.projectGLJ.getShortNameByID(gljType.GENERAL_MACHINE),
  681. GLJID:-1,
  682. projectID:data.projectID,
  683. code:'JXFTZ',
  684. original_code:'JXFTZ',
  685. name:'机械费调整',
  686. specs:'',
  687. unit:'元',
  688. type:gljType.GENERAL_MACHINE,
  689. basePrice:1,
  690. adjCoe:null,
  691. from:'std',
  692. repositoryId:-1,
  693. quantity:'0',
  694. rationItemQuantity:'0'
  695. }
  696. };
  697. return data;
  698. }
  699. };
  700. installation_fee.prototype.updateInstallSetting = function (newValue,callback) {
  701. let mixDatas = {
  702. projectID: projectObj.project.ID(),
  703. updateType: 'update',
  704. properties: {
  705. "property.installSetting":newValue
  706. },
  707. labourCoes: {},
  708. rations: [],
  709. bills: []
  710. };
  711. CommonAjax.post('/pm/api/updateMixDatas', {user_id: userID, mixDataArr: mixDatas}, function (rstData) {
  712. projectInfoObj.projectInfo.property.installSetting = newValue;
  713. if(callback){
  714. callback();
  715. }
  716. });
  717. };
  718. installation_fee.prototype.resetToDefault = function (callback) {
  719. let me = this;
  720. let installFees = [];
  721. for(let d of me.datas){
  722. let ins ={
  723. libID:d.libID,
  724. ID:d.ID
  725. };
  726. installFees.push(ins);
  727. }
  728. //data.projectID,data.installFees
  729. $.bootstrapLoading.start();
  730. CommonAjax.post("/installation/resetToDefault",{projectID:project.ID(),installFees:installFees},function (result) {
  731. console.log(result)
  732. me.datas = result;
  733. if(callback){
  734. callback();
  735. }
  736. $.bootstrapLoading.end();
  737. })
  738. };
  739. // 提交数据后返回数据处理
  740. installation_fee.prototype.doAfterUpdate = function(err, data){
  741. };
  742. return new installation_fee(project);
  743. }
  744. };