ration_facade.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  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 ration_glj_facade = require("../../ration_glj/facade/ration_glj_facade");
  8. let quantity_detail = require("../facade/quantity_detail_facade");
  9. let ration_glj = mongoose.model('ration_glj');
  10. let ration_coe = mongoose.model('ration_coe');
  11. let ration_model = require('../models/ration');
  12. let bill_model = require('../models/bills');
  13. let decimal_facade = require('./decimal_facade');
  14. let installationFeeModel = mongoose.model("installation_fee");
  15. let rationInstallationModel = mongoose.model('ration_installation');
  16. const uuidV1 = require('uuid/v1');
  17. let std_glj_lib_gljList_model = mongoose.model('std_glj_lib_gljList');
  18. let complementary_glj_model = mongoose.model('complementary_glj_lib');
  19. let coeMolde = mongoose.model('std_ration_lib_coe_list');
  20. let _= require('lodash');
  21. const projectDao = require('../../pm/models/project_model').project;
  22. let projectModel = mongoose.model('projects');
  23. module.exports = {
  24. replaceRations: replaceRations,
  25. addNewRation:addNewRation,
  26. addMultiRation: addMultiRation
  27. };
  28. async function addNewRation(data) {
  29. let query = data.itemQuery;
  30. let stdRation = null;
  31. let startTime = +new Date();
  32. if(query){
  33. let searchDao = new SearchDao();
  34. stdRation = await searchDao.getRationItem(query.userID,[query.rationRepId],query.code, query.ID);
  35. //data.newData.code = query.code;
  36. }
  37. let stdRationTime = +new Date();
  38. console.log("取std定额时间-------------------------------"+(stdRationTime - startTime));
  39. if(data.brUpdate.length>0){
  40. await updateSerialNo(data.brUpdate);
  41. }
  42. let newRation =await insertNewRation(data.newData,data.firstLibID,stdRation,data.calQuantity);
  43. let addRationGLJTime = +new Date();
  44. console.log("插入新定额时间-------------------------------"+(addRationGLJTime - stdRationTime));
  45. if(stdRation){
  46. return await addRationSubList(stdRation,newRation,data.needInstall);
  47. }else {
  48. return {ration:newRation};
  49. }
  50. }
  51. async function addMultiRation(datas) {
  52. let rst = [];
  53. for(let data of datas){
  54. let r = await addNewRation(data);
  55. rst.push(r);
  56. }
  57. return rst;
  58. }
  59. async function updateSerialNo(serialNoUpdate){
  60. let tasks=[];
  61. for(let data of serialNoUpdate){
  62. let task={
  63. updateOne:{
  64. filter:{
  65. ID:data.ID,
  66. projectID:data.projectID
  67. },
  68. update :{
  69. serialNo:data.serialNo
  70. }
  71. }
  72. };
  73. tasks.push(task);
  74. }
  75. await ration_model.model.bulkWrite(tasks);
  76. }
  77. async function insertNewRation(newData,firstLibID,std,calQuantity) {//插入新的定额
  78. let startTime = +new Date();
  79. if(std){
  80. newData.code = std.code;
  81. newData.name = std.name;
  82. newData.caption = std.caption;
  83. newData.unit = std.unit;
  84. newData.libID = std.rationRepId;
  85. newData.content = std.jobContent;
  86. newData.annotation = std.annotation;
  87. if (std.chapter) {
  88. newData.comments = std.chapter.explanation;
  89. newData.ruleText = std.chapter.ruleText;
  90. }
  91. newData.prefix = '';
  92. newData.from = std.type === 'complementary' ? 'cpt' : 'std';
  93. if(firstLibID !== std.rationRepId){//借
  94. newData.prefix = '借';
  95. }
  96. else if(std.rationRepId === firstLibID && newData.from === 'cpt') {
  97. newData.prefix = '补';
  98. }
  99. if(std.feeType == undefined || std.feeType == null || std.feeType ==''){//定额取费专业为空的情况下,取项目属性中的定额取费专业ID
  100. newData.programID = await getProgramForProject(newData.projectID);
  101. }else {
  102. newData.programID = std.feeType;
  103. }
  104. newData.rationAssList = createRationAss(std);
  105. // calculate ration Quantity
  106. }
  107. if(calQuantity){
  108. await CalculateQuantity(newData,newData.billsItemID,newData.projectID);
  109. }
  110. let addRationGLJTime = +new Date();
  111. console.log("计算消耗量时间-------------------------------"+(addRationGLJTime - startTime));
  112. console.log(newData);
  113. let newRation = await ration_model.model.create(newData);
  114. return newRation;
  115. /*ration_model.model.create(newData);
  116. return newData;*/
  117. }
  118. async function replaceRations(userID,data) {
  119. let searchDao = new SearchDao();
  120. let recodes = [];
  121. for(let recode of data.nodeInfo){
  122. let stdRation = await searchDao.getRationItem(userID,data.libIDs,recode.newCode, null);
  123. let newRecode = await replaceRation(recode,stdRation,data.firstLibID,data.projectID,data.calQuantity);
  124. if(newRecode){
  125. recodes.push(newRecode);
  126. }else {
  127. break;
  128. }
  129. }
  130. return recodes;
  131. }
  132. async function replaceRation(nodeInfo,stdRation,firstLibID,projectID,calQuantity) {
  133. if(nodeInfo.newCode == null||nodeInfo.newCode ==""){//说明是删除编号,则要变成一条空定额
  134. await deleRationSubRecode(projectID,nodeInfo.ID);//删除定额下挂的各种数据,如定额工料机等
  135. return await setEmptyRation(projectID,nodeInfo.ID);
  136. }else if(stdRation){
  137. await deleRationSubRecode(projectID,nodeInfo.ID);//删除定额下挂的各种数据,如定额工料机等
  138. let newRation = await updateRation(stdRation,firstLibID,nodeInfo.ID,nodeInfo.billsItemID,projectID,calQuantity);//生成并插入新的定额
  139. return await addRationSubList(stdRation,newRation,nodeInfo.needInstall);
  140. }else {
  141. return null;
  142. }
  143. }
  144. async function addRationSubList(stdRation,newRation,needInstall) {
  145. let startTime = +new Date();
  146. let ration_gljs = await addRationGLJ(stdRation,newRation);
  147. let addRationGLJTime = +new Date();
  148. console.log("添加定额工料机时间-----"+(addRationGLJTime - startTime));
  149. let ration_coes = await addRationCoe(stdRation,newRation);
  150. let addRationCoeTime = +new Date();
  151. console.log("添加定额coe时间-----"+(addRationCoeTime - addRationGLJTime));
  152. let ration_installs = [];
  153. if(needInstall){
  154. ration_installs = await addRationInstallFee(stdRation,newRation);
  155. }
  156. let addRationInstallFeeTime = +new Date();
  157. console.log("添加定额install时间-----"+(addRationInstallFeeTime - addRationCoeTime));
  158. return {ration:newRation,ration_gljs:ration_gljs,ration_coes:ration_coes,ration_installs:ration_installs};
  159. }
  160. async function addRationInstallFee(std,newRation) {
  161. let install_fee_list = [];
  162. if(std.hasOwnProperty('rationInstList') && std.rationInstList.length > 0){
  163. let installFee = await installationFeeModel.findOne({'projectID': newRation.projectID});
  164. for(let ri of std.rationInstList){
  165. let feeItem = _.find(installFee.installFeeItem,{'ID':ri.feeItemId});
  166. let section = _.find(installFee.installSection,{'ID':ri.sectionId});
  167. if(feeItem&&section){
  168. let tem_r_i = {
  169. libID:installFee.libID,
  170. projectID:newRation.projectID,
  171. rationID:newRation.ID,
  172. feeItemId:feeItem.ID,
  173. sectionId:section.ID,
  174. itemName:feeItem.feeItem,
  175. feeType:feeItem.feeType,
  176. sectionName:section.name,
  177. unifiedSetting:1,
  178. ruleId:''
  179. };
  180. if(feeItem.isCal==1&&section.feeRuleId&&section.feeRuleId!=''){//勾选记取时并且有规则ID时才读取
  181. let feeRule = _.find(installFee.feeRule,{'ID':section.feeRuleId});
  182. if(feeRule){
  183. tem_r_i.ruleId = feeRule.ID;
  184. }
  185. }
  186. tem_r_i.ID = uuidV1();
  187. install_fee_list.push(tem_r_i);
  188. }
  189. }
  190. if(install_fee_list.length>0){
  191. await rationInstallationModel.insertMany(install_fee_list);
  192. }
  193. }
  194. return install_fee_list;
  195. }
  196. async function addRationCoe(std,newRation) {
  197. let ration_coe_list = [];
  198. let seq = 0;
  199. if(std.hasOwnProperty('rationCoeList')&&std.rationCoeList.length>0){//添加标准库的工料机
  200. for(let sub of std.rationCoeList){
  201. let libCoe = await coeMolde.findOne({'libID':std.rationRepId,'ID':sub.ID,"$or": [{"isDeleted": null}, {"isDeleted": false}]});//std.rationRepId;
  202. if(libCoe){
  203. let newCoe = {};
  204. newCoe.ID = uuidV1();
  205. newCoe.coeID = sub.ID;
  206. newCoe.seq = seq;
  207. newCoe.name = libCoe.name;
  208. newCoe.content = libCoe.content;
  209. newCoe.isAdjust=0;
  210. newCoe.coes = libCoe.coes;
  211. newCoe.rationID = newRation.ID;
  212. newCoe.projectID = newRation.projectID;
  213. seq++;
  214. ration_coe_list.push(newCoe);
  215. }
  216. }
  217. }
  218. let lastCoe ={
  219. coeID:-1,
  220. name : '自定义系数',
  221. content:'人工×1,材料×1,机械×1,主材×1,设备×1',
  222. isAdjust:0,
  223. seq:seq,
  224. rationID : newRation.ID,
  225. projectID : newRation.projectID
  226. };
  227. lastCoe.ID = uuidV1();
  228. lastCoe.coes = getCustomerCoeData();
  229. ration_coe_list.push(lastCoe);
  230. await ration_coe.insertMany(ration_coe_list);
  231. return ration_coe_list;
  232. }
  233. function getCustomerCoeData() {
  234. var coeList = [];
  235. coeList.push({ amount:1, operator:'*', gljCode:null, coeType:'定额'});
  236. coeList.push({ amount:1, operator:'*', gljCode:null, coeType:'人工'});
  237. coeList.push({ amount:1, operator:'*', gljCode:null, coeType:'材料'});
  238. coeList.push({ amount:1, operator:'*', gljCode:null, coeType:'机械'});
  239. coeList.push({ amount:1, operator:'*', gljCode:null, coeType:'主材'});
  240. coeList.push({ amount:1, operator:'*', gljCode:null, coeType:'设备'});
  241. return coeList;
  242. };
  243. async function addRationGLJ(std,newRation) {
  244. let newRationGLJList = [];
  245. let rationGLJShowList = [];
  246. let unitPriceFileId = await projectDao.getUnitPriceFileId(newRation.projectID);
  247. let sum=0;
  248. let first = +new Date();
  249. if(std.hasOwnProperty('rationGljList') && std.rationGljList.length > 0){
  250. let stdGLJID =[];//标准工料机ID数组
  251. let cptGLJID=[];//补充工料机ID数组
  252. //let stdGLJID = _.map(std.rationGljList,'gljId');
  253. for(let tem_g of std.rationGljList){
  254. if(tem_g.type == 'complementary'){
  255. cptGLJID.push(tem_g.gljId);
  256. }else {
  257. stdGLJID.push(tem_g.gljId);
  258. }
  259. }
  260. let stdGLJList = stdGLJID.length > 0 ? await std_glj_lib_gljList_model.find({'ID':{'$in':stdGLJID}}):[];//速度优化-------先一次性取出所有的工料机列表
  261. let stdGLJMap = _.indexBy(stdGLJList, 'ID');
  262. let cptGLJList = cptGLJID.length > 0 ? await complementary_glj_model.find({'userId':std.userId,'ID':{'$in':cptGLJID}}):[];
  263. let cptGLJMap = _.indexBy(cptGLJList, 'ID');
  264. let stdGLJMapTime = +new Date();
  265. console.log("找到工料机映射表时间-------------------------------"+(stdGLJMapTime - first));
  266. for(let sub of std.rationGljList){
  267. let newGLJ = {};
  268. newGLJ.ID = uuidV1();
  269. newGLJ.projectID = newRation.projectID;
  270. newGLJ.GLJID = sub.gljId;
  271. newGLJ.rationID = newRation.ID;
  272. newGLJ.billsItemID = newRation.billsItemID;
  273. newGLJ.rationItemQuantity = sub.consumeAmt;
  274. newGLJ.quantity = sub.consumeAmt;
  275. newGLJ.glj_repository_id = std.rationRepId;
  276. let std_glj = null;
  277. if(sub.type == 'complementary'){//有可能来自标准工料机库或补充工料机库
  278. std_glj = cptGLJMap[sub.gljId];
  279. newGLJ.from = 'cpt';
  280. }else {
  281. std_glj = stdGLJMap[sub.gljId];
  282. newGLJ.from = 'std';
  283. }
  284. let std_gljTime = +new Date();
  285. if(std_glj){
  286. newGLJ.name = std_glj.name;
  287. newGLJ.code = std_glj.code;
  288. newGLJ.original_code = std_glj.code;
  289. newGLJ.unit = std_glj.unit;
  290. newGLJ.specs = std_glj.specs;
  291. newGLJ.model = std_glj.model;
  292. newGLJ.basePrice = std_glj.basePrice;
  293. newGLJ.marketPrice = std_glj.basePrice;
  294. newGLJ.shortName = std_glj.shortName;
  295. newGLJ.type = std_glj.gljType;
  296. newGLJ.repositoryId = std_glj.repositoryId;
  297. newGLJ.adjCoe = std_glj.adjCoe;
  298. newGLJ.materialType = std_glj.materialType;
  299. newGLJ.materialCoe = std_glj.materialCoe;
  300. newGLJ.createType = 'normal';
  301. let info = await ration_glj_facade.getInfoFromProjectGLJ(newGLJ,unitPriceFileId);
  302. newGLJ = ration_glj_facade.createNewRecord(info);
  303. newRationGLJList.push(newGLJ);
  304. rationGLJShowList.push(info);
  305. }
  306. let InfoFromProjectGLJ = +new Date();
  307. console.log("找到项目工料机时间-------------------------------"+(InfoFromProjectGLJ - std_gljTime));
  308. }
  309. }
  310. let before = +new Date();
  311. console.log("总查询时间为-------------------------------"+(before-first));
  312. if(newRationGLJList.length>0){
  313. await ration_glj.insertMany(newRationGLJList);
  314. }
  315. let after = +new Date();
  316. console.log("实际插入时间为-------------------------------"+(after-before));
  317. console.log("总操作时间为-------------------------------"+(after-first));
  318. return rationGLJShowList;
  319. }
  320. async function deleRationSubRecode(projectID,rationID) {//删除挂在定额下的数据,如工程量明细,定额工料机等
  321. let delete_query={projectID: projectID, rationID: rationID};
  322. //删除工程量明细
  323. await quantity_detail.deleteByQuery(delete_query) ;
  324. await ration_coe.deleteMany(delete_query);//删除附注条件
  325. await ration_glj.deleteMany(delete_query);//删除定额工料机
  326. await rationInstallationModel.deleteMany(delete_query);//删除安装增加费
  327. }
  328. async function updateRation(std,firstLibID,rationID,billsItemID,projectID,calQuantity) {
  329. // insertNewRation
  330. let ration ={};
  331. ration.code = std.code;
  332. ration.name = std.name;
  333. ration.caption = std.caption;
  334. ration.unit = std.unit;
  335. ration.libID = std.rationRepId;
  336. ration.content = std.jobContent;
  337. ration.adjustState = '';
  338. ration.isFromDetail=0;
  339. ration.isSubcontract=false;
  340. ration.fees=[];
  341. if (std.chapter) {
  342. ration.comments = std.chapter.explanation;
  343. ration.ruleText = std.chapter.ruleText;
  344. }
  345. ration.from = std.type === 'complementary' ? 'cpt' : 'std';
  346. //定额前缀 none:0, complementary:1, borrow: 2
  347. ration.prefix = '';
  348. //借用优先级比补充高
  349. if(std.rationRepId !== parseInt(firstLibID)){//借用
  350. ration.prefix = '借';
  351. }
  352. else if(std.rationRepId === firstLibID && ration.from === 'cpt') {
  353. ration.prefix = '补';
  354. }
  355. if(std.feeType == undefined || std.feeType == null || std.feeType ==''){//定额取费专业为空的情况下,取项目属性中的定额取费专业ID
  356. ration.programID = await getProgramForProject(projectID);
  357. }else {
  358. ration.programID = std.feeType;
  359. }
  360. ration.rationAssList = createRationAss(std);//生成辅助定额
  361. if(calQuantity){
  362. await CalculateQuantity(ration,billsItemID,projectID);
  363. }
  364. let unsetObject = {
  365. "marketUnitFee":1,
  366. 'marketTotalFee':1,
  367. "maskName":1
  368. }
  369. let newRation = await ration_model.model.findOneAndUpdate({ID:rationID,projectID:projectID},{"$set":ration,"$unset":unsetObject},{new: true});//;
  370. return newRation;
  371. }
  372. async function setEmptyRation(projectID,rationID){
  373. let ration ={};
  374. ration.code = "";
  375. ration.name = "";
  376. ration.caption = "";
  377. ration.unit = "";
  378. ration.libID = null;
  379. ration.content = "";
  380. ration.adjustState = '';
  381. ration.isFromDetail=0;
  382. ration.isSubcontract=false;
  383. ration.fees=[];
  384. ration.comments = "";
  385. ration.ruleText = "";
  386. ration.quantity="";
  387. ration.contain="";
  388. ration.quantityEXP="";
  389. ration.from = 'std';
  390. //定额前缀 none:0, complementary:1, borrow: 2
  391. ration.prefix = '';
  392. ration.rationAssList = [];
  393. ration.marketUnitFee ="";
  394. ration.marketTotalFee ="";
  395. ration.maskName = "";
  396. ration.targetTotalFee ='';
  397. ration.targetUnitFee = "";
  398. ration.deleteInfo = null;
  399. ration.quantityCoe = {};
  400. ration.rationQuantityCoe="";
  401. ration.tenderQuantity = "";
  402. ration.programID = null;
  403. let newRation = await ration_model.model.findOneAndUpdate({ID:rationID,projectID:projectID},{"$set":ration},{new: true});//;
  404. return {ration:newRation,ration_gljs:[],ration_coes:[],ration_installs:[]};
  405. }
  406. function createRationAss(std) {
  407. let rationAssList = [];//生成辅助定额
  408. if(std.hasOwnProperty('rationAssList')&&std.rationAssList.length>0){
  409. for(let i=0;i<std.rationAssList.length;i++){
  410. let ass = std.rationAssList[i];
  411. ass.actualValue = ass.stdValue;
  412. rationAssList.push(ass);
  413. }
  414. }
  415. return rationAssList;
  416. }
  417. async function CalculateQuantity (ration,billsItemID,projectID) {
  418. // calculate ration Quantity
  419. let project = await projectModel.findOne({ID:projectID});
  420. let decimalObject =await decimal_facade.getProjectDecimal(projectID,project);
  421. let quantity_decimal = (decimalObject&&decimalObject.ration&&decimalObject.ration.quantity)?decimalObject.ration.quantity:3;
  422. let pbill = await bill_model.model.findOne({projectID:projectID,ID:billsItemID});
  423. let billsQuantity = pbill.quantity ? pbill.quantity : 0;
  424. let bill_decimal = await decimal_facade.getBillsQuantityDecimal(projectID,pbill.unit,project);
  425. billsQuantity=scMathUtil.roundForObj(billsQuantity,bill_decimal);
  426. ration.quantityEXP="QDL";
  427. ration.quantity = scMathUtil.roundForObj(billsQuantity / FilterNumberFromUnit(ration.unit),quantity_decimal);//不管是否打勾都做转换
  428. ration.contain = scMathUtil.roundForObj(ration.quantity/billsQuantity,6);
  429. };
  430. async function getProgramForProject(projectID){
  431. let project = await projectModel.findOne({ID:projectID});
  432. return project.property.engineering;
  433. }
  434. function FilterNumberFromUnit (unit) {
  435. let reg = new RegExp('^[0-9]+');
  436. if (reg.test(unit)) {
  437. return parseInt(unit.match(reg)[0]);
  438. } else {
  439. return 1;
  440. }
  441. };