ration.js 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890
  1. /**
  2. * Created by Mai on 2017/4/1.
  3. */
  4. var Ration = {
  5. createNew: function (project) {
  6. // 用户定义private方法
  7. var tools = {
  8. formatRationUpdateData: function (data) {
  9. let uData = JSON.parse(JSON.stringify(data));
  10. delete uData.feesIndex;
  11. delete uData.flagsIndex;
  12. // if (uData.fees) {
  13. // for (let fee of uData.fees) {
  14. // fee.unitFee = fee.unitFee.toFixed(2);
  15. // fee.totalFee = fee.totalFee.toFixed(2);
  16. // fee.tenderUnitFee = fee.tenderUnitFee.toFixed(2);
  17. // fee.tenderTotalFee = fee.tenderTotalFee.toFixed(2);
  18. // }
  19. // }
  20. return uData;
  21. }
  22. };
  23. // 所有通过this访问的属性,都不应在此单元外部进行写入操作
  24. var ration = function (proj) {
  25. this.project = proj;
  26. this.datas = null;
  27. var sourceType = ModuleNames.ration;
  28. this.getSourceType = function () {
  29. return sourceType;
  30. }
  31. proj.registerModule(ModuleNames.ration, this);
  32. var maxRationID = 0;
  33. this.getNewRationID = function () {
  34. return uuid.v1();
  35. //return maxRationID += 1;
  36. };
  37. this.maxRationID = function (maxID) {
  38. if (arguments.length === 0) {
  39. return maxRationID;
  40. } else {
  41. maxRationID = Math.max(maxID, maxRationID);
  42. }
  43. };
  44. };
  45. // prototype用于定义public方法
  46. ration.prototype.loadData = function (datas) {
  47. var that = this;
  48. this.datas = datas;
  49. // generate Fees & Flags Index,For View & Calculate
  50. this.datas.forEach(function (data) {
  51. data.feesIndex = getFeeIndex(data.fees);
  52. data.flagsIndex = {};
  53. data.flags.forEach(function (flag) {
  54. data.flagsIndex[flag.fieldName] = flag;
  55. });
  56. that.maxRationID(data.ID);
  57. });
  58. };
  59. ration.prototype.setMaxID = function (ID) {
  60. this.maxRationID(ID);
  61. }
  62. ration.prototype.addDatasToList = function (new_datas) {
  63. let me = this;
  64. if(me.datas && Array.isArray(me.datas)){
  65. for(let d of new_datas){
  66. me.datas.push(d);
  67. }
  68. }else {
  69. me.datas = new_datas;
  70. }
  71. };
  72. // refresh after update
  73. ration.prototype.doAfterUpdate = function(err, data){
  74. if(data.stateRefresh){
  75. this.refreshAdjustState(data);
  76. }
  77. if(data.quantityRefresh){
  78. this.refreshQuantity(data);
  79. }
  80. };
  81. ration.prototype.refreshAdjustState = function(data){
  82. this.refreshDatas(data,'adjustState');
  83. if(data.hasOwnProperty('name')){
  84. this.refreshDatas(data,'name')
  85. }
  86. };
  87. ration.prototype.refreshQuantity = function(data){
  88. this.refreshDatas(data,'quantity');
  89. };
  90. ration.prototype.refreshDatas = function(data,fieldName){
  91. var dataIndex = _.findIndex(this.datas,function(item) {
  92. return item.ID ==data.rationID;
  93. });
  94. this.datas[dataIndex][fieldName] = data[fieldName];
  95. if(fieldName=='quantity'){
  96. this.datas[dataIndex]['isFromDetail']=1
  97. }
  98. var controller = projectObj.mainController;
  99. var selected = controller.sheet.getSelections();
  100. var col = _.findIndex(project.projSetting.main_tree_col.cols,function (col) {
  101. return col.data.field ==fieldName;
  102. });
  103. controller.sheet.getCell(selected[0].row,col).value(data[fieldName]);
  104. };
  105. ration.prototype.getTempRationData = function (id, billsID, serialNo, rType,priceType) {
  106. let newData = {'ID': id, 'serialNo': serialNo, projectID: this.project.ID()};
  107. let pEngineer = projectObj.project.projectInfo.property.projectEngineering;//量价默认使用后台设置的单位工程取费专业
  108. newData[project.masterField.ration] = billsID;
  109. newData['type'] = rType;
  110. if (rType == rationType.volumePrice){
  111. newData['subType'] = priceType?priceType:gljType.GENERAL_MATERIAL; // 如果priceType 没传,默认的量价类型为材料
  112. };
  113. if(rType == rationType.ration){//空定额暂时不输入取费专业
  114. // newData['programID'] = projectObj.project.projectInfo.property.engineering;
  115. }else if(rType == rationType.volumePrice){//量价取费专业默认为费率为0
  116. newData['programID'] = projectObj.project.calcProgram.compiledTemplateMaps["量价(计利润税金)"];
  117. }else {
  118. if(pEngineer) newData['programID'] = pEngineer;
  119. }
  120. return newData;
  121. };
  122. ration.prototype.getBillsSortRation = function (billsID) { // 该方法只适用于叶子清单
  123. var rations = this.datas.filter(function (data) {
  124. return data[project.masterField.ration] === billsID;
  125. });
  126. rations.sort(function (x, y) {
  127. return x.serialNo - y.serialNo;
  128. });
  129. return rations;
  130. };
  131. // CSL, 2017-11-13 取任何清单(父清单、叶子清单)下的所有定额
  132. ration.prototype.getRationNodes = function (billNode) {
  133. if (billNode.sourceType != ModuleNames.bills) return [];
  134. let rations = [], IDs = [];
  135. function getSubBillsIDs(node) {
  136. if (!node) return;
  137. if (node.sourceType != ModuleNames.bills) return;
  138. if (!node.children || node.children.length == 0 || node.children[0].sourceType != ModuleNames.bills)
  139. IDs.push(node.data.ID)
  140. else
  141. getSubBillsIDs(node.children[0]);
  142. getSubBillsIDs(node.nextSibling);
  143. };
  144. if (billNode.source.children.length == 0)
  145. IDs.push(billNode.data.ID)
  146. else
  147. getSubBillsIDs(billNode.children[0]);
  148. for (let id of IDs){
  149. let subRations = this.datas.filter(function (data) {
  150. return data[project.masterField.ration] === id;
  151. });
  152. rations.push(...subRations);
  153. };
  154. rations.sort(function (x, y) {
  155. return x.serialNo - y.serialNo;
  156. });
  157. let rationNodes = [];
  158. for (let ration of rations){
  159. rationNodes.push(projectObj.project.mainTree.nodes['id_' + ration.ID]);
  160. }
  161. return rationNodes;
  162. };
  163. ration.prototype.getInsertRationData = function (billsID, preRation, rationType) {
  164. var br = this.getBillsSortRation(billsID);
  165. var updateData = [];
  166. if (preRation) {
  167. var preIndex = br.indexOf(preRation), i;
  168. updateData.push({updateType: 'ut_create', updateData: this.getTempRationData(this.getNewRationID(), billsID, preIndex < br.length - 1 ? br[preIndex + 1].serialNo : br[preIndex].serialNo + 1, rationType)});
  169. for (i = preIndex + 1; i < br.length; i++) {
  170. updateData.push({updateType: 'ut_update', updateData: this.getTempRationData(br[i].ID, billsID, i < br.length - 1 ? br[i+1].serialNo : br[i].serialNo + 1, br[i].type)});
  171. }
  172. } else {
  173. updateData.push({updateType: 'ut_create', updateData: this.getTempRationData(this.getNewRationID(), billsID, br.length > 0 ? br[br.length - 1].serialNo + 1 : 1, rationType)});
  174. }
  175. return updateData;
  176. };
  177. ration.prototype.getCounterData = function (count) {
  178. var updateData = {'projectID': this.project.ID()};
  179. if (count) {
  180. updateData[this.getSourceType()] = this.maxRationID() + count;
  181. } else {
  182. updateData[this.getSourceType()] = this.maxRationID() + 1;
  183. }
  184. return updateData;
  185. };
  186. ration.prototype.insertRation = function (billsID, preRation, rationType) {
  187. var br = this.getBillsSortRation(billsID);
  188. let insertData = this.getInsertRationData(billsID, preRation, rationType);
  189. this.project.pushNow('insertRation', [this.getSourceType(), this.project.projCounter()],
  190. [insertData, this.getCounterData()]);
  191. var newRation = null;
  192. let newID = -1;
  193. for(let data of insertData){
  194. if(data.updateType === 'ut_create'){
  195. newID = data.updateData.ID;
  196. }
  197. }
  198. if (preRation) {
  199. var preIndex = br.indexOf(preRation), i;
  200. newRation = this.getTempRationData(newID, billsID, preIndex < br.length - 1 ? br[preIndex + 1].serialNo : br[preIndex].serialNo + 1, rationType);
  201. this.datas.push(newRation);
  202. for (i = preIndex + 1; i < br.length; i++) {
  203. br[i].serialNo = i < br.length - 1 ? br [i + 1].serialNo : br[i].serialNo + 1;
  204. }
  205. } else {
  206. newRation = this.getTempRationData(newID, billsID, br.length > 0 ? br[br.length - 1].serialNo + 1 : 1, rationType);
  207. this.datas.push(newRation);
  208. }
  209. return newRation;
  210. };
  211. ration.prototype.insertStdRation = function (billsID, preRation, std) {
  212. var br = this.getBillsSortRation(billsID), updateData = this.getInsertRationData(billsID, preRation, rationType.ration), newRation = null, that = this;
  213. updateData.forEach(function (data) {
  214. if (data.updateType === 'ut_create') {
  215. data.updateData.code = std.code;
  216. data.updateData.name = std.name;
  217. data.updateData.caption = std.caption;
  218. data.updateData.unit = std.unit;
  219. data.updateData.libID = std.rationRepId;
  220. data.updateData.content = std.jobContent;
  221. if (std.chapter) {
  222. data.updateData.comments = std.chapter.explanation;
  223. data.updateData.ruleText = std.chapter.ruleText;
  224. }
  225. data.updateData.from = std.type === 'complementary' ? 'cpt' : 'std';
  226. data.updateData.programID = std.feeType;
  227. data.updateData.rationAssList = projectObj.project.ration_ass.CreateNewAss(std);
  228. // calculate ration Quantity
  229. that.CalculateQuantity(data.updateData);
  230. newRation = data.updateData;
  231. }
  232. });
  233. this.project.pushNow('insertRation', [this.getSourceType(), this.project.projCounter()], [updateData, this.getCounterData()]);
  234. //newRation.ID = this.getNewRationID();
  235. if (preRation) {
  236. var preIndex = br.indexOf(preRation), i;
  237. this.datas.push(newRation);
  238. for (i = preIndex + 1; i < br.length; i++) {
  239. br[i].serialNo = i < br.length - 1 ? br [i + 1].serialNo : br[i].serialNo + 1;
  240. }
  241. } else {
  242. this.datas.push(newRation);
  243. }
  244. return newRation;
  245. };
  246. ration.prototype.getDeleteData = function (rationData) {
  247. var updateData = [];
  248. updateData.push({'updateType': 'ut_delete', 'updateData': {'ID': rationData.ID, 'projectID': this.project.ID()}});
  249. return updateData;
  250. };
  251. ration.prototype.delete = function (ration) {
  252. var ration_glj =projectObj.project.ration_glj;
  253. this.project.pushNow('deleteRation', [this.getSourceType(),ration_glj.getSourceType()], [this.getDeleteData(ration),ration_glj.getDeleteDataByRation(ration)]);
  254. this.deleteSubListOfRation(ration);
  255. this.datas.splice(this.datas.indexOf(ration), 1);
  256. };
  257. ration.prototype.removeByID = function(ID){
  258. _.remove(this.datas,{'ID':ID});
  259. };
  260. ration.prototype.getDeleteDataByBill = function (nodes) {
  261. let updateData = [];
  262. for (let node of nodes) {
  263. if (node.children.length > 0) {
  264. updateData = updateData.concat(this.getDeleteDataByBill(node.children));
  265. } else {
  266. let rations = this.getBillsSortRation(node.getID());
  267. for (let r of rations) {
  268. updateData.push({'updateType': 'ut_delete', 'updateData': {'ID': r.ID, 'projectID': this.project.ID()}});
  269. }
  270. }
  271. }
  272. return updateData;
  273. };
  274. ration.prototype.deleteByBills = function (nodes) {
  275. for (let node of nodes) {
  276. if (node.children.length > 0) {
  277. this.deleteByBills(node.children);
  278. } else {
  279. let rations = this.getBillsSortRation(node.getID());
  280. for (let r of rations) {
  281. this.datas.splice(this.datas.indexOf(r), 1);
  282. }
  283. }
  284. }
  285. }
  286. ration.prototype.changeMultiPos = function (baseRation, rations) {
  287. const updateData = [];
  288. let tempSerialNo = baseRation.serialNo;
  289. rations.forEach(ration => {
  290. updateData.push({
  291. updateType: 'ut_update',
  292. updateData: { ID: ration.ID, serialNo: tempSerialNo, projectID: this.project.ID()}
  293. });
  294. let orgSerialNo = ration.serialNo;
  295. ration.serialNo = tempSerialNo;
  296. tempSerialNo = orgSerialNo;
  297. });
  298. updateData.push({
  299. updateType: 'ut_update',
  300. updateData: { ID: baseRation.ID, serialNo: tempSerialNo, projectID: this.project.ID()}
  301. });
  302. baseRation.serialNo = tempSerialNo;
  303. this.project.pushNow('insertRation', [this.getSourceType()], [updateData]);
  304. };
  305. ration.prototype.updateField = function (ration, field, newValue) {
  306. calcFees.setFee(ration, field, newValue);
  307. let updateData = [];
  308. let data = {'ID': ration.ID, 'projectID': this.project.ID()};
  309. if (field === 'quantity') {
  310. data[field] = newValue;
  311. data.isFromDetail=0;
  312. // to do Calculate
  313. if (ration.fees) {
  314. data.fees = ration.fees;
  315. }
  316. } else if (field === 'feesIndex.common.unitFee') {
  317. // to do Calculate
  318. if (ration.fees) {
  319. data.fees = ration.fees;
  320. }
  321. } else {
  322. data[field] = newValue;
  323. }
  324. updateData.push({'updateType': 'ut_update', 'updateData': data});
  325. this.project.pushNow('updateBills', this.getSourceType(), updateData);
  326. };
  327. ration.prototype.updateRation = function (ration, updateNow) {
  328. let updateData = [];
  329. updateData.push({'updateType': 'ut_update', 'updateData': tools.formatRationUpdateData(ration)});
  330. if (updateNow) {
  331. this.project.pushNow('updateRations', this.getSourceType(), updateData);
  332. } else {
  333. this.project.push(this.getSourceType(), updateData);
  334. }
  335. };
  336. ration.prototype.FilterNumberFromUnit = function (unit) {
  337. let reg = new RegExp('^[0-9]+');
  338. if (reg.test(unit)) {
  339. return parseInt(unit.match(reg)[0]);
  340. } else {
  341. return 1;
  342. }
  343. };
  344. ration.prototype.CalculateQuantity = function (ration) {
  345. // calculate ration Quantity
  346. let quantity_decimal = getDecimal("ration.quantity");
  347. let process_decimal = getDecimal("process");
  348. if (optionsOprObj.getOption(optionsOprObj.optionsTypes.GENERALOPTS, 'rationQuanACToBillsQuan')) {
  349. let billsNode = this.project.Bills.tree.findNode(ration[this.project.masterField.ration]);
  350. let billsQuantity = billsNode.data.quantity ? billsNode.data.quantity : 0;
  351. billsQuantity=scMathUtil.roundForObj(billsQuantity,quantity_decimal);
  352. ration.quantityEXP="QDL";
  353. /* if (optionsOprObj.getOption(optionsOprObj.optionsTypes.GENERALOPTS, 'rationQuanACToRationUnit')) {
  354. ration.quantity = (billsQuantity / this.FilterNumberFromUnit(ration.unit)).toDecimal(quantity_decimal);
  355. } else {
  356. ration.quantity = billsQuantity.toDecimal(quantity_decimal);
  357. }*/
  358. ration.quantity = (billsQuantity / this.FilterNumberFromUnit(ration.unit)).toDecimal(quantity_decimal);//改成不管是否打勾都做转换
  359. ration.contain = scMathUtil.roundForObj(ration.quantity/billsQuantity,process_decimal);
  360. }
  361. };
  362. ration.prototype.updateRationCodes = function (recodes,cleanzmhs = false) {
  363. let libID = rationLibObj.getCurrentStdRationLibID();
  364. let libIDs = rationLibObj.getStdRationLibIDs();
  365. let defaultLibID = rationLibObj.getDefaultStdRationLibID();
  366. let engineering = projectObj.project.projectInfo.property.engineering;
  367. let projectID = projectObj.project.projectInfo.ID;
  368. let project = projectObj.project;
  369. let mainTree = project.mainTree;
  370. let nodeInfo =[];
  371. let refershNodes = [];
  372. if(libIDs == null){
  373. return;
  374. }
  375. //设置定额库的优先级, 当是清空子目换算时,使用原定额的定额库ID,其它情况再按: 默认先取选中的定额库,如果没有再取default定额库
  376. let selectedLib = null;
  377. if(cleanzmhs == true && recodes.length > 0){
  378. //原定额的定额库是补充工料机库,则用补充的库代替,不是的用原始定额库ID
  379. selectedLib = recodes[0].node.data.from == "cpt"?rationLibObj.compleRationLibId:recodes[0].node.data.libID;
  380. }else {
  381. selectedLib = sessionStorage.getItem("stdRationLib")
  382. }
  383. selectedLib&&selectedLib!='undefined'?libIDs.unshift(selectedLib):libIDs.unshift(defaultLibID);
  384. for(let r of recodes){
  385. let needInstall = false;
  386. if(projectObj.project.isInstall()) {//如果是安装工程,要看需不需要生成安装增加费
  387. needInstall = project.Bills.isFBFX(r.node);
  388. }
  389. r.value===null||r.value===undefined?"":r.value = r.value.replace(/[\s\r\n]/g, "");//去掉空格回车换行等字符
  390. if(cleanzmhs == true||r.value != r.node.data.code){
  391. nodeInfo.push({ID:r.node.data.ID,billsItemID:r.node.data.billsItemID,newCode:r.value,needInstall:needInstall});
  392. refershNodes.push(r.node);
  393. }
  394. }
  395. let calQuantity = optionsOprObj.getOption(optionsOprObj.optionsTypes.GENERALOPTS, 'rationQuanACToBillsQuan');
  396. $.bootstrapLoading.start();
  397. CommonAjax.post("/ration/replaceRations",{nodeInfo:nodeInfo,libIDs:libIDs,defaultLibID: defaultLibID,projectID:projectID,calQuantity:calQuantity,cleanzmhs:cleanzmhs,programArray: calcTools.getProgramArray()},function (data) {
  398. for(let recode of data){
  399. let node = mainTree.getNodeByID(recode.ration.ID);
  400. if(node) {
  401. for(let temkey in recode.ration){//更新缓存
  402. node.data[temkey] = recode.ration[temkey];
  403. }
  404. node.data.feesIndex = {};
  405. //删除定额节点下的主材和设备节点
  406. project.ration_glj.removeNodeByRation(recode.ration,projectObj.mainController);
  407. project.Ration.deleteSubListOfRation(recode.ration,cleanzmhs);//删除旧定额下的相关记录
  408. //添加新的记录
  409. project.Ration.addSubListOfRation(recode,false);
  410. project.ration_glj.addToMainTree(recode.ration_gljs);
  411. }
  412. }
  413. project.projectGLJ.calcQuantity();
  414. mbzm_obj.nodeChanged = true;//子目模板关联刷新
  415. project.calcProgram.calcNodesAndSave(refershNodes);
  416. projectObj.mainController.refreshTreeNode(refershNodes, true);
  417. gljOprObj.showDataIfRationSelect(projectObj.project.mainTree.selected,"-111111111");//这里第二个参数是为了使改前和改后selectedID不一样,删除了的话下方的定额工料机不会刷新
  418. $.bootstrapLoading.end();
  419. if(data.length < nodeInfo.length && nodeInfo[data.length].newCode!=null){//说明有部分定额编号没找到记录
  420. alert('当前库中找不到定额"' + nodeInfo[data.length].newCode + '"');
  421. }
  422. })
  423. };
  424. ration.prototype.addMultiRation = async function (items) {
  425. let me = this;
  426. let project = projectObj.project, sheetController = projectObj.mainController;
  427. let engineering = projectObj.project.projectInfo.property.engineering;
  428. let selected = project.mainTree.selected, newSource = null, newNode = null,pre = null,br = null;
  429. let billItemID = null,serialNo=1,nextID=null;
  430. let needInstall = false;
  431. let newDatas = [];
  432. if (selected === null) { return; }
  433. if (selected.sourceType === project.Bills.getSourceType() && selected.depth() > 0) {
  434. if (selected.source.children.length > 0) {
  435. alert('当前清单已有清单子项,不能套用定额。');
  436. } else if (selected.data.calcBase&&selected.data.calcBase!="") {
  437. alert('当前有基数计算,不能插入定额/量价/人材机。');
  438. } else {
  439. if(selected.data.type === billType.FB){
  440. return;
  441. }
  442. billItemID = selected.source.getID();
  443. nextID = selected.tree.rootID();
  444. br = this.getBillsSortRation(billItemID);
  445. serialNo = br.length > 0 ? br[br.length - 1].serialNo + 1 : 1
  446. }
  447. } else if (selected.sourceType === project.Ration.getSourceType()) {
  448. billItemID = selected.getParentID();
  449. br = this.getBillsSortRation(billItemID);
  450. serialNo = selected.data.serialNo+1;
  451. nextID = selected.getNextSiblingID();
  452. pre = selected.source;
  453. };
  454. if(billItemID){
  455. let calQuantity = optionsOprObj.getOption(optionsOprObj.optionsTypes.GENERALOPTS, 'rationQuanACToBillsQuan');
  456. if(projectObj.project.isInstall()) {//如果是安装工程,要看需不需要生成安装增加费
  457. let billsNode = project.mainTree.getNodeByID(billItemID);
  458. needInstall = project.Bills.isFBFX(billsNode);//在分部分项插入的定额才需要定额安装增加费
  459. }
  460. let programArray = calcTools.getProgramArray();
  461. for(let i = 0; i < items.length; i++){
  462. let newData = me.getTempRationData(me.getNewRationID(), billItemID, serialNo, items[i].rationType);
  463. serialNo++;
  464. let brUpdate = [];
  465. //更新兄弟节点的序列号
  466. if (i ===0 && pre) {
  467. let preIndex = br.indexOf(pre), i;
  468. for (i = preIndex + 1; i < br.length; i++) {
  469. br[i].serialNo = i < br.length - 1 ? br [i + 1].serialNo + items.length - 1 : br[i].serialNo + items.length;
  470. brUpdate.push({projectID:newData.projectID,ID:br[i].ID,serialNo:br[i].serialNo});
  471. }
  472. }
  473. newDatas.push({itemQuery: items[i].itemQuery, newData: newData, defaultLibID: rationLibObj.getDefaultStdRationLibID(), calQuantity: calQuantity, brUpdate: brUpdate, needInstall: needInstall,programArray:programArray})
  474. }
  475. const rstData = await ajaxPost('/ration/addMultiRation', { projectID: me.project.ID(), newDatas });
  476. let newNodes = [];
  477. //更新缓存
  478. for(let data of rstData){
  479. me.datas.push(data.ration);
  480. me.addSubListOfRation(data,false);
  481. //插入树节点
  482. newSource = data.ration;
  483. newNode = project.mainTree.insert(billItemID, nextID, newSource.ID);
  484. newNodes.push(newNode);
  485. newNode.source = newSource;
  486. newNode.sourceType = project.Ration.getSourceType();
  487. newNode.data = newSource;
  488. ProjectController.syncDisplayNewNode(sheetController, newNode);
  489. nextID = project.mainTree.selected.getNextSiblingID();
  490. }
  491. project.projectGLJ.calcQuantity();
  492. for(let data of rstData){
  493. project.ration_glj.addToMainTree(data.ration_gljs);
  494. }
  495. projectObj.mainController.refreshTreeNode(newNodes, false);
  496. if(project.Bills.isFBFX(newNodes[0])) { //判断是否属于分部分项工程 ,是的话才需要做计取安装费计算
  497. project.installation_fee.calcInstallationFee(function (isChange,rations) {
  498. if(isChange){
  499. rations = rations.concat(newNodes);
  500. project.calcProgram.calcNodesAndSave(rations);
  501. }else {
  502. project.calcProgram.calcNodesAndSave(newNodes);
  503. }
  504. });
  505. }else {
  506. project.calcProgram.calcNodesAndSave(newNodes);
  507. }
  508. }
  509. };
  510. ration.prototype.insertVolumePrice = function(type,ext){
  511. this.addNewRation(null,rationType.volumePrice,function (newNode) {//插入人工不需要自动定位到编号列
  512. projectObj.selectColAndFocus(newNode,null);
  513. },true,type,true,ext);
  514. };
  515. ration.prototype.addNewRation = function (itemQuery,rationType,callback=null,isEmpty=false,priceType,needCalcAndSave=true,ext) {//priceType 是量价类型
  516. let me = this;
  517. let project = projectObj.project, sheetController = projectObj.mainController;
  518. let engineering = projectObj.project.projectInfo.property.engineering;
  519. let selected = project.mainTree.selected, newSource = null, newNode = null,pre=null,br=null;
  520. let billItemID = null,serialNo=1,nextID=null;
  521. let needInstall = false;
  522. if (selected === null) { return null; }
  523. let startTime = +new Date();
  524. if (selected.sourceType === project.Bills.getSourceType() && selected.depth() > 0) {
  525. if(selected.data.type === billType.FB){
  526. return null;
  527. }
  528. else if (selected.source.children.length > 0) {
  529. alert('当前清单已有清单子项,不能套用定额。');
  530. } else if (selected.data.calcBase&&selected.data.calcBase!="") {
  531. alert('当前有基数计算,不能插入定额/量价/人材机。');
  532. } else {
  533. billItemID = selected.source.getID();
  534. nextID = selected.tree.rootID();
  535. br = this.getBillsSortRation(billItemID);
  536. serialNo = br.length > 0 ? br[br.length - 1].serialNo + 1 : 1
  537. }
  538. } else if (selected.sourceType === project.Ration.getSourceType()) {
  539. billItemID = selected.getParentID();
  540. br = this.getBillsSortRation(billItemID);
  541. serialNo = selected.data.serialNo+1;
  542. nextID = selected.getNextSiblingID();
  543. pre = selected.source;
  544. };
  545. if(billItemID){
  546. let newID = me.getNewRationID();
  547. let newData = me.getTempRationData(newID, billItemID, serialNo, rationType,priceType);
  548. let calQuantity = isEmpty===true?false:optionsOprObj.getOption(optionsOprObj.optionsTypes.GENERALOPTS, 'rationQuanACToBillsQuan');
  549. let brUpdate = [];
  550. //更新兄弟节点的序列号
  551. if (pre) {
  552. let preIndex = br.indexOf(pre), i;
  553. for (i = preIndex + 1; i < br.length; i++) {
  554. br[i].serialNo = i < br.length - 1 ? br [i + 1].serialNo : br[i].serialNo + 1;
  555. brUpdate.push({projectID:newData.projectID,ID:br[i].ID,serialNo:br[i].serialNo});
  556. }
  557. }
  558. if(projectObj.project.isInstall()) {//如果是安装工程,要看需不需要生成安装增加费
  559. let billsNode = project.mainTree.getNodeByID(billItemID);
  560. needInstall = project.Bills.isFBFX(billsNode);//在分部分项插入的定额才需要定额安装增加费
  561. }
  562. if(ext) gljUtil.setProperty(newData,ext);
  563. $.bootstrapLoading.start();
  564. let tdata = {
  565. projectID: me.project.ID(),
  566. itemQuery: itemQuery,
  567. newData: newData,
  568. defaultLibID: rationLibObj.getDefaultStdRationLibID(),
  569. calQuantity: calQuantity,
  570. brUpdate: brUpdate,
  571. needInstall: needInstall,
  572. programArray: calcTools.getProgramArray()
  573. }
  574. CommonAjax.post("/ration/addNewRation",tdata,function (data) {
  575. //更新缓存
  576. me.datas.push(data.ration);
  577. me.addSubListOfRation(data);
  578. //插入树节点
  579. newSource = data.ration;
  580. if(needCalcAndSave == false){
  581. syncNodeOper(data);
  582. if(callback) callback(newNode);
  583. }else {
  584. syncNodeOper(data);
  585. if (newNode.parent.data.calcFlag) newNode.parent.updateData.calcFlag = null; // 删除定额时不用改Flag,反正添加定额时已经改好了。
  586. project.calcProgram.calcAndSave(newNode,function () {
  587. let endShowTime = +new Date();
  588. console.log(`插入定额总时间——${endShowTime - startTime}`);
  589. if(project.Bills.isFBFX(newNode)) { //判断是否属于分部分项工程 ,是的话才需要做计取安装费计算
  590. installationFeeObj.calcInstallationFee();
  591. }
  592. });
  593. //如果添加规则中,添加内容为定额子目,则更新相关清单
  594. if(callback) callback(newNode);
  595. }
  596. $.bootstrapLoading.end();
  597. });
  598. return newNode;
  599. }
  600. else return null;
  601. function syncNodeOper(data) {//插入后刷新节点操作
  602. newNode = project.mainTree.insert(billItemID, nextID, newSource.ID);
  603. newNode.source = newSource;
  604. newNode.sourceType = project.Ration.getSourceType();
  605. newNode.data = newSource;
  606. ProjectController.syncDisplayNewNode(sheetController, newNode,function(){
  607. project.ration_glj.addToMainTree(data.ration_gljs);
  608. projectObj.mainController.refreshTreeNode([newNode], false);
  609. });
  610. }
  611. };
  612. ration.prototype.addNewRationFast = function (rationType,callback) {
  613. let me = this;
  614. let project = projectObj.project, sheetController = projectObj.mainController;
  615. let engineering = projectObj.project.projectInfo.property.engineering;
  616. let selected = project.mainTree.selected, newSource = null, newNode = null,pre=null,br=null;
  617. let billItemID = null,serialNo=1,nextID=null;
  618. if (selected === null) { return null; }
  619. if (selected.sourceType === project.Bills.getSourceType() && selected.depth() > 0) {
  620. if(selected.data.type === billType.FB){
  621. return null;
  622. }
  623. else if (selected.source.children.length > 0) {
  624. alert('当前清单已有清单子项,不能套用定额。');
  625. } else if (selected.data.calcBase&&selected.data.calcBase!="") {
  626. alert('当前有基数计算,不能插入定额/量价/人材机。');
  627. } else {
  628. billItemID = selected.source.getID();
  629. nextID = selected.tree.rootID();
  630. br = this.getBillsSortRation(billItemID);
  631. serialNo = br.length > 0 ? br[br.length - 1].serialNo + 1 : 1
  632. }
  633. } else if (selected.sourceType === project.Ration.getSourceType()) {
  634. billItemID = selected.getParentID();
  635. br = this.getBillsSortRation(billItemID);
  636. serialNo = selected.data.serialNo+1;
  637. nextID = selected.getNextSiblingID();
  638. pre = selected.source;
  639. };
  640. if(billItemID){
  641. let newID = me.getNewRationID();
  642. let newData = me.getTempRationData(newID, billItemID, serialNo, rationType);
  643. let brUpdate = [];
  644. //更新兄弟节点的序列号
  645. if (pre) {
  646. let preIndex = br.indexOf(pre), i;
  647. for (i = preIndex + 1; i < br.length; i++) {
  648. br[i].serialNo = i < br.length - 1 ? br [i + 1].serialNo : br[i].serialNo + 1;
  649. brUpdate.push({projectID:newData.projectID,ID:br[i].ID,serialNo:br[i].serialNo});
  650. }
  651. }
  652. if(projectObj.project.isInstall()) {//如果是安装工程,要看需不需要生成安装增加费
  653. let billsNode = project.mainTree.getNodeByID(billItemID);
  654. }
  655. $.bootstrapLoading.start();
  656. newNode = project.mainTree.insert(billItemID, nextID, newID);
  657. newNode.sourceType = project.Ration.getSourceType();
  658. newNode.data = newData;
  659. CommonAjax.post("/ration/addNewRation",{itemQuery:null,newData:newData,defaultLibID: rationLibObj.getDefaultStdRationLibID(),calQuantity:false,brUpdate:brUpdate,needInstall:false,programArray: calcTools.getProgramArray()},function (data) {
  660. //更新缓存
  661. me.datas.push(data.ration);
  662. me.addSubListOfRation(data);
  663. //插入树节点
  664. newSource = data.ration;
  665. newNode.source = newSource;
  666. newNode.data = newSource;
  667. });
  668. ProjectController.syncDisplayNewNode(sheetController, newNode);
  669. if(callback){
  670. callback(newNode);
  671. };
  672. if (newNode.parent.data.calcFlag) { // 删除定额时不用改Flag,反正添加定额时已经改好了。
  673. newNode.parent.updateData.calcFlag = null;
  674. project.calcProgram.calcAndSave(newNode.parent);
  675. };
  676. $.bootstrapLoading.end();
  677. return newNode;
  678. }
  679. else return null;
  680. };
  681. ration.prototype.deleteSubListOfRation = function(ration,cleanzmhs = false){
  682. projectObj.project.ration_glj.deleteByRation(ration);
  683. projectObj.project.ration_coe.deleteByRation(ration);
  684. if(cleanzmhs == false){
  685. projectObj.project.quantity_detail.deleteByRation(ration);
  686. projectObj.project.ration_installation.deleteByRation(ration);
  687. projectObj.project.ration_template.deleteByRation(ration);
  688. }
  689. };
  690. ration.prototype.addSubListOfRation = function (data,calquantity = true) {
  691. project.ration_glj.addDatasToList(data.ration_gljs);
  692. project.ration_coe.addDatasToList(data.ration_coes);
  693. project.ration_installation.addDatasToList(data.ration_installations);
  694. project.ration_template.addDatasToList(data.ration_templates);
  695. project.quantity_detail.addDatasToList(data.quantity_details);
  696. if(data.projectGLJList ) projectObj.project.projectGLJ.loadNewProjectGLJToCaches(data.projectGLJList,calquantity);
  697. };
  698. ration.prototype.replaceRation = function (ration, std) {
  699. this.project.beginUpdate('replaceRation');
  700. // delete
  701. let ration_glj =projectObj.project.ration_glj;
  702. this.project.push(this.project.ration_glj.getSourceType(), this.project.ration_glj.getDeleteDataByRation(ration));
  703. this.deleteSubListOfRation(ration);
  704. // insertNewRation
  705. let updateData = [];
  706. ration.code = std.code;
  707. ration.name = std.name;
  708. ration.caption = std.caption;
  709. ration.unit = std.unit;
  710. ration.libID = std.rationRepId;
  711. ration.content = std.jobContent;
  712. ration.adjustState = '';
  713. if (std.chapter) {
  714. ration.comments = std.chapter.explanation;
  715. ration.ruleText = std.chapter.ruleText;
  716. }
  717. ration.from = std.type === 'complementary' ? 'cpt' : 'std';
  718. ration.programID = std.feeType;
  719. ration.rationAssList = projectObj.project.ration_ass.CreateNewAss(std);
  720. // calculate ration Quantity
  721. this.CalculateQuantity(ration);
  722. updateData.push({updateType: 'ut_update', updateData: ration});
  723. this.project.push(this.getSourceType(), updateData);
  724. this.project.endUpdate();
  725. };
  726. ration.prototype.updateContain=function (value,node) {
  727. let me = this;
  728. if(isNaN(value)){
  729. alert("当前输入的数据类型不正确,请重新输入");
  730. projectObj.mainController.refreshTreeNode([node]);
  731. return;
  732. }
  733. if(node.data.quantityEXP=="GCLMXHJ"){//如果定额工程量是来自工程量明细
  734. hintBox.infoBox('操作确认', '已有工程量明细,是否清空明细表?', 2, function () {
  735. node.data.isFromDetail=0;
  736. project.quantity_detail.cleanQuantityDetail(node,true);
  737. me.doContainUpdate(value,node);
  738. }, function () {
  739. projectObj.mainController.refreshTreeNode([node]);
  740. },['确定','取消'],false);
  741. }else {
  742. me.doContainUpdate(value,node);
  743. }
  744. };
  745. ration.prototype.getNearRations = function (ration,callback) {
  746. if(ration&&ration.code && ration.code !=""){
  747. CommonAjax.post("/ration/getSameSectionRations",{from:ration.from,code:ration.code,libID:ration.libID},function(rations){
  748. callback(rations);
  749. })
  750. }else {
  751. callback([]);
  752. }
  753. };
  754. ration.prototype.doContainUpdate = function (value,node) {
  755. let billNode = node.parent;
  756. let contain = scMathUtil.roundForObj(value,getDecimal("process"));
  757. let billQuantity = billNode.data.quantity||billNode.data.quantity!=""?billNode.data.quantity:0;
  758. billQuantity = parseFloat(billQuantity);
  759. node.updateData.contain = contain;
  760. node.updateData.quantityEXP="QDL*"+contain;
  761. node.updateData.quantity=scMathUtil.roundForObj(billQuantity*contain,getDecimal("quantity",node));
  762. if(!gljUtil.isKGtoT(billNode.data.unit,node.data.unit)){
  763. console.log('hehe')
  764. let times = parseInt(node.data.unit);
  765. if (!isNaN(times)) {
  766. node.updateData.quantityEXP+='*'+times;
  767. }
  768. }
  769. // node.data.quantity = projectObj.project.quantity_detail.autoTransformQuantity(node.data.quantity,node);//按单位做转换
  770. node.changed = true;
  771. project.calcProgram.calcAndSave(node, function () {
  772. project.projectGLJ.calcQuantity();
  773. });
  774. projectObj.mainController.refreshTreeNode(node.children);//刷新子工料机树节点总消耗量
  775. };
  776. ration.prototype.addRationChecking=function(selected){
  777. if (selected) {// Vincent, 2018-01-02
  778. if(selected.sourceType === project.Ration.getSourceType()){ // 焦点行是定额/量价/工料机,有效显示。
  779. return false;
  780. }else if(selected.sourceType === project.Bills.getSourceType()){
  781. if(selected.data.type == billType.FX||selected.data.type == billType.BX){//焦点行是分项,有效显示。
  782. return false
  783. }
  784. if(selected.data.type == billType.BILL && selected.source.children.length === 0){//焦点行是清单,且没有子项,有效显示。
  785. return false
  786. }
  787. }
  788. }
  789. return true;
  790. };
  791. ration.prototype.canAdd = function (node) { // CSL.2018.07.23
  792. if (!node) return false;
  793. if (calcTools.isRationCategory(node)) return true;
  794. if (calcTools.isBill(node)){
  795. if (node.data.type == billType.FX || node.data.type == billType.BX) return true; // 分项、补项
  796. if (calcTools.isLeafBill(node)
  797. && (node.data.type != billType.DXFY)
  798. && (node.data.type != billType.FB)) return true; // 叶子清单项
  799. };
  800. return false;
  801. }
  802. ration.prototype.getAllInstallTypeRation = function () {//取所有计取安装增加费生成的定额
  803. return _.filter(this.datas,{'type':rationType.install});
  804. };
  805. ration.prototype.getLabourTotalFee=function(ration){//feesIndex.labour.totalFee 取定额的人工费合价
  806. if(ration.feesIndex&&ration.feesIndex.labour&&ration.feesIndex.labour.totalFee){
  807. return ration.feesIndex.labour.totalFee;
  808. }else {
  809. return 0;
  810. }
  811. };
  812. ration.prototype.getMaterialTotalFee=function(ration){//feesIndex.material.totalFee 取定额的材料费合价
  813. if(ration.feesIndex&&ration.feesIndex.material&&ration.feesIndex.material.totalFee){
  814. return ration.feesIndex.material.totalFee;
  815. }else {
  816. return 0;
  817. }
  818. } ;
  819. ration.prototype.getMachineTotalFee=function(ration){//feesIndex.machine.totalFee 取定额的机械费合价
  820. if(ration.feesIndex&&ration.feesIndex.machine&&ration.feesIndex.machine.totalFee){
  821. return ration.feesIndex.machine.totalFee;
  822. }else {
  823. return 0;
  824. }
  825. } ;
  826. //获取定额前缀
  827. ration.prototype.getRationPrefix = function(defaultLibID, ration){
  828. if(defaultLibID !== ration.libID){
  829. return rationPrefix.borrow;
  830. }
  831. if(ration.from && ration.from === rationFrom.cpt){
  832. return rationPrefix.complementary;
  833. }
  834. return rationPrefix.none;
  835. };
  836. return new ration(project);
  837. }
  838. };
  839. function FilterNumberFromUnit (unit) {
  840. let reg = new RegExp('^[0-9]+');
  841. if (reg.test(unit)) {
  842. return parseInt(unit.match(reg)[0]);
  843. } else {
  844. return 1;
  845. }
  846. };