ration_facade.js 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791
  1. /**
  2. * Created by zhang on 2018/2/9.
  3. */
  4. let mongoose = require('mongoose');
  5. import SearchDao from '../../complementary_ration_lib/models/searchModel';
  6. const scMathUtil = require('../../../public/scMathUtil').getUtil();
  7. let gljUtil = require('../../../public/gljUtil');
  8. let ration_glj_facade = require("../../ration_glj/facade/ration_glj_facade");
  9. let glj_calculate_facade = require("../../ration_glj/facade/glj_calculate_facade");
  10. let quantity_detail = require("../facade/quantity_detail_facade");
  11. let ration_glj = mongoose.model('ration_glj');
  12. let ration_coe = mongoose.model('ration_coe');
  13. let ration_model = require('../models/ration');
  14. let bill_model = require('../models/bills');
  15. let decimal_facade = require('./decimal_facade');
  16. let installationFeeModel = mongoose.model("installation_fee");
  17. let rationInstallationModel = mongoose.model('ration_installation');
  18. let rationTemplateModel = mongoose.model('ration_template');
  19. const uuidV1 = require('uuid/v1');
  20. let std_glj_lib_gljList_model = mongoose.model('std_glj_lib_gljList');
  21. let complementary_glj_model = mongoose.model('complementary_glj_lib');
  22. let rationItemModel = mongoose.model("std_ration_lib_ration_items");
  23. let complementaryRationModel = mongoose.model('complementary_ration_items');
  24. let freightCalcModel = mongoose.model('freight_calc');
  25. let originaltCalcModel = mongoose.model('original_calc');
  26. let coeMolde = mongoose.model('std_ration_lib_coe_list');
  27. let compleCoeModel = mongoose.model('complementary_ration_coe_list');
  28. let _= require('lodash');
  29. const projectDao = require('../../pm/models/project_model').project;
  30. let projectModel = mongoose.model('projects');
  31. const fs = require('fs');
  32. module.exports = {
  33. replaceRations: replaceRations,
  34. addNewRation:addNewRation,
  35. updateMaterialRation:updateMaterialRation,
  36. addMaterialRation:addMaterialRation,
  37. addMultiRation: addMultiRation,
  38. getSameSectionRations:getSameSectionRations,
  39. getExtendData:getExtendData,
  40. getDefaultProgramID:getDefaultProgramID,
  41. deleteSubListByQuery:deleteSubListByQuery,
  42. updateCoeAdjust:updateCoeAdjust
  43. };
  44. async function addNewRation(data,compilation) {
  45. let query = data.itemQuery;
  46. let stdRation = null;
  47. let startTime = +new Date();
  48. if(query){
  49. let searchDao = new SearchDao();
  50. stdRation = await searchDao.getRationItem(query.userID, compilation._id, [query.rationRepId],query.code, query.ID);
  51. //data.newData.code = query.code;
  52. }
  53. let stdRationTime = +new Date();
  54. console.log("取std定额时间-------------------------------"+(stdRationTime - startTime));
  55. if(data.brUpdate.length>0){
  56. await updateSerialNo(data.brUpdate);
  57. }
  58. let newRation =await insertNewRation(data.newData,data.defaultLibID,stdRation,data.calQuantity);
  59. let addRationGLJTime = +new Date();
  60. console.log("插入新定额时间-------------------------------"+(addRationGLJTime - stdRationTime));
  61. if(stdRation){
  62. return await addRationSubList(stdRation,newRation,data.needInstall,compilation);
  63. }else {
  64. return {ration:newRation};
  65. }
  66. }
  67. async function updateMaterialRation(data,compilation){
  68. let result = {};
  69. switch (data.actionType){
  70. case "add":
  71. result = await addMaterialRation(data,compilation);
  72. break;
  73. case "delete":
  74. result = await deleteMaterialRation(data);
  75. case "update":
  76. result = await modifyMaterialRation(data,compilation);
  77. }
  78. return result;
  79. }
  80. async function deleteMaterialRation(data) {
  81. let model = data.type == "freight"?freightCalcModel:originaltCalcModel;
  82. await model.update(
  83. {ID:data.parentID},
  84. { $pull: { rations: { ID: data.rationID},ration_gljs:{rationID:data.rationID} } },
  85. { multi: true }
  86. );
  87. return data;
  88. }
  89. async function modifyMaterialRation(data,compilation) {
  90. let model = data.type == "freight"?freightCalcModel:originaltCalcModel;
  91. if(data.field == "code"){
  92. let [newRation,ration_gljs,projectGLJList] = await getNewMaterialRationDatas(data,compilation);
  93. let quantity = data.rations[data.row].quantity;
  94. newRation.quantity = quantity;
  95. data.rations[data.row] = newRation;
  96. _.remove(data.ration_gljs,{rationID:data.rationID});
  97. data.ration_gljs = data.ration_gljs.concat(ration_gljs);
  98. await model.update({'ID':data.parentID},{rations:data.rations,ration_gljs:data.ration_gljs});
  99. return {ration:newRation,ration_gljs:ration_gljs,projectGLJList:projectGLJList}
  100. }else {
  101. let doc = {},pre = "rations.$.";
  102. let field = pre+data.field;
  103. doc[field] = data.value;
  104. if(data.ext){
  105. for(let key in data.ext){
  106. doc[pre+key] = data.ext[key];
  107. }
  108. }
  109. if(data.ration_gljs){
  110. let tasks = [];
  111. for(let g of data.ration_gljs){
  112. tasks.push({updateOne: {filter: {'ID':data.parentID,'ration_gljs.ID':g.ID}, update: {"ration_gljs.$.quantity":g.quantity}}})
  113. }
  114. await model.bulkWrite(tasks);
  115. }
  116. return await model.update({'ID':data.parentID,'rations.ID':data.rationID},doc);
  117. }
  118. }
  119. async function addMaterialRation(data,compilation) {
  120. let [newRation,ration_gljs,projectGLJList] = await getNewMaterialRationDatas(data,compilation);
  121. let model = data.type == "freight"?freightCalcModel:originaltCalcModel;
  122. await model.update({ID:data.parentID},{$push:{rations:newRation,ration_gljs:{$each:ration_gljs}}});
  123. return{ration:newRation,ration_gljs:ration_gljs,projectGLJList:projectGLJList};
  124. }
  125. async function getNewMaterialRationDatas(data,compilation){
  126. let searchDao = new SearchDao();
  127. let stdRation = await searchDao.getRationItem(data.userID, compilation._id, data.rationRepIds,data.code);
  128. if(!stdRation) throw "找不到指定的定额!";//new Error("找不到指定的定额!");
  129. let newRation = await createNewMaterialRation(stdRation,data.quantityDecimal,data.projectID);
  130. let [ration_gljs,projectGLJList] = await addRationGLJ(stdRation,newRation,compilation,true,data.connect_key);
  131. return [newRation,ration_gljs,projectGLJList];
  132. }
  133. async function createNewMaterialRation(std,quantityDecimal,projectID){
  134. let newData = {};
  135. newData.ID = uuidV1();
  136. newData.projectID = projectID;
  137. newData.code = std.code;
  138. newData.name = std.name;
  139. newData.caption = std.caption;
  140. newData.unit = std.unit;
  141. newData.libID = std.rationRepId;
  142. newData.stdID = std.ID;
  143. newData.quantity=scMathUtil.roundForObj(1 / FilterNumberFromUnit(std.unit),quantityDecimal);
  144. newData.from = std.type === 'complementary' ? 'cpt' : 'std';
  145. newData.rationAssList =await createRationAss(std,true);
  146. return newData;
  147. }
  148. async function addMultiRation(datas,compilation) {
  149. let rst = [];
  150. for(let data of datas){
  151. let r = await addNewRation(data,compilation);
  152. rst.push(r);
  153. }
  154. return rst;
  155. }
  156. async function getSameSectionRations(data,userId,compilationId){
  157. //let userId
  158. //要先根据定额获取所属章节的ID
  159. let from = data.from; //定额类型,是标准的还是用户定义的
  160. let code = data.code;
  161. let libID = data.libID;
  162. let sectionId,rations=[];
  163. if(from == 'std'){
  164. let ration = await rationItemModel.findOne({rationRepId:libID,code:code},['sectionId']);
  165. sectionId = ration? ration.sectionId:null;
  166. }else {
  167. let ration = await complementaryRationModel.findOne({userId:userId,compilationId: compilationId,code:code},['sectionId']);
  168. sectionId = ration?ration.sectionId:null;
  169. }
  170. if(sectionId){
  171. if (from == 'std') {
  172. rations = await rationItemModel.find({sectionId: sectionId});
  173. } else {
  174. rations = await complementaryRationModel.find({userId: userId, sectionId: sectionId});
  175. }
  176. rations = _.sortBy(rations,'code');
  177. }
  178. return rations
  179. }
  180. async function updateSerialNo(serialNoUpdate){
  181. let tasks=[];
  182. for(let data of serialNoUpdate){
  183. let task={
  184. updateOne:{
  185. filter:{
  186. ID:data.ID,
  187. projectID:data.projectID
  188. },
  189. update :{
  190. serialNo:data.serialNo
  191. }
  192. }
  193. };
  194. tasks.push(task);
  195. }
  196. await ration_model.model.bulkWrite(tasks);
  197. }
  198. async function insertNewRation(newData,defaultLibID,std,calQuantity) {//插入新的定额
  199. let startTime = +new Date();
  200. if(std){
  201. newData.code = std.code;
  202. newData.name = std.name;
  203. newData.caption = std.caption;
  204. newData.unit = std.unit;
  205. newData.libID = std.rationRepId;
  206. newData.stdID = std.ID;
  207. newData.content = std.jobContent;
  208. newData.annotation = std.annotation;
  209. if (std.chapter) {
  210. newData.comments = std.chapter.explanation;
  211. newData.ruleText = std.chapter.ruleText;
  212. }
  213. newData.prefix = '';
  214. newData.from = std.type === 'complementary' ? 'cpt' : 'std';
  215. if(defaultLibID !== std.rationRepId){//借
  216. newData.prefix = '借';
  217. }
  218. else if(std.rationRepId === defaultLibID && newData.from === 'cpt') {
  219. newData.prefix = '补';
  220. }
  221. if(std.feeType == undefined || std.feeType == null || std.feeType ==''){//定额取费专业为空的情况下,取项目属性中的定额取费专业ID
  222. newData.programID = await getProgramForProject(newData.projectID);
  223. }else {
  224. newData.programID = std.feeType;
  225. }
  226. newData.rationAssList =await createRationAss(std);
  227. // calculate ration Quantity
  228. }
  229. if(calQuantity){
  230. await CalculateQuantity(newData,newData.billsItemID,newData.projectID);
  231. }
  232. let addRationGLJTime = +new Date();
  233. console.log("计算消耗量时间-------------------------------"+(addRationGLJTime - startTime));
  234. let newRation = await ration_model.model.create(newData);
  235. return newRation;
  236. /*ration_model.model.create(newData);
  237. return newData;*/
  238. }
  239. async function replaceRations(userID,data,compilation) {
  240. let searchDao = new SearchDao();
  241. let recodes = [];
  242. for(let recode of data.nodeInfo){
  243. let stdRation = await searchDao.getRationItem(userID,compilation._id,data.libIDs,recode.newCode, null);
  244. let newRecode = await replaceRation(recode,stdRation,data.defaultLibID,data.projectID,data.calQuantity,compilation,data.cleanzmhs);
  245. if(newRecode){
  246. recodes.push(newRecode);
  247. }else {
  248. break;
  249. }
  250. }
  251. return recodes;
  252. }
  253. async function getDefaultProgramID(data) {
  254. let searchDao = new SearchDao();
  255. let programID;
  256. let std = await searchDao.getRationItem(data.userID,data.compilationId,[data.libID],data.code, null);
  257. if(std == null||std ==undefined || std.feeType == undefined || std.feeType == null || std.feeType ==''){//定额取费专业为空的情况下,取项目属性中的定额取费专业ID
  258. programID = await getProgramForProject(data.projectID);
  259. }else {
  260. programID = std.feeType;
  261. }
  262. return programID;
  263. }
  264. async function replaceRation(nodeInfo,stdRation,defaultLibID,projectID,calQuantity,compilation,cleanzmhs) {
  265. if(nodeInfo.newCode == null||nodeInfo.newCode ==""){//说明是删除编号,则要变成一条空定额
  266. await deleRationSubRecode(projectID,nodeInfo.ID);//删除定额下挂的各种数据,如定额工料机等
  267. return await setEmptyRation(projectID,nodeInfo.ID);
  268. }else if(stdRation){
  269. await deleRationSubRecode(projectID,nodeInfo.ID,cleanzmhs);//删除定额下挂的各种数据,如定额工料机等
  270. let newRation = await updateRation(stdRation,defaultLibID,nodeInfo.ID,nodeInfo.billsItemID,projectID,calQuantity,cleanzmhs);//生成并插入新的定额
  271. return await addRationSubList(stdRation,newRation,nodeInfo.needInstall,compilation,cleanzmhs);
  272. }else {
  273. return null;
  274. }
  275. }
  276. async function addRationSubList(stdRation,newRation,needInstall,compilation,cleanzmhs=false) {
  277. let startTime = +new Date();
  278. let [ration_gljs,projectGLJList] = await addRationGLJ(stdRation,newRation,compilation);
  279. let addRationGLJTime = +new Date();
  280. console.log("添加定额工料机时间-----"+(addRationGLJTime - startTime));
  281. let ration_coes = await addRationCoe(stdRation,newRation,compilation);
  282. let addRationCoeTime = +new Date();
  283. console.log("添加定额coe时间-----"+(addRationCoeTime - addRationGLJTime));
  284. let ration_installations = [];
  285. let ration_template = [];
  286. if(cleanzmhs == false){//清除子目换算即cleanzmh==true时 模板子目、安装增加费不用恢复成标准的
  287. if(needInstall && stdRation.type == 'std'){//只有标准的定额才有安装增加费,补充的定额没有安装增加费
  288. ration_installations = await addRationInstallFee(stdRation,newRation);
  289. }
  290. let addRationInstallFeeTime = +new Date();
  291. console.log("添加定额install时间-----"+(addRationInstallFeeTime - addRationCoeTime));
  292. //添加定额模板子目
  293. ration_template = await addRationTemplate(stdRation,newRation);
  294. }
  295. return {ration:newRation,ration_gljs:ration_gljs,ration_coes:ration_coes,ration_installations:ration_installations,ration_templates:ration_template?[ration_template]:[],projectGLJList:projectGLJList};
  296. }
  297. async function addRationInstallFee(std,newRation) {
  298. let install_fee_list = [];
  299. if(std.hasOwnProperty('rationInstList') && std.rationInstList.length > 0){
  300. let installFee = await installationFeeModel.findOne({'projectID': newRation.projectID});
  301. if(!installFee) return;//如果没有找到项目对应的安装增加费,则不添加
  302. for(let ri of std.rationInstList){
  303. let feeItem = _.find(installFee.installFeeItem,{'ID':ri.feeItemId});
  304. let section = _.find(installFee.installSection,{'ID':ri.sectionId});
  305. if(feeItem&&section){
  306. let tem_r_i = {
  307. libID:installFee.libID,
  308. projectID:newRation.projectID,
  309. rationID:newRation.ID,
  310. feeItemId:feeItem.ID,
  311. sectionId:section.ID,
  312. itemName:feeItem.feeItem,
  313. feeType:feeItem.feeType,
  314. sectionName:section.name,
  315. unifiedSetting:1,
  316. ruleId:''
  317. };
  318. if(feeItem.isCal==1&&section.feeRuleId&&section.feeRuleId!=''){//勾选记取时并且有规则ID时才读取
  319. let feeRule = _.find(installFee.feeRule,{'ID':section.feeRuleId});
  320. if(feeRule){
  321. tem_r_i.ruleId = feeRule.ID;
  322. }
  323. }
  324. tem_r_i.ID = uuidV1();
  325. install_fee_list.push(tem_r_i);
  326. }
  327. }
  328. if(install_fee_list.length>0){
  329. await rationInstallationModel.insertMany(install_fee_list);
  330. }
  331. }
  332. return install_fee_list;
  333. }
  334. async function addRationTemplate(std,newRation) {
  335. let templateList = [];
  336. if(std.hasOwnProperty('rationTemplateList') && std.rationTemplateList.length > 0){
  337. for(let tem of std.rationTemplateList){
  338. let re_ration = await rationItemModel.findOne({rationRepId:std.rationRepId,ID:tem.rationID});
  339. if(re_ration){
  340. let template = {
  341. billID:"",
  342. fxID:"",
  343. quantity:"0",
  344. coe:"0"
  345. };
  346. template.code = re_ration.code;
  347. template.name = re_ration.name;
  348. template.type = tem.type;
  349. template.unit = re_ration.unit;
  350. template.billsLocation = tem.billsLocation;
  351. template.defaultLocation = tem.billsLocation;
  352. templateList.push(template)
  353. }
  354. }
  355. }
  356. if(templateList.length > 0){
  357. let ration_template = {};
  358. ration_template.ID = uuidV1();
  359. ration_template.projectID = newRation.projectID;
  360. ration_template.rationID = newRation.ID;
  361. ration_template.createLocation = 1; //默认模板子目分别放在措施项目下
  362. ration_template.templateList = templateList;
  363. await rationTemplateModel.create(ration_template);
  364. return ration_template;
  365. }
  366. return null;
  367. }
  368. async function addRationCoe(std,newRation,compilation) {
  369. let ration_coe_list = [];
  370. let seq = 0;
  371. if(std.hasOwnProperty('rationCoeList')&&std.rationCoeList.length>0){//添加标准库的工料机
  372. for(let sub of std.rationCoeList){
  373. let libCoe;
  374. if (std.type === 'std') {
  375. libCoe = await coeMolde.findOne({'libID':std.rationRepId,'ID':sub.ID,"$or": [{"isDeleted": null}, {"isDeleted": false}]});//std.rationRepId;
  376. } else {
  377. libCoe = await compleCoeModel.findOne({ID: sub.ID, $or: [{deleteInfo: null}, {'deleteInfo.deleted': false}]});
  378. }
  379. if(libCoe){
  380. let newCoe = {};
  381. newCoe.ID = uuidV1();
  382. newCoe.coeID = sub.ID;
  383. newCoe.seq = seq;
  384. newCoe.name = libCoe.name;
  385. newCoe.content = libCoe.content;
  386. newCoe.original_code = libCoe.original_code;
  387. newCoe.option_codes = libCoe.option_codes;
  388. newCoe.option_list = libCoe.option_list;
  389. newCoe.isAdjust=0;
  390. newCoe.coes = libCoe.coes;
  391. newCoe.rationID = newRation.ID;
  392. newCoe.projectID = newRation.projectID;
  393. seq++;
  394. ration_coe_list.push(newCoe);
  395. }
  396. }
  397. }
  398. let lastCoe = await getCustomerCoe(newRation.projectID,newRation.ID,seq,compilation);
  399. ration_coe_list.push(lastCoe);
  400. await ration_coe.insertMany(ration_coe_list);
  401. return ration_coe_list;
  402. }
  403. function getCustomerCoeData() {
  404. var coeList = [
  405. {amount:1, operator:'*', gljCode:null, coeType:'定额'},
  406. { amount:1, operator:'*', gljCode:null, coeType:'人工'},
  407. { amount:1, operator:'*', gljCode:null, coeType:'材料'},
  408. { amount:1, operator:'*', gljCode:null, coeType:'机械'},
  409. /* { amount:1, operator:'*', gljCode:null, coeType:'主材'},*/
  410. { amount:1, operator:'*', gljCode:null, coeType:'设备'}
  411. ];
  412. return coeList;
  413. };
  414. async function getCustomerCoe(projectID,rationID,seq,compilation){//取自定义乘系数,根据编办不同,内容可能不同
  415. //生成默认的自定义乘系数
  416. let lastCoe ={
  417. coeID:-1,
  418. name : '自定义系数',
  419. content:'人工×1,材料×1,机械×1,设备×1',//主材×1,
  420. isAdjust:1,
  421. seq:seq,
  422. rationID : rationID,
  423. projectID : projectID
  424. };
  425. lastCoe.ID = uuidV1();
  426. lastCoe.coes = getCustomerCoeData();
  427. try {
  428. //查看编办中有没有重写路径
  429. if(compilation.overWriteUrl && compilation.overWriteUrl!=""){
  430. let overWrite = require("../../.."+compilation.overWriteUrl);
  431. if(overWrite.getCusCoeContent) lastCoe.content = overWrite.getCusCoeContent();
  432. if(overWrite.getCustomerCoeData) lastCoe.coes = overWrite.getCustomerCoeData();
  433. }
  434. return lastCoe
  435. }catch (err){
  436. console.log("读取自定义系数重写文件失败");
  437. console.log(err.message);
  438. return lastCoe
  439. }
  440. }
  441. //对于多单价,多组成物消耗量的编办,通过这个方法获取单价、组成物消耗量的字段,
  442. function getExtendData(property,compilation) {
  443. return projectDao.getExtendData(property,compilation);
  444. }
  445. async function addRationGLJ(std,newRation,compilation,isMaterial,connect_key) {
  446. let newRationGLJList = [];
  447. let rationGLJShowList = [];
  448. let projectGLJList = [];
  449. let gljKeyMap = {};
  450. let maxRatioMap={};
  451. let unitPriceFileId = 0;
  452. let property = await projectDao.getProjectProperty(newRation.projectID);
  453. if(property){
  454. unitPriceFileId = property.unitPriceFile !== undefined ? property.unitPriceFile.id : 0;
  455. }
  456. let ext = getExtendData(property,compilation);
  457. let first = +new Date();
  458. if(std.hasOwnProperty('rationGljList') && std.rationGljList.length > 0){
  459. let stdGLJID =[];//标准工料机ID数组
  460. let cptGLJID=[];//补充工料机ID数组
  461. //let stdGLJID = _.map(std.rationGljList,'gljId');
  462. for(let tem_g of std.rationGljList){
  463. if(tem_g.type == 'complementary'){
  464. cptGLJID.push(tem_g.gljId);
  465. }else {
  466. stdGLJID.push(tem_g.gljId);
  467. }
  468. }
  469. let stdGLJList = stdGLJID.length > 0 ? await std_glj_lib_gljList_model.find({'ID':{'$in':stdGLJID}}).lean():[];//速度优化-------先一次性取出所有的工料机列表
  470. let stdGLJMap = _.indexBy(stdGLJList, 'ID');
  471. let cptGLJList = cptGLJID.length > 0 ? await complementary_glj_model.find({'userId':std.userId,'ID':{'$in':cptGLJID}}).lean():[];
  472. let cptGLJMap = _.indexBy(cptGLJList, 'ID');
  473. let stdGLJMapTime = +new Date();
  474. console.log("找到工料机映射表时间-------------------------------"+(stdGLJMapTime - first));
  475. if(isMaterial == true){//材料计算添加时要先检查
  476. for(let sub of std.rationGljList){
  477. let t_g = getStdGlj(sub,stdGLJMap,cptGLJMap,{},ext);
  478. if(t_g && connect_key == gljUtil.getIndex(t_g)) throw `本定额中包含工料机${t_g.code},与当前工料机编号相同,添加定额失败`;
  479. }
  480. }
  481. for(let sub of std.rationGljList){
  482. let newGLJ = {};
  483. let proportion = sub.proportion || 0;
  484. newGLJ.ID = uuidV1();
  485. newGLJ.projectID = newRation.projectID;
  486. newGLJ.GLJID = sub.gljId;
  487. newGLJ.rationID = newRation.ID;
  488. newGLJ.billsItemID = newRation.billsItemID;
  489. newGLJ.rationItemQuantity = sub.consumeAmt;
  490. newGLJ.quantity = sub.consumeAmt;
  491. newGLJ.glj_repository_id = std.rationRepId;
  492. newGLJ.rationProportion = proportion;
  493. newGLJ.adjustProportion = proportion;
  494. let std_glj = getStdGlj(sub,stdGLJMap,cptGLJMap,{},ext);
  495. if(std_glj){
  496. let tindex = getIndex(newGLJ);
  497. ration_glj_facade.setPropertyFromStd(newGLJ,std_glj);
  498. if(std_glj.component && std_glj.component.length > 0) maxRatioMap[tindex] = std_glj.component
  499. gljKeyMap[tindex] = newGLJ;
  500. /* let [info,projectGLJ] = await ration_glj_facade.getInfoFromProjectGLJ(newGLJ,unitPriceFileId,ext);
  501. newGLJ = ration_glj_facade.createNewRecord(info);
  502. newRationGLJList.push(newGLJ);
  503. rationGLJShowList.push(info);
  504. projectGLJList.push(projectGLJ); */
  505. }
  506. //let InfoFromProjectGLJ = +new Date();
  507. //console.log("找到项目工料机时间-------------------------------"+(InfoFromProjectGLJ - std_gljTime));
  508. }
  509. }
  510. let before = +new Date();
  511. console.log("总查询时间为-------------------------------"+(before-first));
  512. if(isMaterial == true) return [newRationGLJList,projectGLJList];//如果是材料计算的工料机,这里返回就可以了
  513. if(newRationGLJList.length>0){
  514. await ration_glj.insertMany(newRationGLJList);
  515. }
  516. let after = +new Date();
  517. console.log("实际插入时间为-------------------------------"+(after-before));
  518. console.log("总操作时间为-------------------------------"+(after-first));
  519. return [rationGLJShowList,projectGLJList];
  520. }
  521. function getStdGlj(sub,stdGLJMap,cptGLJMap,newGLJ,ext) {
  522. let std_glj = null;
  523. if(sub.type == 'complementary'){//有可能来自标准工料机库或补充工料机库
  524. std_glj = cptGLJMap[sub.gljId];
  525. newGLJ.from = 'cpt';
  526. }else {
  527. std_glj = stdGLJMap[sub.gljId];
  528. newGLJ.from = 'std';
  529. //多单价情况处理
  530. if(ext && ext.priceField && std_glj && std_glj.priceProperty){
  531. std_glj.basePrice = std_glj.priceProperty[ext.priceField];
  532. }
  533. }
  534. return std_glj;
  535. }
  536. async function deleRationSubRecode(projectID,rationID,cleanzmhs=false) {//删除挂在定额下的数据,如工程量明细,定额工料机等
  537. let delete_query={projectID: projectID, rationID: rationID};
  538. //删除工程量明细
  539. await deleteSubListByQuery(delete_query,cleanzmhs) ;
  540. }
  541. async function deleteSubListByQuery(delete_query,cleanzmhs=false) {
  542. if(cleanzmhs == false){//清空子目换算即cleanzmh==true时不需要清空工程量明细、模板关联子目、安装增加费
  543. await quantity_detail.deleteByQuery(delete_query) ;//删除工程量明细
  544. await rationInstallationModel.deleteMany(delete_query);//删除安装增加费
  545. await rationTemplateModel.deleteMany(delete_query);//删除模板关联子目
  546. }
  547. //to do稳定土也要删除
  548. await ration_coe.deleteMany(delete_query);//删除附注条件
  549. await ration_glj.deleteMany(delete_query);//删除定额工料机
  550. }
  551. async function updateCoeAdjust(data,compilation) {
  552. let replace = [],projectGLJList=[];
  553. await ration_coe.update({ID:data.ID},data.doc);
  554. //添加单个工料机的情况
  555. if (data.add.length > 0){
  556. let [tg,pl] = await ration_glj_facade.insertAddTypeGLJ(data.add,compilation);
  557. if(pl.length > 0) projectGLJList = projectGLJList.concat(pl);
  558. }
  559. if(data.delete.length > 0) await ration_glj_facade.deleteGLJ(data.delete);
  560. //替换工料机的情况
  561. if (data.replace.length > 0){
  562. for(let r of data.replace){
  563. let r_result = await ration_glj_facade.replaceGLJByData(r,compilation);
  564. replace.push(r_result.data) ;
  565. projectGLJList.push(r_result.projectGLJ);
  566. if(r_result.newRecodes.length > 0) data.add = data.add.concat(r_result.newRecodes);
  567. if(r_result.deleteList.length > 0) data.delete = data.delete.concat(r_result.deleteList);
  568. }
  569. }
  570. let cal_result = await glj_calculate_facade.calculateQuantity({projectID:data.projectID,rationID:data.rationID},null,true);
  571. let coe = {
  572. query:{ID:data.ID,projectID:data.projectID},
  573. doc:data.doc
  574. };
  575. let ration_glj ={
  576. quantityRefresh:true,
  577. glj_result:cal_result.glj_result
  578. };
  579. let ration = {
  580. ID:cal_result.rationID,
  581. adjustState:cal_result.adjustState,
  582. name:cal_result.rationName
  583. };
  584. return {coe:coe,ration_glj:ration_glj,ration:ration,add:data.add,delete:data.delete,replace:replace,projectGLJList:projectGLJList}
  585. }
  586. async function updateRation(std,defaultLibID,rationID,billsItemID,projectID,calQuantity,cleanzmh=false) {
  587. // insertNewRation
  588. let ration ={};
  589. ration.code = std.code;
  590. ration.name = std.name;
  591. ration.caption = std.caption;
  592. ration.unit = std.unit;
  593. if (std.type === 'std') {
  594. ration.libID = std.rationRepId;
  595. ration.stdID = std.ID;
  596. }
  597. ration.content = std.jobContent;
  598. ration.adjustState = '';
  599. ration.isFromDetail=0;
  600. ration.isSubcontract=false;
  601. ration.fees=[];
  602. if (std.chapter) {
  603. ration.comments = std.chapter.explanation;
  604. ration.ruleText = std.chapter.ruleText;
  605. }
  606. ration.from = std.type === 'complementary' ? 'cpt' : 'std';
  607. //定额前缀 none:0, complementary:1, borrow: 2
  608. ration.prefix = '';
  609. //借用优先级比补充高
  610. if(std.rationRepId !== parseInt(defaultLibID)){//借用
  611. ration.prefix = '借';
  612. }
  613. else if(std.rationRepId === defaultLibID && ration.from === 'cpt') {
  614. ration.prefix = '补';
  615. }
  616. ration.rationAssList =await createRationAss(std);//生成辅助定额
  617. if(cleanzmh==false){//如果是清空子目换算,即cleanzmh==true 保留定额工程量、工程量表达式、含量(分解系数)、取费专业(取费类别)
  618. if(std.feeType == undefined || std.feeType == null || std.feeType ==''){//定额取费专业为空的情况下,取项目属性中的定额取费专业ID
  619. ration.programID = await getProgramForProject(projectID);
  620. }else {
  621. ration.programID = std.feeType;
  622. }
  623. if( calQuantity){
  624. await CalculateQuantity(ration,billsItemID,projectID);
  625. }
  626. }
  627. let unsetObject = {
  628. "marketUnitFee":1,
  629. 'marketTotalFee':1,
  630. "maskName":1
  631. }
  632. let newRation = await ration_model.model.findOneAndUpdate({ID:rationID,projectID:projectID},{"$set":ration,"$unset":unsetObject},{new: true});//;
  633. return newRation;
  634. }
  635. async function setEmptyRation(projectID,rationID){
  636. let ration ={};
  637. ration.code = "";
  638. ration.name = "";
  639. ration.caption = "";
  640. ration.unit = "";
  641. ration.libID = null;
  642. ration.content = "";
  643. ration.adjustState = '';
  644. ration.isFromDetail=0;
  645. ration.isSubcontract=false;
  646. ration.fees=[];
  647. ration.comments = "";
  648. ration.ruleText = "";
  649. ration.quantity="";
  650. ration.contain="";
  651. ration.quantityEXP="";
  652. ration.from = 'std';
  653. //定额前缀 none:0, complementary:1, borrow: 2
  654. ration.prefix = '';
  655. ration.rationAssList = [];
  656. ration.marketUnitFee ="";
  657. ration.marketTotalFee ="";
  658. ration.maskName = "";
  659. ration.targetTotalFee ='';
  660. ration.targetUnitFee = "";
  661. ration.deleteInfo = null;
  662. ration.quantityCoe = {};
  663. ration.rationQuantityCoe="";
  664. ration.tenderQuantity = "";
  665. ration.programID = null;
  666. let newRation = await ration_model.model.findOneAndUpdate({ID:rationID,projectID:projectID},{"$set":ration},{new: true});//;
  667. return {ration:newRation,ration_gljs:[],ration_coes:[],ration_installs:[]};
  668. }
  669. async function createRationAss(std,isMaterial) {
  670. let rationAssList = [];//生成辅助定额
  671. if(std.hasOwnProperty('rationAssList')&&std.rationAssList.length>0){
  672. let assGroup = _.groupBy(std.rationAssList,'name');
  673. for(let key in assGroup){
  674. let assList = assGroup[key];
  675. let ass = assList[0];
  676. ass._doc.actualValue = ass.stdValue;
  677. ass._doc.isAdjust = 0;
  678. if(_.isString(ass._doc.assistCode)) ass._doc.assistCode = ass._doc.assistCode.replace("\n","");
  679. if(_.isString(ass._doc.thirdRationCode)) ass._doc.thirdRationCode = ass._doc.thirdRationCode.replace("\n","");
  680. if(assList.length > 1){
  681. ass._doc.groupList = JSON.parse(JSON.stringify(assList)) ;
  682. ass._doc.maxValue = assList[assList.length-1]._doc.maxValue;
  683. }
  684. if(isMaterial == true){//材料计算进来的,直接保存辅助定额的信息 //常规的定额以后可以考虑也这样做
  685. let t_assRation = await rationItemModel.findOne({rationRepId:std.rationRepId,code:ass.assistCode}).lean();
  686. if(t_assRation) ass._doc.assRation = t_assRation;
  687. }
  688. rationAssList.push(ass);
  689. }
  690. }
  691. return rationAssList;
  692. }
  693. async function CalculateQuantity (ration,billsItemID,projectID) {
  694. // calculate ration Quantity
  695. let project = await projectModel.findOne({ID:projectID});
  696. let decimalObject =await decimal_facade.getProjectDecimal(projectID,project);
  697. let quantity_decimal = (decimalObject&&decimalObject.ration&&decimalObject.ration.quantity)?decimalObject.ration.quantity:3;
  698. let pbill = await bill_model.model.findOne({projectID:projectID,ID:billsItemID});
  699. /* let t_unit = ration.unit?ration.unit.replace(/^\d+/,""):""; 2019-02-01 养护去掉清单与定额单位的这个判断
  700. if(t_unit!=pbill.unit){//如果定额工程量的单位去除前面的数字后不等于清单单位,定额工程量保持不变
  701. return ;
  702. }*/
  703. let billsQuantity = pbill.quantity ? pbill.quantity : 0;
  704. let bill_decimal = await decimal_facade.getBillsQuantityDecimal(projectID,pbill.unit,project);
  705. billsQuantity=scMathUtil.roundForObj(billsQuantity,bill_decimal);
  706. ration.quantityEXP="QDL";
  707. ration.quantity = scMathUtil.roundForObj(billsQuantity / FilterNumberFromUnit(ration.unit),quantity_decimal);//不管是否打勾都做转换
  708. ration.contain = scMathUtil.roundForObj(ration.quantity/billsQuantity,6);
  709. };
  710. async function getProgramForProject(projectID){
  711. let project = await projectModel.findOne({ID:projectID});
  712. return project.property.engineering;
  713. }
  714. function FilterNumberFromUnit (unit) {
  715. let reg = new RegExp('^[0-9]+');
  716. if (reg.test(unit)) {
  717. return parseInt(unit.match(reg)[0]);
  718. } else {
  719. return 1;
  720. }
  721. };
  722. getIndex(obj,tpops){
  723. let pops = tpops?tpops:['code','name','specs','unit','type'];
  724. let t_index = '';
  725. let k_arr=[];
  726. for(let p of pops){
  727. let tmpK = (obj[p]==undefined||obj[p]==null||obj[p]=='')?'null':obj[p];
  728. k_arr.push(tmpK);
  729. }
  730. t_index=k_arr.join("|-|");
  731. return t_index;
  732. }