ration.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  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 = {};
  52. data.fees.forEach(function (fee) {
  53. data.feesIndex[fee.fieldName] = fee;
  54. });
  55. data.flagsIndex = {};
  56. data.flags.forEach(function (flag) {
  57. data.flagsIndex[flag.fieldName] = flag;
  58. });
  59. that.maxRationID(data.ID);
  60. });
  61. };
  62. ration.prototype.setMaxID = function (ID) {
  63. this.maxRationID(ID);
  64. }
  65. // refresh after update
  66. ration.prototype.doAfterUpdate = function(err, data){
  67. if(data.stateRefresh){
  68. this.refreshAdjustState(data);
  69. }
  70. if(data.quantityRefresh){
  71. this.refreshQuantity(data);
  72. }
  73. };
  74. ration.prototype.refreshAdjustState = function(data){
  75. this.refreshDatas(data,'adjustState');
  76. if(data.hasOwnProperty('name')){
  77. this.refreshDatas(data,'name')
  78. }
  79. };
  80. ration.prototype.refreshQuantity = function(data){
  81. this.refreshDatas(data,'quantity');
  82. };
  83. ration.prototype.refreshDatas = function(data,fieldName){
  84. var dataIndex = _.findIndex(this.datas,function(item) {
  85. return item.ID ==data.rationID;
  86. });
  87. this.datas[dataIndex][fieldName] = data[fieldName];
  88. if(fieldName=='quantity'){
  89. this.datas[dataIndex]['isFromDetail']=1
  90. }
  91. var controller = projectObj.mainController;
  92. var selected = controller.sheet.getSelections();
  93. var col = _.findIndex(project.projSetting.main_tree_col.cols,function (col) {
  94. return col.data.field ==fieldName;
  95. });
  96. controller.sheet.getCell(selected[0].row,col).value(data[fieldName]);
  97. };
  98. ration.prototype.getTempRationData = function (id, billsID, serialNo, rType) {
  99. var newData = {'ID': id, 'serialNo': serialNo, projectID: this.project.ID()};
  100. newData[project.masterField.ration] = billsID;
  101. newData['type'] = rType;
  102. if (rType == rationType.volumePrice){
  103. newData['subType'] = gljType.GENERAL_MATERIAL; // 默认的量价类型为材料
  104. newData['programID'] = projectInfoObj.projectInfo.property.engineering;
  105. };
  106. return newData;
  107. };
  108. ration.prototype.getBillsSortRation = function (billsID) { // 该方法只适用于叶子清单
  109. var rations = this.datas.filter(function (data) {
  110. return data[project.masterField.ration] === billsID;
  111. });
  112. rations.sort(function (x, y) {
  113. return x.serialNo - y.serialNo;
  114. });
  115. return rations;
  116. };
  117. // CSL, 2017-11-13 取任何清单(父清单、叶子清单)下的所有定额
  118. ration.prototype.getRationNodes = function (billNode) {
  119. if (billNode.sourceType != ModuleNames.bills) return [];
  120. let rations = [], IDs = [];
  121. function getSubBillsIDs(node) {
  122. if (!node) return;
  123. if (node.sourceType != sBills) return;
  124. if (!node.children || node.children.length == 0 || node.children[0].sourceType != sBills)
  125. IDs.push(node.data.ID)
  126. else
  127. getSubBillsIDs(node.children[0]);
  128. getSubBillsIDs(node.nextSibling);
  129. };
  130. if (billNode.source.children.length == 0)
  131. IDs.push(billNode.data.ID)
  132. else
  133. getSubBillsIDs(billNode.children[0]);
  134. for (let id of IDs){
  135. let subRations = this.datas.filter(function (data) {
  136. return data[project.masterField.ration] === id;
  137. });
  138. rations.push(...subRations);
  139. };
  140. rations.sort(function (x, y) {
  141. return x.serialNo - y.serialNo;
  142. });
  143. let rationNodes = [];
  144. for (let ration of rations){
  145. rationNodes.push(projectObj.project.mainTree.nodes['id_' + ration.ID]);
  146. };
  147. return rationNodes;
  148. };
  149. ration.prototype.getInsertRationData = function (billsID, preRation, rationType) {
  150. var br = this.getBillsSortRation(billsID);
  151. var updateData = [];
  152. if (preRation) {
  153. var preIndex = br.indexOf(preRation), i;
  154. updateData.push({updateType: 'ut_create', updateData: this.getTempRationData(this.getNewRationID(), billsID, preIndex < br.length - 1 ? br[preIndex + 1].serialNo : br[preIndex].serialNo + 1, rationType)});
  155. for (i = preIndex + 1; i < br.length; i++) {
  156. 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)});
  157. }
  158. } else {
  159. updateData.push({updateType: 'ut_create', updateData: this.getTempRationData(this.getNewRationID(), billsID, br.length > 0 ? br[br.length - 1].serialNo + 1 : 1, rationType)});
  160. }
  161. return updateData;
  162. };
  163. ration.prototype.getCounterData = function (count) {
  164. var updateData = {'projectID': this.project.ID()};
  165. if (count) {
  166. updateData[this.getSourceType()] = this.maxRationID() + count;
  167. } else {
  168. updateData[this.getSourceType()] = this.maxRationID() + 1;
  169. }
  170. return updateData;
  171. };
  172. ration.prototype.insertRation = function (billsID, preRation, rationType) {
  173. var br = this.getBillsSortRation(billsID);
  174. let insertData = this.getInsertRationData(billsID, preRation, rationType);
  175. this.project.pushNow('insertRation', [this.getSourceType(), this.project.projCounter()],
  176. [insertData, this.getCounterData()]);
  177. var newRation = null;
  178. let newID = -1;
  179. for(let data of insertData){
  180. if(data.updateType === 'ut_create'){
  181. newID = data.updateData.ID;
  182. }
  183. }
  184. if (preRation) {
  185. var preIndex = br.indexOf(preRation), i;
  186. newRation = this.getTempRationData(newID, billsID, preIndex < br.length - 1 ? br[preIndex + 1].serialNo : br[preIndex].serialNo + 1, rationType);
  187. this.datas.push(newRation);
  188. for (i = preIndex + 1; i < br.length; i++) {
  189. br[i].serialNo = i < br.length - 1 ? br [i + 1].serialNo : br[i].serialNo + 1;
  190. }
  191. } else {
  192. newRation = this.getTempRationData(newID, billsID, br.length > 0 ? br[br.length - 1].serialNo + 1 : 1, rationType);
  193. this.datas.push(newRation);
  194. }
  195. return newRation;
  196. };
  197. ration.prototype.insertStdRation = function (billsID, preRation, std) {
  198. var br = this.getBillsSortRation(billsID), updateData = this.getInsertRationData(billsID, preRation, rationType.ration), newRation = null, that = this;
  199. updateData.forEach(function (data) {
  200. if (data.updateType === 'ut_create') {
  201. data.updateData.code = std.code;
  202. data.updateData.name = std.name;
  203. data.updateData.caption = std.caption;
  204. data.updateData.unit = std.unit;
  205. data.updateData.libID = std.rationRepId;
  206. data.updateData.content = std.jobContent;
  207. if (std.chapter) {
  208. data.updateData.comments = std.chapter.explanation;
  209. data.updateData.ruleText = std.chapter.ruleText;
  210. }
  211. data.updateData.from = std.type === 'complementary' ? 'cpt' : 'std';
  212. data.updateData.programID = std.feeType;
  213. data.updateData.rationAssList = projectObj.project.ration_ass.CreateNewAss(std);
  214. // calculate ration Quantity
  215. that.CalculateQuantity(data.updateData);
  216. newRation = data.updateData;
  217. }
  218. });
  219. this.project.pushNow('insertRation', [this.getSourceType(), this.project.projCounter()], [updateData, this.getCounterData()]);
  220. //newRation.ID = this.getNewRationID();
  221. if (preRation) {
  222. var preIndex = br.indexOf(preRation), i;
  223. this.datas.push(newRation);
  224. for (i = preIndex + 1; i < br.length; i++) {
  225. br[i].serialNo = i < br.length - 1 ? br [i + 1].serialNo : br[i].serialNo + 1;
  226. }
  227. } else {
  228. this.datas.push(newRation);
  229. }
  230. return newRation;
  231. };
  232. ration.prototype.getDeleteData = function (rationData) {
  233. var updateData = [];
  234. updateData.push({'updateType': 'ut_delete', 'updateData': {'ID': rationData.ID, 'projectID': this.project.ID()}});
  235. return updateData;
  236. };
  237. ration.prototype.delete = function (ration) {
  238. var ration_glj =projectObj.project.ration_glj;
  239. this.project.pushNow('deleteRation', [this.getSourceType(),ration_glj.getSourceType()], [this.getDeleteData(ration),ration_glj.getDeleteDataByRation(ration)]);
  240. project.ration_glj.deleteByRation(ration);
  241. project.ration_coe.deleteByRation(ration);
  242. project.quantity_detail.deleteByRation(ration);
  243. this.datas.splice(this.datas.indexOf(ration), 1);
  244. };
  245. ration.prototype.getDeleteDataByBill = function (nodes) {
  246. let updateData = [];
  247. for (let node of nodes) {
  248. if (node.children.length > 0) {
  249. updateData = updateData.concat(this.getDeleteDataByBill(node.children));
  250. } else {
  251. let rations = this.getBillsSortRation(node.getID());
  252. for (let r of rations) {
  253. updateData.push({'updateType': 'ut_delete', 'updateData': {'ID': r.ID, 'projectID': this.project.ID()}});
  254. }
  255. }
  256. }
  257. return updateData;
  258. };
  259. ration.prototype.deleteByBills = function (nodes) {
  260. for (let node of nodes) {
  261. if (node.children.length > 0) {
  262. this.deleteByBills(node.children);
  263. } else {
  264. let rations = this.getBillsSortRation(node.getID());
  265. for (let r of rations) {
  266. this.datas.splice(this.datas.indexOf(r), 1);
  267. }
  268. }
  269. }
  270. }
  271. ration.prototype.getChangePosUpdateData = function (ration1, ration2) {
  272. var updateData = [];
  273. updateData.push({updateType: 'ut_update', updateData: this.getTempRationData(ration1.ID, ration1.billsItemID, ration2.serialNo)});
  274. updateData.push({updateType: 'ut_update', updateData: this.getTempRationData(ration2.ID, ration2.billsItemID, ration1.serialNo)});
  275. return updateData;
  276. };
  277. ration.prototype.changePos = function (ration1, ration2) {
  278. var updateData = this.getChangePosUpdateData(ration1, ration2);
  279. this.project.pushNow('insertRation', [this.getSourceType()], [updateData]);
  280. var preSerialNo = ration1.serialNo;
  281. ration1.serialNo = ration2.serialNo;
  282. ration2.serialNo = preSerialNo;
  283. };
  284. ration.prototype.updateField = function (ration, field, newValue) {
  285. calcFees.setFee(ration, field, newValue);
  286. let updateData = [];
  287. let data = {'ID': ration.ID, 'projectID': this.project.ID()};
  288. if (field === 'quantity') {
  289. data[field] = newValue;
  290. data.isFromDetail=0;
  291. // to do Calculate
  292. if (ration.fees) {
  293. data.fees = ration.fees;
  294. }
  295. } else if (field === 'feesIndex.common.unitFee') {
  296. // to do Calculate
  297. if (ration.fees) {
  298. data.fees = ration.fees;
  299. }
  300. } else {
  301. data[field] = newValue;
  302. }
  303. updateData.push({'updateType': 'ut_update', 'updateData': data});
  304. this.project.pushNow('updateBills', this.getSourceType(), updateData);
  305. };
  306. ration.prototype.updateRation = function (ration, updateNow) {
  307. let updateData = [];
  308. updateData.push({'updateType': 'ut_update', 'updateData': tools.formatRationUpdateData(ration)});
  309. if (updateNow) {
  310. this.project.pushNow('updateRations', this.getSourceType(), updateData);
  311. } else {
  312. this.project.push(this.getSourceType(), updateData);
  313. }
  314. };
  315. ration.prototype.FilterNumberFromUnit = function (unit) {
  316. let reg = new RegExp('^[0-9]+');
  317. if (reg.test(unit)) {
  318. return parseInt(unit.match(reg)[0]);
  319. } else {
  320. return 1;
  321. }
  322. };
  323. ration.prototype.CalculateQuantity = function (ration) {
  324. // calculate ration Quantity
  325. let quantity_decimal = getDecimal("ration.quantity");
  326. let process_decimal = getDecimal("process");
  327. if (optionsOprObj.getOption(optionsOprObj.optionsTypes.GENERALOPTS, 'rationQuanACToBillsQuan')) {
  328. let billsNode = this.project.Bills.tree.findNode(ration[this.project.masterField.ration]);
  329. let billsQuantity = billsNode.data.quantity ? billsNode.data.quantity : 0;
  330. billsQuantity=scMathUtil.roundForObj(billsQuantity,quantity_decimal);
  331. ration.contain = 1;
  332. ration.quantityEXP="QDL";
  333. if (optionsOprObj.getOption(optionsOprObj.optionsTypes.GENERALOPTS, 'rationQuanACToRationUnit')) {
  334. ration.quantity = (billsQuantity / this.FilterNumberFromUnit(ration.unit)).toDecimal(quantity_decimal);
  335. } else {
  336. ration.quantity = billsQuantity.toDecimal(quantity_decimal);
  337. }
  338. }
  339. };
  340. ration.prototype.replaceRation = function (ration, std) {
  341. this.project.beginUpdate('replaceRation');
  342. // delete
  343. let ration_glj =projectObj.project.ration_glj;
  344. this.project.push(this.project.ration_glj.getSourceType(), this.project.ration_glj.getDeleteDataByRation(ration));
  345. this.project.ration_glj.deleteByRation(ration);
  346. this.project.ration_coe.deleteByRation(ration);
  347. this.project.quantity_detail.deleteByRation(ration);
  348. // insertNewRation
  349. let updateData = [];
  350. ration.code = std.code;
  351. ration.name = std.name;
  352. ration.caption = std.caption;
  353. ration.unit = std.unit;
  354. ration.libID = std.rationRepId;
  355. ration.content = std.jobContent;
  356. ration.adjustState = '';
  357. if (std.chapter) {
  358. ration.comments = std.chapter.explanation;
  359. ration.ruleText = std.chapter.ruleText;
  360. }
  361. ration.from = std.type === 'complementary' ? 'cpt' : 'std';
  362. ration.programID = std.feeType;
  363. ration.rationAssList = projectObj.project.ration_ass.CreateNewAss(std);
  364. // calculate ration Quantity
  365. this.CalculateQuantity(ration);
  366. updateData.push({updateType: 'ut_update', updateData: ration});
  367. this.project.push(this.getSourceType(), updateData);
  368. this.project.endUpdate();
  369. };
  370. ration.prototype.updateContain=function (value,node) {
  371. if(isNaN(value)){
  372. alert("当前输入的数据类型不正确,请重新输入");
  373. projectObj.mainController.refreshTreeNode([node]);
  374. return;
  375. }
  376. let billNode = node.parent;
  377. let contain = scMathUtil.roundForObj(value,getDecimal("process"));
  378. if(node.data.quantityEXP=="GCLMXHJ"){//如果定额工程量是来自工程量明细
  379. var c = confirm('已有工程量明细,是否清空明细表,采用手工输入的表达式?');
  380. if(c){
  381. node.data.isFromDetail=0;
  382. project.quantity_detail.cleanQuantityDetail(node,true);
  383. }else {
  384. projectObj.mainController.refreshTreeNode([node]);
  385. return;
  386. }
  387. }
  388. let billQuantity = billNode.data.quantity||billNode.data.quantity!=""?billNode.data.quantity:0;
  389. billQuantity = parseFloat(billQuantity);
  390. node.data.contain = contain;
  391. node.data.quantityEXP="QDL*"+contain;
  392. node.data.quantity=scMathUtil.roundForObj(billQuantity*contain,getDecimal("quantity"),node);
  393. node.data.quantity = projectObj.project.quantity_detail.autoTransformQuantity(node.data.quantity,node);//按单位做转换
  394. node.changed = true;
  395. project.calcProgram.calcAndSave(node);
  396. projectObj.mainController.refreshTreeNode(node.children);//刷新子工料机树节点总消耗量
  397. };
  398. ration.prototype.addRationChecking=function(selected){
  399. if (selected) {// Vincent, 2018-01-02
  400. if(selected.sourceType === project.Ration.getSourceType()){ // 焦点行是定额/量价/工料机,有效显示。
  401. return false;
  402. }else if(selected.sourceType === project.Bills.getSourceType()){
  403. if(selected.data.type == billType.FX){//焦点行是分项,有效显示。
  404. return false
  405. }
  406. if(selected.data.type == billType.BILL && selected.source.children.length === 0){//焦点行是清单,且没有子项,有效显示。
  407. return false
  408. }
  409. }
  410. }
  411. return true;
  412. };
  413. return new ration(project);
  414. }
  415. };