ration_facade.js 44 KB

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