ration_facade.js 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306
  1. /**
  2. * Created by zhang on 2018/2/9.
  3. */
  4. module.exports = {
  5. replaceRations: replaceRations,
  6. addNewRation:addNewRation,
  7. updateMaterialRation:updateMaterialRation,
  8. updateDivideRation:updateDivideRation,
  9. addMaterialRation:addMaterialRation,
  10. addMultiRation: addMultiRation,
  11. getSameSectionRations:getSameSectionRations,
  12. getExtendData:getExtendData,
  13. getDefaultProgramID:getDefaultProgramID,
  14. deleteSubListByQuery:deleteSubListByQuery,
  15. updateCoeAdjust:updateCoeAdjust,
  16. getUnitPriceData:getUnitPriceData,
  17. setIDfromCounter:setIDfromCounter,
  18. getNewProjectGLJFromMissMixratio:getNewProjectGLJFromMissMixratio
  19. };
  20. let mongoose = require('mongoose');
  21. import SearchDao from '../../complementary_ration_lib/models/searchModel';
  22. import GLJListModel from "../../glj/models/glj_list_model";
  23. import e from 'express';
  24. const scMathUtil = require('../../../public/scMathUtil').getUtil();
  25. let gljUtil = require('../../../public/gljUtil');
  26. let ration_glj_facade = require("../../ration_glj/facade/ration_glj_facade");
  27. let glj_calculate_facade = require("../../ration_glj/facade/glj_calculate_facade");
  28. let quantity_detail = require("../facade/quantity_detail_facade");
  29. let ration_glj = mongoose.model('ration_glj');
  30. let ration_coe = mongoose.model('ration_coe');
  31. let ration_model = require('../models/ration');
  32. let bill_model = require('../models/bills');
  33. let decimal_facade = require('./decimal_facade');
  34. let divide_facade = require('./divide_facade');
  35. let installationFeeModel = mongoose.model("installation_fee");
  36. let rationInstallationModel = mongoose.model('ration_installation');
  37. let rationTemplateModel = mongoose.model('ration_template');
  38. const uuidV1 = require('uuid/v1');
  39. let std_glj_lib_gljList_model = mongoose.model('std_glj_lib_gljList');
  40. let complementary_glj_model = mongoose.model('complementary_glj_lib');
  41. let rationItemModel = mongoose.model("std_ration_lib_ration_items");
  42. let complementaryRationModel = mongoose.model('complementary_ration_items');
  43. let freightCalcModel = mongoose.model('freight_calc');
  44. let originaltCalcModel = mongoose.model('original_calc');
  45. let coeMolde = mongoose.model('std_ration_lib_coe_list');
  46. let compleCoeModel = mongoose.model('complementary_ration_coe_list');
  47. let projectGLJModel = mongoose.model("glj_list");
  48. let mixRatioModel = mongoose.model("mix_ratio");
  49. let complementaryGljLibModel = mongoose.model('complementary_glj_lib');
  50. let counterModel = mongoose.model('counter');
  51. let _= require('lodash');
  52. const projectDao = require('../../pm/models/project_model').project;
  53. let projectModel = mongoose.model('projects');
  54. let unitPriceModel = mongoose.model('unit_price');
  55. let unitPriceFileModel = mongoose.model('unit_price_file');
  56. let vvTaxModel = mongoose.model("std_vehicleVesselTax_items");
  57. let divideModel = mongoose.model("divide_setting");
  58. const fs = require('fs');
  59. async function addNewRation(data,compilation) {
  60. let query = data.itemQuery;
  61. let stdRation = null;
  62. let startTime = +new Date();
  63. if(query){
  64. let searchDao = new SearchDao();
  65. stdRation = await searchDao.getRationItem(query.userID, compilation._id, [query.rationRepId],query.code, query.ID);
  66. //data.newData.code = query.code;
  67. }
  68. let stdRationTime = +new Date();
  69. console.log("取std定额时间-------------------------------"+(stdRationTime - startTime));
  70. if(data.brUpdate.length>0){
  71. await updateSerialNo(data.brUpdate);
  72. }
  73. let newRation =await insertNewRation(data.newData,data.defaultLibID,stdRation,data.calQuantity);
  74. let addRationGLJTime = +new Date();
  75. console.log("插入新定额时间-------------------------------"+(addRationGLJTime - stdRationTime));
  76. if(stdRation){
  77. return await addRationSubList(stdRation,newRation,data.needInstall,compilation);
  78. }else {
  79. return {ration:newRation};
  80. }
  81. }
  82. async function updateMaterialRation(data,compilation){
  83. let result = {};
  84. switch (data.actionType){
  85. case "add":
  86. result = await addMaterialRation(data,compilation);
  87. break;
  88. case "delete":
  89. result = await deleteMaterialRation(data);
  90. case "update":
  91. result = await modifyMaterialRation(data,compilation);
  92. }
  93. return result;
  94. }
  95. async function updateDivideRation(data,compilation){
  96. let result = {};
  97. switch (data.type){
  98. case "add":
  99. result = await addDivideRation(data,compilation);
  100. break;
  101. case "update":
  102. result = await modifyDivideRation(data,compilation);
  103. break;
  104. }
  105. return result;
  106. }
  107. async function deleteMaterialRation(data) {
  108. let model = data.type == "freight"?freightCalcModel:originaltCalcModel;
  109. await model.update(
  110. {ID:data.parentID},
  111. { $pull: { rations: { ID: data.rationID},ration_gljs:{rationID:data.rationID} } },
  112. { multi: true }
  113. );
  114. return data;
  115. }
  116. async function modifyMaterialRation(data,compilation) {
  117. let model = data.type == "freight"?freightCalcModel:originaltCalcModel;
  118. if(data.field == "code"){
  119. let [newRation,ration_gljs,projectGLJList] = await getNewMaterialRationDatas(data,compilation);
  120. let quantity = data.rations[data.row].quantity;
  121. newRation.quantity = quantity;
  122. data.rations[data.row] = newRation;
  123. _.remove(data.ration_gljs,{rationID:data.rationID});
  124. data.ration_gljs = data.ration_gljs.concat(ration_gljs);
  125. await model.update({'ID':data.parentID},{rations:data.rations,ration_gljs:data.ration_gljs});
  126. return {ration:newRation,ration_gljs:ration_gljs,projectGLJList:projectGLJList}
  127. }else {
  128. let doc = {},pre = "rations.$.";
  129. let field = pre+data.field;
  130. doc[field] = data.value;
  131. if(data.ext){
  132. for(let key in data.ext){
  133. doc[pre+key] = data.ext[key];
  134. }
  135. }
  136. if(data.ration_gljs){
  137. let tasks = [];
  138. for(let g of data.ration_gljs){
  139. tasks.push({updateOne: {filter: {'ID':data.parentID,'ration_gljs.ID':g.ID}, update: {"ration_gljs.$.quantity":g.quantity}}})
  140. }
  141. await model.bulkWrite(tasks);
  142. }
  143. return await model.update({'ID':data.parentID,'rations.ID':data.rationID},doc);
  144. }
  145. }
  146. async function addMaterialRation(data,compilation) {
  147. let [newRation,ration_gljs,projectGLJList] = await getNewMaterialRationDatas(data,compilation);
  148. let model = data.type == "freight"?freightCalcModel:originaltCalcModel;
  149. await model.update({ID:data.parentID},{$push:{rations:newRation,ration_gljs:{$each:ration_gljs}}});
  150. return{ration:newRation,ration_gljs:ration_gljs,projectGLJList:projectGLJList};
  151. }
  152. async function addDivideRation(data,compilation){
  153. let [newRation,ration_gljs,projectGLJList,ration_coes] = await getNewMaterialRationDatas(data,compilation,true);
  154. delete newRation.projectID;
  155. newRation.type=1;
  156. newRation.ParentID = data.ParentID;
  157. newRation.itemType = "定额";
  158. newRation.programID = data.programID;
  159. newRation.seq = data.seq;
  160. await divideModel.update({ID:data.divideID},{$push:{divideList:newRation,ration_gljs:{$each:ration_gljs},ration_coes:{$each:ration_coes}}});
  161. if(data.divideDatas.length > 0)await divide_facade.updateItem({ID:data.divideID,updateDatas:data.divideDatas});
  162. return{ration:newRation,ration_gljs:ration_gljs,projectGLJList:projectGLJList,ration_coes};
  163. }
  164. async function modifyDivideRation(data,compilation){//目前只有替换分摊的定额走这个逻辑
  165. let [newRation,ration_gljs,projectGLJList,ration_coes] = await getNewMaterialRationDatas(data,compilation,true);
  166. newRation.quantity = data.oldData.quantity;
  167. newRation.type=1;
  168. newRation.itemType = "定额";
  169. newRation.programID = data.oldData.programID;
  170. newRation.seq = data.oldData.seq;
  171. newRation.ParentID = data.oldData.ParentID;
  172. await divideModel.update({ID:data.ID},{$push:{divideList:newRation,ration_gljs:{$each:ration_gljs},ration_coes:{$each:ration_coes}}});
  173. await divideModel.update(
  174. {ID:data.ID},
  175. {
  176. $pull: {divideList:{ID:data.rationID},ration_gljs:{rationID:data.rationID},ration_coes:{rationID:data.rationID}}
  177. },
  178. { multi: true })
  179. return {ration:newRation,ration_gljs:ration_gljs,projectGLJList:projectGLJList,ration_coes}
  180. }
  181. async function getNewMaterialRationDatas(data,compilation,withCoe = false){
  182. let searchDao = new SearchDao();
  183. let stdRation = await searchDao.getRationItem(data.userID, compilation._id, data.rationRepIds,data.code);
  184. if(!stdRation) throw "找不到指定的定额!";//new Error("找不到指定的定额!");
  185. let newRation = await createNewMaterialRation(stdRation,data.quantityDecimal,data.projectID);
  186. let [ration_gljs,projectGLJList] = await addRationGLJ(stdRation,newRation,compilation,true,data.connect_key);
  187. let result = [newRation,ration_gljs,projectGLJList]
  188. if(withCoe == true){
  189. let ration_coes = await addRationCoe(stdRation,newRation,compilation,true);
  190. result.push(ration_coes);
  191. }
  192. return result;
  193. }
  194. async function createNewMaterialRation(std,quantityDecimal,projectID){
  195. let newData = {};
  196. newData.ID = uuidV1();
  197. newData.projectID = projectID;
  198. newData.code = std.code;
  199. newData.name = std.name;
  200. newData.caption = std.caption;
  201. newData.unit = std.unit;
  202. newData.libID = std.rationRepId;
  203. newData.stdID = std.ID;
  204. newData.quantity=scMathUtil.roundForObj(1 / FilterNumberFromUnit(std.unit),quantityDecimal);
  205. newData.from = std.type === 'complementary' ? 'cpt' : 'std';
  206. newData.rationAssList =await createRationAss(std,true);
  207. return newData;
  208. }
  209. async function addMultiRation(datas,compilation) {
  210. let rst = [];
  211. for(let data of datas){
  212. let r = await addNewRation(data,compilation);
  213. rst.push(r);
  214. }
  215. return rst;
  216. }
  217. async function getSameSectionRations(data,userId,compilationId){
  218. //let userId
  219. //要先根据定额获取所属章节的ID
  220. let from = data.from; //定额类型,是标准的还是用户定义的
  221. let code = data.code;
  222. let libID = data.libID;
  223. let sectionId,rations=[];
  224. if(from == 'std'){
  225. let ration = await rationItemModel.findOne({rationRepId:libID,code:code},['sectionId']);
  226. sectionId = ration? ration.sectionId:null;
  227. }else {
  228. let ration = await complementaryRationModel.findOne({userId:userId,compilationId: compilationId,code:code},['sectionId']);
  229. sectionId = ration?ration.sectionId:null;
  230. }
  231. if(sectionId){
  232. if (from == 'std') {
  233. rations = await rationItemModel.find({sectionId: sectionId});
  234. } else {
  235. rations = await complementaryRationModel.find({userId: userId, sectionId: sectionId});
  236. }
  237. rations = _.sortBy(rations,'code');
  238. }
  239. return rations
  240. }
  241. async function updateSerialNo(serialNoUpdate){
  242. let tasks=[];
  243. for(let data of serialNoUpdate){
  244. let task={
  245. updateOne:{
  246. filter:{
  247. ID:data.ID,
  248. projectID:data.projectID
  249. },
  250. update :{
  251. serialNo:data.serialNo
  252. }
  253. }
  254. };
  255. tasks.push(task);
  256. }
  257. await ration_model.model.bulkWrite(tasks);
  258. }
  259. async function insertNewRation(newData,defaultLibID,std,calQuantity) {//插入新的定额
  260. let startTime = +new Date();
  261. if(std){
  262. newData.code = std.code;
  263. newData.name = std.name;
  264. newData.caption = std.caption;
  265. newData.unit = std.unit;
  266. newData.libID = std.rationRepId;
  267. newData.stdID = std.ID;
  268. newData.content = std.jobContent;
  269. newData.annotation = std.annotation;
  270. if (std.chapter) {
  271. newData.comments = std.chapter.explanation;
  272. newData.ruleText = std.chapter.ruleText;
  273. }
  274. newData.prefix = '';
  275. newData.from = std.type === 'complementary' ? 'cpt' : 'std';
  276. if(defaultLibID !== std.rationRepId){//借
  277. newData.prefix = '借';
  278. }
  279. else if(std.rationRepId === defaultLibID && newData.from === 'cpt') {
  280. newData.prefix = '补';
  281. }
  282. if(std.feeType == undefined || std.feeType == null || std.feeType ==''){//定额取费专业为空的情况下,取项目属性中的定额取费专业ID
  283. newData.programID = await getProgramForProject(newData.projectID);
  284. }else {
  285. newData.programID = std.feeType;
  286. }
  287. newData.rationAssList =await createRationAss(std);
  288. // calculate ration Quantity
  289. }
  290. if(calQuantity){
  291. await CalculateQuantity(newData,newData.billsItemID,newData.projectID);
  292. }
  293. let addRationGLJTime = +new Date();
  294. console.log("计算消耗量时间-------------------------------"+(addRationGLJTime - startTime));
  295. await ration_model.model.insertMany([newData]);
  296. return newData;
  297. /*ration_model.model.create(newData);
  298. return newData;*/
  299. }
  300. async function replaceRations(userID,data,compilation) {
  301. let searchDao = new SearchDao();
  302. let recodes = [];
  303. for(let recode of data.nodeInfo){
  304. let stdRation = await searchDao.getRationItem(userID,compilation._id,data.libIDs,recode.newCode, null);
  305. let newRecode = await replaceRation(recode,stdRation,data.defaultLibID,data.projectID,data.calQuantity,compilation,data.cleanzmhs);
  306. if(newRecode){
  307. recodes.push(newRecode);
  308. }else {
  309. break;
  310. }
  311. }
  312. return recodes;
  313. }
  314. async function getDefaultProgramID(data) {
  315. let searchDao = new SearchDao();
  316. let programID;
  317. let std = await searchDao.getRationItem(data.userID,data.compilationId,[data.libID],data.code, null);
  318. if(std == null||std ==undefined || std.feeType == undefined || std.feeType == null || std.feeType ==''){//定额取费专业为空的情况下,取项目属性中的定额取费专业ID
  319. programID = await getProgramForProject(data.projectID);
  320. }else {
  321. programID = std.feeType;
  322. }
  323. return programID;
  324. }
  325. async function replaceRation(nodeInfo,stdRation,defaultLibID,projectID,calQuantity,compilation,cleanzmhs) {
  326. if(nodeInfo.newCode == null||nodeInfo.newCode ==""){//说明是删除编号,则要变成一条空定额
  327. await deleRationSubRecode(projectID,nodeInfo.ID);//删除定额下挂的各种数据,如定额工料机等
  328. return await setEmptyRation(projectID,nodeInfo.ID);
  329. }else if(stdRation){
  330. await deleRationSubRecode(projectID,nodeInfo.ID,cleanzmhs);//删除定额下挂的各种数据,如定额工料机等
  331. let newRation = await updateRation(stdRation,defaultLibID,nodeInfo.ID,nodeInfo.billsItemID,projectID,calQuantity,cleanzmhs);//生成并插入新的定额
  332. return await addRationSubList(stdRation,newRation,nodeInfo.needInstall,compilation,cleanzmhs);
  333. }else {
  334. return null;
  335. }
  336. }
  337. async function addRationSubList(stdRation,newRation,needInstall,compilation,cleanzmhs=false) {
  338. let startTime = +new Date();
  339. let [ration_gljs,projectGLJList] = await addRationGLJ(stdRation,newRation,compilation);
  340. let addRationGLJTime = +new Date();
  341. console.log("添加定额工料机时间-----"+(addRationGLJTime - startTime));
  342. let ration_coes = await addRationCoe(stdRation,newRation,compilation);
  343. let addRationCoeTime = +new Date();
  344. console.log("添加定额coe时间-----"+(addRationCoeTime - addRationGLJTime));
  345. let ration_installations = [];
  346. let ration_template = [];
  347. if(cleanzmhs == false){//清除子目换算即cleanzmh==true时 模板子目、安装增加费不用恢复成标准的
  348. if(needInstall && stdRation.type == 'std'){//只有标准的定额才有安装增加费,补充的定额没有安装增加费
  349. ration_installations = await addRationInstallFee(stdRation,newRation);
  350. }
  351. let addRationInstallFeeTime = +new Date();
  352. console.log("添加定额install时间-----"+(addRationInstallFeeTime - addRationCoeTime));
  353. //添加定额模板子目
  354. ration_template = await addRationTemplate(stdRation,newRation);
  355. }
  356. return {ration:newRation,ration_gljs:ration_gljs,ration_coes:ration_coes,ration_installations:ration_installations,ration_templates:ration_template?[ration_template]:[],projectGLJList:projectGLJList};
  357. }
  358. async function addRationInstallFee(std,newRation) {
  359. let install_fee_list = [];
  360. if(std.hasOwnProperty('rationInstList') && std.rationInstList.length > 0){
  361. let installFee = await installationFeeModel.findOne({'projectID': newRation.projectID});
  362. if(!installFee) return;//如果没有找到项目对应的安装增加费,则不添加
  363. for(let ri of std.rationInstList){
  364. let feeItem = _.find(installFee.installFeeItem,{'ID':ri.feeItemId});
  365. let section = _.find(installFee.installSection,{'ID':ri.sectionId});
  366. if(feeItem&&section){
  367. let tem_r_i = {
  368. libID:installFee.libID,
  369. projectID:newRation.projectID,
  370. rationID:newRation.ID,
  371. feeItemId:feeItem.ID,
  372. sectionId:section.ID,
  373. itemName:feeItem.feeItem,
  374. feeType:feeItem.feeType,
  375. sectionName:section.name,
  376. unifiedSetting:1,
  377. ruleId:''
  378. };
  379. if(feeItem.isCal==1&&section.feeRuleId&&section.feeRuleId!=''){//勾选记取时并且有规则ID时才读取
  380. let feeRule = _.find(installFee.feeRule,{'ID':section.feeRuleId});
  381. if(feeRule){
  382. tem_r_i.ruleId = feeRule.ID;
  383. }
  384. }
  385. tem_r_i.ID = uuidV1();
  386. install_fee_list.push(tem_r_i);
  387. }
  388. }
  389. if(install_fee_list.length>0){
  390. await rationInstallationModel.insertMany(install_fee_list);
  391. }
  392. }
  393. return install_fee_list;
  394. }
  395. async function addRationTemplate(std,newRation) {
  396. let templateList = [];
  397. if(std.hasOwnProperty('rationTemplateList') && std.rationTemplateList.length > 0){
  398. for(let tem of std.rationTemplateList){
  399. let re_ration = await rationItemModel.findOne({rationRepId:std.rationRepId,ID:tem.rationID});
  400. if(re_ration){
  401. let template = {
  402. billID:"",
  403. fxID:"",
  404. quantity:"0",
  405. coe:"0"
  406. };
  407. template.code = re_ration.code;
  408. template.name = re_ration.name;
  409. template.type = tem.type;
  410. template.unit = re_ration.unit;
  411. template.billsLocation = tem.billsLocation;
  412. template.defaultLocation = tem.billsLocation;
  413. templateList.push(template)
  414. }
  415. }
  416. }
  417. if(templateList.length > 0){
  418. let ration_template = {};
  419. ration_template.ID = uuidV1();
  420. ration_template.projectID = newRation.projectID;
  421. ration_template.rationID = newRation.ID;
  422. ration_template.createLocation = 1; //默认模板子目分别放在措施项目下
  423. ration_template.templateList = templateList;
  424. await rationTemplateModel.create(ration_template);
  425. return ration_template;
  426. }
  427. return null;
  428. }
  429. async function addRationCoe(std,newRation,compilation,notInsert = false) {
  430. let ration_coe_list = [];
  431. let seq = 0;
  432. if(std.hasOwnProperty('rationCoeList')&&std.rationCoeList.length>0){//添加标准库的工料机
  433. for(let sub of std.rationCoeList){
  434. let libCoe;
  435. if (std.type === 'std') {
  436. libCoe = await coeMolde.findOne({'libID':std.rationRepId,'ID':sub.ID,"$or": [{"isDeleted": null}, {"isDeleted": false}]});//std.rationRepId;
  437. } else {
  438. libCoe = await compleCoeModel.findOne({ID: sub.ID, $or: [{deleteInfo: null}, {'deleteInfo.deleted': false}]});
  439. }
  440. if(libCoe){
  441. let newCoe = {};
  442. newCoe.ID = uuidV1();
  443. newCoe.coeID = sub.ID;
  444. newCoe.seq = seq;
  445. newCoe.name = libCoe.name;
  446. newCoe.content = libCoe.content;
  447. newCoe.original_code = libCoe.original_code;
  448. newCoe.option_codes = libCoe.option_codes;
  449. newCoe.option_list = libCoe.option_list;
  450. newCoe.isAdjust=0;
  451. newCoe.coes = libCoe.coes;
  452. newCoe.rationID = newRation.ID;
  453. newCoe.projectID = newRation.projectID;
  454. seq++;
  455. ration_coe_list.push(newCoe);
  456. }
  457. }
  458. }
  459. let lastCoe = await getCustomerCoe(newRation.projectID,newRation.ID,seq,compilation);
  460. ration_coe_list.push(lastCoe);
  461. if(notInsert!=true) await ration_coe.insertMany(ration_coe_list);//分摊下的时候不保存在这里
  462. return ration_coe_list;
  463. }
  464. function getCustomerCoeData() {
  465. var coeList = [
  466. {amount:1, operator:'*', gljCode:null, coeType:'定额'},
  467. { amount:1, operator:'*', gljCode:null, coeType:'人工'},
  468. { amount:1, operator:'*', gljCode:null, coeType:'材料'},
  469. { amount:1, operator:'*', gljCode:null, coeType:'机械'},
  470. /* { amount:1, operator:'*', gljCode:null, coeType:'主材'},*/
  471. { amount:1, operator:'*', gljCode:null, coeType:'设备'}
  472. ];
  473. return coeList;
  474. };
  475. async function getCustomerCoe(projectID,rationID,seq,compilation){//取自定义乘系数,根据编办不同,内容可能不同
  476. //生成默认的自定义乘系数
  477. let lastCoe ={
  478. coeID:-1,
  479. name : '自定义系数',
  480. content:'人工×1,材料×1,机械×1,设备×1',//主材×1,
  481. isAdjust:1,
  482. seq:seq,
  483. rationID : rationID,
  484. projectID : projectID
  485. };
  486. lastCoe.ID = uuidV1();
  487. lastCoe.coes = getCustomerCoeData();
  488. try {
  489. //查看编办中有没有重写路径 -- 养护中暂时没用到
  490. /* if(compilation.overWriteUrl && compilation.overWriteUrl!=""){
  491. let overWrite = require("../../.."+compilation.overWriteUrl);
  492. if(overWrite.getCusCoeContent) lastCoe.content = overWrite.getCusCoeContent();
  493. if(overWrite.getCustomerCoeData) lastCoe.coes = overWrite.getCustomerCoeData();
  494. } */
  495. return lastCoe
  496. }catch (err){
  497. console.log("读取自定义系数重写文件失败");
  498. console.log(err.message);
  499. return lastCoe
  500. }
  501. }
  502. //对于多单价,多组成物消耗量的编办,通过这个方法获取单价、组成物消耗量的字段,
  503. function getExtendData(property,compilation) {
  504. return projectDao.getExtendData(property,compilation);
  505. }
  506. async function addRationGLJ(std,newRation,compilation,isMaterial,connect_key) {
  507. let newRationGLJList = [];
  508. let rationGLJShowList = [];
  509. let projectGLJList = [];
  510. let gljKeyMap = {};
  511. let mixRatioMap={};
  512. let gljCodes=[];
  513. let unitPriceFileId = 0;
  514. let property = await projectDao.getProjectProperty(newRation.projectID);
  515. if(property){
  516. unitPriceFileId = property.unitPriceFile !== undefined ? property.unitPriceFile.id : 0;
  517. }
  518. let ext = getExtendData(property,compilation);
  519. let first = +new Date();
  520. if(std.hasOwnProperty('rationGljList') && std.rationGljList.length > 0){
  521. let stdGLJID =[];//标准工料机ID数组
  522. let cptGLJID=[];//补充工料机ID数组
  523. //let stdGLJID = _.map(std.rationGljList,'gljId');
  524. for(let tem_g of std.rationGljList){
  525. if(tem_g.type == 'complementary'){
  526. cptGLJID.push(tem_g.gljId);
  527. }else {
  528. stdGLJID.push(tem_g.gljId);
  529. }
  530. }
  531. let stdGLJList = stdGLJID.length > 0 ? await std_glj_lib_gljList_model.find({'ID':{'$in':stdGLJID}}).lean():[];//速度优化-------先一次性取出所有的工料机列表
  532. let stdGLJMap = _.indexBy(stdGLJList, 'ID');
  533. let cptGLJList = cptGLJID.length > 0 ? await complementary_glj_model.find({'userId':std.userId,'ID':{'$in':cptGLJID}}).lean():[];
  534. let cptGLJMap = _.indexBy(cptGLJList, 'ID');
  535. let stdGLJMapTime = +new Date();
  536. console.log("找到工料机映射表时间-------------------------------"+(stdGLJMapTime - first));
  537. if(isMaterial == true){//材料计算添加时要先检查
  538. for(let sub of std.rationGljList){
  539. let t_g = getStdGlj(sub,stdGLJMap,cptGLJMap,{},ext);
  540. if(t_g && connect_key == gljUtil.getIndex(t_g)) throw `本定额中包含工料机${t_g.code},与当前工料机编号相同,添加定额失败`;
  541. }
  542. }
  543. for(let sub of std.rationGljList){
  544. let newGLJ = {};
  545. let proportion = sub.proportion || 0;
  546. newGLJ.ID = uuidV1();
  547. newGLJ.projectID = newRation.projectID;
  548. newGLJ.GLJID = sub.gljId;
  549. newGLJ.rationID = newRation.ID;
  550. newGLJ.billsItemID = newRation.billsItemID;
  551. newGLJ.rationItemQuantity = sub.consumeAmt;
  552. newGLJ.quantity = sub.consumeAmt;
  553. newGLJ.glj_repository_id = std.rationRepId;
  554. newGLJ.rationProportion = proportion;
  555. newGLJ.adjustProportion = proportion;
  556. let std_glj = getStdGlj(sub,stdGLJMap,cptGLJMap,{},ext);
  557. if(std_glj){
  558. ration_glj_facade.setPropertyFromStd(newGLJ,std_glj);
  559. let tindex = getIndex(newGLJ);
  560. if(std_glj.component && std_glj.component.length > 0) mixRatioMap[tindex] = std_glj.component
  561. let tdata = ration_glj_facade.getGLJSearchInfo(newGLJ);
  562. gljKeyMap[tindex] = tdata;
  563. gljCodes.push(tdata.code);
  564. newRationGLJList.push(newGLJ);
  565. }
  566. }
  567. [newRationGLJList, projectGLJList] = await getProjectGLJinfo(newRation.projectID,newRationGLJList,gljKeyMap,gljCodes,mixRatioMap,unitPriceFileId,ext);
  568. let InfoFromProjectGLJ = +new Date();
  569. console.log("找到项目工料机时间-------------------------------"+(InfoFromProjectGLJ - stdGLJMapTime));
  570. }
  571. if(isMaterial == true) return [newRationGLJList,projectGLJList];//如果是材料计算的工料机,这里返回就可以了
  572. if(newRationGLJList.length>0){
  573. await ration_glj.insertMany(newRationGLJList);
  574. }
  575. let after = +new Date();
  576. console.log("总操作时间为-------------------------------"+(after-first));
  577. return [newRationGLJList,projectGLJList];
  578. }
  579. async function getProjectGLJinfo(projectID,t_newRationGLJList,gljKeyMap,gljCodes,mixRatioMap,unitPriceFileId,ext){//批量插入或查找项目工料机信息
  580. //先根据工料机编号在项目工料机中查找工料机是否存在
  581. let projectGLJMap={};
  582. let projectGLJList = [];
  583. let newProjectGLJList=[];//工料机ID要重新去取
  584. let connectKeyList = [];
  585. let CCSMap = {keyMap:{},codes:[]};//需要添加车船税的机械台班
  586. let newRationGLJList=[];
  587. let gljListModel = new GLJListModel();
  588. let t_projectGLJList = await projectGLJModel.find({'project_id':projectID,'code':{'$in':gljCodes}}).lean();
  589. for(let pg of t_projectGLJList){
  590. let pindex = getIndex(pg);
  591. projectGLJMap[pindex] = pg;
  592. }
  593. for(let key in gljKeyMap){
  594. if(!projectGLJMap[key]){//如果项目工料机不存在,则添加
  595. newProjectGLJList.push(gljKeyMap[key]);
  596. projectGLJMap[key] = gljKeyMap[key];
  597. if(gljKeyMap[key].type == 301){//如果是机械台班,需看看有没有车船税
  598. CCSMap.keyMap[key] = true;
  599. CCSMap.codes.push(gljKeyMap[key].code);
  600. }
  601. }
  602. //查看组成物
  603. if(gljListModel.ownCompositionTypes.indexOf(gljKeyMap[key].type)!=-1){//有组成物的类型
  604. connectKeyList.push(key);
  605. }
  606. }
  607. let [existMixRatioMap,mixRatioInsertData,missCodeList] = await getMixRatioInfo(projectID,projectGLJMap,newProjectGLJList,mixRatioMap,connectKeyList,unitPriceFileId,CCSMap,ext);
  608. if(missCodeList.length > 0) gljCodes = gljCodes.concat(missCodeList);
  609. //处理车般税相关,车船税是添加项目时,项目工料机,和单价文件里自动添加的 --- todo
  610. let [unitPriceMap,newUnitPriceList] = await getUnitPriceData(newProjectGLJList,gljCodes,unitPriceFileId);
  611. if(mixRatioInsertData.length > 0) await mixRatioModel.insertMany(mixRatioInsertData);
  612. //插入项目工料机
  613. if(newProjectGLJList.length > 0){
  614. await setIDfromCounter("glj_list",newProjectGLJList);
  615. await projectGLJModel.insertMany(newProjectGLJList);
  616. }
  617. //组装数据
  618. for(let ration_glj of t_newRationGLJList){
  619. let rkey = getIndex(ration_glj);
  620. let pglj = projectGLJMap[rkey];
  621. let subList = [];
  622. setUnitPrice(pglj,unitPriceMap);
  623. if(existMixRatioMap[rkey]){//如果有组成物
  624. for(let m of existMixRatioMap[rkey]){
  625. let mpglj = projectGLJMap[getIndex(m)]
  626. if(mpglj){
  627. let cglj = _.clone(mpglj);
  628. setUnitPrice(cglj,unitPriceMap);
  629. cglj.ratio_data = m;
  630. subList.push(cglj);
  631. }else{
  632. throw `组成物${m.name}对应的项目工料机没有找到`;
  633. }
  634. }
  635. pglj.subList =subList;
  636. }
  637. ration_glj.projectGLJID = pglj.id;
  638. newRationGLJList.push(ration_glj_facade.createNewRecord(ration_glj));
  639. projectGLJList.push(pglj);
  640. }
  641. return [newRationGLJList, projectGLJList];
  642. function setUnitPrice(p,unitPriceMap){
  643. p.unit_price = unitPriceMap[getIndex(p)];
  644. }
  645. }
  646. //找到并返回单价文件信息,如果没有自动插入
  647. async function getUnitPriceData(newProjectGLJList,gljCodes,unitPriceFileId){
  648. let unitPriceMap = {};
  649. let newUnitPriceList = [];
  650. let unitPriceList = await unitPriceModel.find({unit_price_file_id: unitPriceFileId,'code':{'$in':gljCodes}}).lean();
  651. for(let u of unitPriceList){
  652. unitPriceMap[getIndex(u)]=u;
  653. }
  654. for(let np of newProjectGLJList){
  655. let pkey = getIndex(np);
  656. if(unitPriceMap[pkey]) continue;
  657. let insertData = {
  658. code: np.code,
  659. base_price: np.base_price,
  660. market_price: np.market_price,
  661. unit_price_file_id: unitPriceFileId,
  662. name: np.name,
  663. specs:np.specs?np.specs:'',
  664. original_code:np.original_code,
  665. unit:np.unit?np.unit:'',
  666. type: np.type,
  667. short_name: np.shortName !== undefined ? np.shortName : '',
  668. glj_id: np.glj_id,
  669. is_add:0,
  670. grossWeightCoe:np.grossWeightCoe,
  671. purchaseStorageRate:np.purchaseStorageRate,
  672. offSiteTransportLossRate:np.offSiteTransportLossRate,
  673. handlingLossRate:np.handlingLossRate
  674. };
  675. if(np.from=='cpt') insertData.is_add=1;//如果是来自补充工料机,则都添加新增标记
  676. if(insertData.code != insertData.original_code) insertData.is_add=1;//添加的时候如果是复制整块来的,可能在源项目中是新增的工料机,这里也要添上(暂时可能还用不到)
  677. newUnitPriceList.push(insertData);
  678. unitPriceMap[pkey] = insertData;
  679. }
  680. if(newUnitPriceList.length > 0){
  681. await setIDfromCounter("unit_price",newUnitPriceList);
  682. await unitPriceModel.insertMany(newUnitPriceList);
  683. }
  684. return [unitPriceMap,newUnitPriceList];
  685. }
  686. async function getMixRatioInfo(projectID,projectGLJMap,newProjectGLJList,mixRatioMap,connectKeyList,unitPriceFileId,CCSMap,ext){//取组成物信息,得到缺少的组成物情况
  687. let missCodeList = []; //所有组成物信息的编码,用来统一查询对应的项目工料机是否存在
  688. let existMixRatioMap ={};
  689. let codeMap={};//用来去重
  690. let mixRatioInsertData = [];
  691. // 1. 先检查现在的组成物表中,是否有相关信息 - 生成映射记录
  692. if(connectKeyList.length > 0){//有组成物的话从数据库中取出组成物信息
  693. let mixRatioList = await mixRatioModel.find({'unit_price_file_id': unitPriceFileId,'connect_key': {'$in':connectKeyList}}).lean();
  694. for(let m of mixRatioList){
  695. //组成物信息分组,查看哪些是已经存在的
  696. existMixRatioMap[m.connect_key]?existMixRatioMap[m.connect_key].push(m):existMixRatioMap[m.connect_key]=[m];
  697. //查看组成物对应的项目工料机是否存在,如果不存在,要插入项目工料机
  698. let mkey = getIndex(m);
  699. if(!projectGLJMap[mkey] && !codeMap[m.code]){//如果之前查出来的项目工料机中不包含组成物的信息,要加到missCode里面再查找一次项目工料机看是否存在
  700. missCodeList.push(m.code);
  701. codeMap[m.code] = true;
  702. }
  703. }
  704. // 2 将第一步得到的映射表 与在标准库查询父工料机得到的映射表对比,得出哪些组物成还需要添加,获得库ID
  705. let stdIDs = [];
  706. let comIDs = [];
  707. let missMixRatioGroup = [];
  708. for(let ck of connectKeyList){//查看项目中组成物信息是否已经存在,如果不存在,则用插定额时获取的组成物信息从数据库中获取
  709. if(!existMixRatioMap[ck] && mixRatioMap[ck] && mixRatioMap[ck].length > 0){//组成物信息不存在
  710. let pglj = projectGLJMap[ck];//取出父数据
  711. let from = pglj.from === undefined|| pglj.from ===null || pglj.from === ""?'std' : pglj.from;
  712. for(let c of mixRatioMap[ck]){
  713. if(from == "std"){//标准的工料机只来自标准的
  714. stdIDs.push(c.ID);
  715. }else{
  716. c.isStd?stdIDs.push(c.ID):comIDs.push(c.ID);
  717. }
  718. }
  719. missMixRatioGroup.push({'connect_key':ck,'list':mixRatioMap[ck],'from':from});
  720. }
  721. }
  722. //3.统一查询所有组成物在标准库中的详细信息
  723. let stdMixMap = {};
  724. //整理需插入的组成物列表的数据
  725. //来自标准工料机
  726. if(stdIDs.length > 0){
  727. stdIDs = _.uniq(stdIDs);//去重
  728. let stdMixList = await std_glj_lib_gljList_model.find({'ID':{'$in':stdIDs}}).lean();
  729. for(let sm of stdMixList){
  730. stdMixMap[sm.ID] = sm;
  731. let skey = getIndex(sm,['code','name','specs','unit','gljType']);
  732. if(!projectGLJMap[skey] && !codeMap[sm.code]){
  733. missCodeList.push(sm.code);
  734. codeMap[sm.code] = true;
  735. }
  736. }
  737. }
  738. //来自组成物工料机
  739. let comMixMap = {};
  740. if(comIDs.length > 0){
  741. comIDs = _.uniq(comIDs);//去重
  742. let comMixList = await complementaryGljLibModel.find({'ID':{'$in':comIDs}}).lean();
  743. for(let cm of comMixList){
  744. comMixMap[cm.ID] = cm;
  745. let ckey = getIndex(cm,['code','name','specs','unit','gljType']);
  746. if(!projectGLJMap[ckey] && codeMap[cm.code]){
  747. missCodeList.push(cm.code);
  748. codeMap[cm.code] = true;
  749. }
  750. }
  751. }
  752. //4.生成需要插入组成物表的数据
  753. for(let mg of missMixRatioGroup){//整理需要插入组成物列表的数据
  754. for(let tc of mg.list){
  755. let consumpiton = tc.consumeAmt;
  756. //只有标准的工料机的组成物才会有多单价、多组成物消耗量的情况
  757. if(mg.from == 'std' && ext && ext.quantityField &&( tc.consumeAmtProperty[ext.quantityField]!= undefined && tc.consumeAmtProperty[ext.quantityField]!=null)){
  758. consumpiton = tc.consumeAmtProperty[ext.quantityField];
  759. }
  760. let mfrom = mg.from == 'std' || tc.isStd?'std':'cpt';
  761. let tmp = mfrom == 'std'?stdMixMap[tc.ID]:comMixMap[tc.ID];//取出之前库中查到的工料机
  762. let mixRatioData = {
  763. consumption: consumpiton,
  764. glj_id: tmp.ID,
  765. unit_price_file_id: unitPriceFileId,
  766. connect_key: mg.connect_key,
  767. type: tmp.gljType,
  768. code: tmp.code,
  769. specs:tmp.specs?tmp.specs:"",
  770. name:tmp.name,
  771. unit:tmp.unit?tmp.unit:'',
  772. from:mfrom
  773. };
  774. mixRatioInsertData.push(mixRatioData);
  775. }
  776. }
  777. //4.5 处理车船税问题,查询机械台班是否需要添加车船税
  778. if(CCSMap.codes.length > 0){
  779. let unitFileInfo = await unitPriceFileModel.findOne({id:unitPriceFileId}).lean();
  780. if(unitFileInfo.vvTaxFileID && unitFileInfo.vvTaxFileID!=""){
  781. let needCCS = false;
  782. let items = await vvTaxModel.find({libID:unitFileInfo.vvTaxFileID,'code':{'$in':CCSMap.codes}}).lean();
  783. for(let i of items){
  784. let ikey = getIndex(i);
  785. if(CCSMap.keyMap[ikey]){
  786. needCCS = true;
  787. mixRatioInsertData.push(gljUtil.getBaseCCSMixRatio(unitPriceFileId,i.vehicleVesselTax,ikey))
  788. }
  789. }
  790. if(needCCS && !codeMap["80CCS"]) missCodeList.push("80CCS");
  791. }
  792. }
  793. if(mixRatioInsertData.length > 0) await setIDfromCounter("mix_ratio",mixRatioInsertData,existMixRatioMap,'connect_key');
  794. //await mixRatioModel.insertMany(mixRatioInsertData); 因为没有事务添加组成物数据要放在添加单价文件数据之后
  795. //5.查询组成物对应的项目工料机是否存在,如果不存在,生成项目工料机信息
  796. let projectGLJList = await projectGLJModel.find({'project_id':projectID,'code':{'$in':missCodeList}}).lean();
  797. for(let pg of projectGLJList){
  798. let pindex = getIndex(pg);
  799. projectGLJMap[pindex] = pg;
  800. }
  801. let lessMix = [];//组成物表存在,项目工料机不存在的数据
  802. let lessMixMap = {};//防止重复添加
  803. for(let connect_key in existMixRatioMap){
  804. let mixRatios = existMixRatioMap[connect_key];
  805. for(let m of mixRatios){
  806. let mk = getIndex(m);
  807. if(!projectGLJMap[mk] && !lessMixMap[mk]){//如果组成物对应的项目工料机不存在
  808. let nglj = null;
  809. if(m.from == 'std'){//这里有值,说明是刚添加到组成物文件中的数据
  810. nglj = stdMixMap[m.glj_id];
  811. }else if(m.from == 'cpt'){//这里有值,说明是刚添加到组成物文件中的数据
  812. nglj = comMixMap[m.glj_id];
  813. }
  814. if(nglj){
  815. nglj.from = m.from;
  816. let np = getProjectGLJNewData(nglj,projectID,ext);
  817. newProjectGLJList.push(np);
  818. projectGLJMap[mk] = np;
  819. }else{//这里没找到,说明是组成物文件里有,但是项目工料机没有的数据
  820. lessMix.push(m);
  821. }
  822. lessMixMap[mk] = true;//只要处理过一次,就不用再重新处理了,机械组成物,比如柴油这些,会出现多次
  823. }
  824. }
  825. }
  826. //6. 组成物文件里有,但是项目工料机没有的数据(共用单价文件等情况产生)
  827. let lessIDList=[];
  828. let uniqMap ={};//去重
  829. let lessStdMix = [];//防止组成物中改了名称等,但是通过glj_id取出来的是还没改前的原始数据
  830. if(lessMix.length > 0){
  831. for(let lm of lessMix){
  832. let parentglj = projectGLJMap[lm.connect_key];
  833. if(!parentglj) throw `含有组成物工料机${lm.connect_key},没有找到,添加定额失败`;
  834. if((parentglj.from == "std" || lm.from == "std") && lm.code!="80CCS"){//车船税特殊处理
  835. if(!uniqMap[lm.glj_id]){
  836. lessIDList.push(lm.glj_id);
  837. uniqMap[lm.glj_id] = lm;
  838. }
  839. lessStdMix.push(lm);
  840. }else {//来自组成物的直接设置
  841. lm.from = 'cpt';
  842. lm.gljType = lm.type;
  843. let t_mg = getProjectGLJNewData(lm,projectID);
  844. newProjectGLJList.push(t_mg);
  845. projectGLJMap[getIndex(lm)] = t_mg;
  846. }
  847. }
  848. }
  849. if(lessIDList.length > 0){
  850. let less_stds = await std_glj_lib_gljList_model.find({'ID':{'$in':lessIDList}}).lean();
  851. let less_stds_map = {};
  852. for(let les of less_stds){
  853. less_stds_map[les.ID] = les;
  854. }
  855. for(let t_l_m of lessStdMix){
  856. let t_nglj = less_stds_map[t_l_m.glj_id];
  857. t_nglj.from = 'std';
  858. //防止组成物中改了名称等,但是通过glj_id取出来的是还没改前的原始数据
  859. t_nglj.name = t_l_m.name;
  860. t_nglj.code = t_l_m.code;
  861. t_nglj.gljType = t_l_m.type;
  862. t_nglj.specs = t_l_m.specs;
  863. t_nglj.unit = t_l_m.unit;
  864. let t_np = getProjectGLJNewData(t_nglj,projectID,ext);
  865. newProjectGLJList.push(t_np);
  866. projectGLJMap[getIndex(t_l_m)] = t_np;
  867. }
  868. }
  869. }
  870. return [existMixRatioMap,mixRatioInsertData,missCodeList]
  871. }
  872. //根据缺少项目工料机的组成物信息,反向生成对应的项目工料机
  873. async function getNewProjectGLJFromMissMixratio(projectID,lessMix,projectGLJMap,newProjectGLJList,ext){
  874. let lessIDList=[];
  875. let uniqMap ={};//去重
  876. let lessStdMix = [];//防止组成物中改了名称等,但是通过glj_id取出来的是还没改前的原始数据
  877. if(lessMix.length > 0){
  878. for(let lm of lessMix){
  879. let parentglj = projectGLJMap[lm.connect_key];
  880. if(!parentglj) throw `含有组成物工料机${lm.connect_key},没有找到,添加定额失败`;
  881. if((parentglj.from == "std" || lm.from == "std") && lm.code!="80CCS"){//车船税特殊处理
  882. if(!uniqMap[lm.glj_id]){
  883. lessIDList.push(lm.glj_id);
  884. uniqMap[lm.glj_id] = lm;
  885. }
  886. lessStdMix.push(lm);
  887. }else {//来自组成物的直接设置
  888. lm.from = 'cpt';
  889. lm.gljType = lm.type;
  890. let t_mg = getProjectGLJNewData(lm,projectID);
  891. newProjectGLJList.push(t_mg);
  892. projectGLJMap[getIndex(lm)] = t_mg;
  893. }
  894. }
  895. }
  896. if(lessIDList.length > 0){
  897. let less_stds = await std_glj_lib_gljList_model.find({'ID':{'$in':lessIDList}}).lean();
  898. let less_stds_map = {};
  899. for(let les of less_stds){
  900. less_stds_map[les.ID] = les;
  901. }
  902. for(let t_l_m of lessStdMix){
  903. let t_nglj = less_stds_map[t_l_m.glj_id];
  904. t_nglj.from = 'std';
  905. //防止组成物中改了名称等,但是通过glj_id取出来的是还没改前的原始数据
  906. t_nglj.name = t_l_m.name;
  907. t_nglj.code = t_l_m.code;
  908. t_nglj.gljType = t_l_m.type;
  909. t_nglj.specs = t_l_m.specs;
  910. t_nglj.unit = t_l_m.unit;
  911. let t_np = getProjectGLJNewData(t_nglj,projectID,ext);
  912. newProjectGLJList.push(t_np);
  913. projectGLJMap[getIndex(t_l_m)] = t_np;
  914. }
  915. }
  916. return newProjectGLJList;
  917. }
  918. function getProjectGLJNewData(tmp,projectId,ext){
  919. let gljData = {
  920. glj_id: tmp.ID,
  921. repositoryId:tmp.repositoryId,
  922. project_id: projectId,
  923. code: tmp.code,
  924. name: tmp.name,
  925. specs: tmp.specs?tmp.specs:'',
  926. unit: tmp.unit === undefined ? '' : tmp.unit,
  927. type: tmp.gljType,
  928. adjCoe:tmp.adjCoe,
  929. original_code:tmp.code,
  930. materialType: tmp.materialType, //三材类别
  931. materialCoe: tmp.materialCoe,
  932. base_price: tmp.basePrice,
  933. market_price: tmp.basePrice,
  934. from:tmp.from?tmp.from:"std"
  935. };
  936. if(gljData.from == 'std' && ext && ext.priceField &&(tmp.priceProperty && tmp.priceProperty[ext.priceField]!= undefined && tmp.priceProperty[ext.priceField]!=null)){
  937. const basePrice = scMathUtil.roundTo(tmp.priceProperty[ext.priceField],-6);
  938. gljData.base_price = basePrice;
  939. gljData.market_price = basePrice;
  940. }
  941. return gljData;
  942. }
  943. async function setIDfromCounter(name,list,map,keyfield){//map,keyfield
  944. let update = {$inc: {sequence_value: list.length}};
  945. let condition = {_id: name};
  946. let options = {new: true};
  947. // 先查找更新
  948. let counter = await counterModel.findOneAndUpdate(condition, update, options);
  949. let firstID = counter.sequence_value - (list.length - 1);
  950. for(let a of list){
  951. a.id = firstID;
  952. firstID+=1
  953. if(map && keyfield){
  954. let key = a[keyfield];
  955. map[key]?map[key].push(a):map[key]=[a]
  956. }
  957. }
  958. }
  959. function getStdGlj(sub,stdGLJMap,cptGLJMap,newGLJ,ext) {
  960. let std_glj = null;
  961. if(sub.type == 'complementary'){//有可能来自标准工料机库或补充工料机库
  962. std_glj = cptGLJMap[sub.gljId];
  963. newGLJ.from = 'cpt';
  964. }else {
  965. std_glj = stdGLJMap[sub.gljId];
  966. newGLJ.from = 'std';
  967. //多单价情况处理
  968. if(ext && ext.priceField && std_glj && std_glj.priceProperty){
  969. std_glj.basePrice = std_glj.priceProperty[ext.priceField];
  970. }
  971. }
  972. return std_glj;
  973. }
  974. async function deleRationSubRecode(projectID,rationID,cleanzmhs=false) {//删除挂在定额下的数据,如工程量明细,定额工料机等
  975. let delete_query={projectID: projectID, rationID: rationID};
  976. //删除工程量明细
  977. await deleteSubListByQuery(delete_query,cleanzmhs) ;
  978. }
  979. async function deleteSubListByQuery(delete_query,cleanzmhs=false) {
  980. if(cleanzmhs == false){//清空子目换算即cleanzmh==true时不需要清空工程量明细、模板关联子目、安装增加费
  981. await quantity_detail.deleteByQuery(delete_query) ;//删除工程量明细
  982. await rationInstallationModel.deleteMany(delete_query);//删除安装增加费
  983. await rationTemplateModel.deleteMany(delete_query);//删除模板关联子目
  984. }
  985. //to do稳定土也要删除
  986. await ration_coe.deleteMany(delete_query);//删除附注条件
  987. await ration_glj.deleteMany(delete_query);//删除定额工料机
  988. }
  989. async function updateCoeAdjust(data,compilation) {
  990. let replace = [],projectGLJList=[];
  991. await ration_coe.update({ID:data.ID},data.doc);
  992. //添加单个工料机的情况
  993. if (data.add.length > 0){
  994. let [tg,pl] = await ration_glj_facade.insertAddTypeGLJ(data.add,compilation);
  995. if(pl.length > 0) projectGLJList = projectGLJList.concat(pl);
  996. }
  997. if(data.delete.length > 0) await ration_glj_facade.deleteGLJ(data.delete);
  998. //替换工料机的情况
  999. if (data.replace.length > 0){
  1000. for(let r of data.replace){
  1001. let r_result = await ration_glj_facade.replaceGLJByData(r,compilation);
  1002. replace.push(r_result.data) ;
  1003. projectGLJList.push(r_result.projectGLJ);
  1004. if(r_result.newRecodes.length > 0) data.add = data.add.concat(r_result.newRecodes);
  1005. if(r_result.deleteList.length > 0) data.delete = data.delete.concat(r_result.deleteList);
  1006. }
  1007. }
  1008. let cal_result = await glj_calculate_facade.calculateQuantity({projectID:data.projectID,rationID:data.rationID},null,true);
  1009. let coe = {
  1010. query:{ID:data.ID,projectID:data.projectID},
  1011. doc:data.doc
  1012. };
  1013. let ration_glj ={
  1014. quantityRefresh:true,
  1015. glj_result:cal_result.glj_result
  1016. };
  1017. let ration = {
  1018. ID:cal_result.rationID,
  1019. adjustState:cal_result.adjustState,
  1020. name:cal_result.rationName
  1021. };
  1022. return {coe:coe,ration_glj:ration_glj,ration:ration,add:data.add,delete:data.delete,replace:replace,projectGLJList:projectGLJList}
  1023. }
  1024. async function updateRation(std,defaultLibID,rationID,billsItemID,projectID,calQuantity,cleanzmh=false) {
  1025. // insertNewRation
  1026. let ration ={};
  1027. ration.code = std.code;
  1028. ration.name = std.name;
  1029. ration.caption = std.caption;
  1030. ration.unit = std.unit;
  1031. if (std.type === 'std') {
  1032. ration.libID = std.rationRepId;
  1033. ration.stdID = std.ID;
  1034. }
  1035. ration.content = std.jobContent;
  1036. ration.adjustState = '';
  1037. ration.isFromDetail=0;
  1038. ration.isSubcontract=false;
  1039. ration.fees=[];
  1040. if (std.chapter) {
  1041. ration.comments = std.chapter.explanation;
  1042. ration.ruleText = std.chapter.ruleText;
  1043. }
  1044. ration.from = std.type === 'complementary' ? 'cpt' : 'std';
  1045. //定额前缀 none:0, complementary:1, borrow: 2
  1046. ration.prefix = '';
  1047. //借用优先级比补充高
  1048. if(std.rationRepId !== parseInt(defaultLibID)){//借用
  1049. ration.prefix = '借';
  1050. }
  1051. else if(std.rationRepId === defaultLibID && ration.from === 'cpt') {
  1052. ration.prefix = '补';
  1053. }
  1054. ration.rationAssList =await createRationAss(std);//生成辅助定额
  1055. if(cleanzmh==false){//如果是清空子目换算,即cleanzmh==true 保留定额工程量、工程量表达式、含量(分解系数)、取费专业(取费类别)
  1056. if(std.feeType == undefined || std.feeType == null || std.feeType ==''){//定额取费专业为空的情况下,取项目属性中的定额取费专业ID
  1057. ration.programID = await getProgramForProject(projectID);
  1058. }else {
  1059. ration.programID = std.feeType;
  1060. }
  1061. if( calQuantity){
  1062. await CalculateQuantity(ration,billsItemID,projectID);
  1063. }
  1064. }
  1065. let unsetObject = {
  1066. "marketUnitFee":1,
  1067. 'marketTotalFee':1,
  1068. "maskName":1
  1069. }
  1070. let newRation = await ration_model.model.findOneAndUpdate({ID:rationID,projectID:projectID},{"$set":ration,"$unset":unsetObject},{new: true});//;
  1071. return newRation;
  1072. }
  1073. async function setEmptyRation(projectID,rationID){
  1074. let ration ={};
  1075. ration.code = "";
  1076. ration.name = "";
  1077. ration.caption = "";
  1078. ration.unit = "";
  1079. ration.libID = null;
  1080. ration.content = "";
  1081. ration.adjustState = '';
  1082. ration.isFromDetail=0;
  1083. ration.isSubcontract=false;
  1084. ration.fees=[];
  1085. ration.comments = "";
  1086. ration.ruleText = "";
  1087. ration.quantity="";
  1088. ration.contain="";
  1089. ration.quantityEXP="";
  1090. ration.from = 'std';
  1091. //定额前缀 none:0, complementary:1, borrow: 2
  1092. ration.prefix = '';
  1093. ration.rationAssList = [];
  1094. ration.marketUnitFee ="";
  1095. ration.marketTotalFee ="";
  1096. ration.maskName = "";
  1097. ration.targetTotalFee ='';
  1098. ration.targetUnitFee = "";
  1099. ration.deleteInfo = null;
  1100. ration.quantityCoe = {};
  1101. ration.rationQuantityCoe="";
  1102. ration.tenderQuantity = "";
  1103. ration.programID = null;
  1104. let newRation = await ration_model.model.findOneAndUpdate({ID:rationID,projectID:projectID},{"$set":ration},{new: true});//;
  1105. return {ration:newRation,ration_gljs:[],ration_coes:[],ration_installs:[]};
  1106. }
  1107. async function createRationAss(std,isMaterial) {
  1108. let rationAssList = [];//生成辅助定额
  1109. if(std.hasOwnProperty('rationAssList')&&std.rationAssList.length>0){
  1110. let assGroup = _.groupBy(std.rationAssList,'name');
  1111. for(let key in assGroup){
  1112. let assList = assGroup[key];
  1113. let ass = assList[0];
  1114. ass._doc.actualValue = ass.stdValue;
  1115. ass._doc.isAdjust = 0;
  1116. if(_.isString(ass._doc.assistCode)) ass._doc.assistCode = ass._doc.assistCode.replace("\n","");
  1117. if(_.isString(ass._doc.thirdRationCode)) ass._doc.thirdRationCode = ass._doc.thirdRationCode.replace("\n","");
  1118. if(assList.length > 1){
  1119. ass._doc.groupList = JSON.parse(JSON.stringify(assList)) ;
  1120. ass._doc.maxValue = assList[assList.length-1]._doc.maxValue;
  1121. }
  1122. if(isMaterial == true){//材料计算进来的,直接保存辅助定额的信息 //常规的定额以后可以考虑也这样做
  1123. let t_assRation = await rationItemModel.findOne({rationRepId:std.rationRepId,code:ass.assistCode}).lean();
  1124. if(t_assRation) ass._doc.assRation = t_assRation;
  1125. }
  1126. rationAssList.push(ass);
  1127. }
  1128. }
  1129. return rationAssList;
  1130. }
  1131. async function CalculateQuantity (ration,billsItemID,projectID) {
  1132. // calculate ration Quantity
  1133. let project = await projectModel.findOne({ID:projectID});
  1134. let decimalObject =await decimal_facade.getProjectDecimal(projectID,project);
  1135. let quantity_decimal = (decimalObject&&decimalObject.ration&&decimalObject.ration.quantity)?decimalObject.ration.quantity:3;
  1136. let pbill = await bill_model.model.findOne({projectID:projectID,ID:billsItemID});
  1137. let rationTimes = 1 ;//清单单位转定额单位的倍数,如 kg 转 t 时是1000
  1138. let t_unit = ration.unit?ration.unit:"";
  1139. let b_unit = pbill.unit?pbill.unit:"";
  1140. ration.quantityEXP="QDL";
  1141. if((/.*kg$/i).test(b_unit)){
  1142. if((/t/i).test(t_unit)) {
  1143. rationTimes = 1000;//如 kg 转 t 时是1000
  1144. ration.quantityEXP="QDL*0.001"
  1145. }
  1146. if((/10t/i).test(t_unit)){
  1147. rationTimes = 10000;//如 kg 转 10t 时是1000
  1148. ration.quantityEXP="QDL*0.0001"
  1149. }
  1150. }
  1151. /* let t_unit = ration.unit?ration.unit.replace(/^\d+/,""):""; 2019-02-01 养护去掉清单与定额单位的这个判断
  1152. if(t_unit!=pbill.unit){//如果定额工程量的单位去除前面的数字后不等于清单单位,定额工程量保持不变
  1153. return ;
  1154. }*/
  1155. let billsQuantity = pbill.quantity ? pbill.quantity : 0;
  1156. let bill_decimal = await decimal_facade.getBillsQuantityDecimal(projectID,pbill.unit,project);
  1157. let ftimes = rationTimes == 1?FilterNumberFromUnit(ration.unit):rationTimes;
  1158. billsQuantity=scMathUtil.roundForObj(billsQuantity,bill_decimal);
  1159. ration.quantity = scMathUtil.roundForObj(billsQuantity / ftimes ,quantity_decimal);//不管是否打勾都做转换
  1160. ration.contain = scMathUtil.roundForObj(ration.quantity/billsQuantity,6);
  1161. };
  1162. async function getProgramForProject(projectID){
  1163. let project = await projectModel.findOne({ID:projectID});
  1164. return project.property.engineering;
  1165. }
  1166. function FilterNumberFromUnit (unit) {
  1167. let reg = new RegExp('^[0-9]+');
  1168. if (reg.test(unit)) {
  1169. return parseInt(unit.match(reg)[0]);
  1170. } else {
  1171. return 1;
  1172. }
  1173. };
  1174. function getIndex(obj,tpops){
  1175. let pops = tpops?tpops:['code','name','specs','unit','type'];
  1176. let t_index = '';
  1177. let k_arr=[];
  1178. for(let p of pops){
  1179. let tmpK = (obj[p]==undefined||obj[p]==null||obj[p]=='')?'null':obj[p];
  1180. k_arr.push(tmpK);
  1181. }
  1182. t_index=k_arr.join("|-|");
  1183. return t_index;
  1184. }