ration_facade.js 46 KB

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