ration_facade.js 31 KB

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