ration_glj_facade.js 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069
  1. /**
  2. * Created by chen on 2017/6/29.
  3. */
  4. let mongoose = require('mongoose');
  5. const uuidV1 = require('uuid/v1');
  6. let consts = require('../../main/models/project_consts')
  7. let commonConsts = consts.commonConst;
  8. let _ = require("lodash");
  9. let ration_glj = mongoose.model('ration_glj');
  10. import GLJListModel from '../../glj/models/glj_list_model';
  11. let std_glj_lib_gljList_model = mongoose.model('std_glj_lib_gljList');
  12. let async_n = require("async");
  13. let ration = mongoose.model('ration');
  14. let ration_coe_facade = require('./ration_coe_facade');
  15. let ration_coe = mongoose.model('ration_coe');
  16. let std_ration_lib_ration_items = mongoose.model('std_ration_lib_ration_items');
  17. let glj_calculate_facade = require('./glj_calculate_facade');
  18. let glj_type_util = require('../../../public/cache/std_glj_type_util');
  19. let quantity_detail_facade = require('../../main/facade/quantity_detail_facade');
  20. let ration_installation_facade = require('../../main/facade/ration_installation_facade');
  21. let logger = require("../../../logs/log_helper").logger;
  22. import stdgljutil from "../../../public/cache/std_glj_type_util";
  23. import EngineeringLibModel from "../../users/models/engineering_lib_model";
  24. import GljDao from "../../complementary_glj_lib/models/gljModel";
  25. const complementaryGljModel = mongoose.model('complementary_glj_lib');
  26. const stdGljModel = mongoose.model('std_glj_lib_gljList');
  27. const gljClassModel = mongoose.model('std_glj_lib_gljClass');
  28. const projectDao = require('../../pm/models/project_model').project;
  29. const compleClassModel = mongoose.model('complementary_glj_section');
  30. let gljUtil = require('../../../public/gljUtil');
  31. module.exports = {
  32. save: save,
  33. getData: getData,
  34. deleteByRation: deleteByRation,
  35. getQuantityByProjectGLJ: getQuantityByProjectGLJ,
  36. getLibInfo: getLibInfo,
  37. getGLJData: getGLJData,
  38. getGLJDataByCodes:getGLJDataByCodes,
  39. addGLJ: addGLJ,
  40. deleteRationGLJ:deleteRationGLJ,
  41. deleteGLJ:deleteGLJ,
  42. insertAddTypeGLJ:insertAddTypeGLJ,
  43. replaceGLJ: replaceGLJ,
  44. replaceGLJByData:replaceGLJByData,
  45. mReplaceGLJ: mReplaceGLJ,
  46. updateRationGLJByEdit: updateRationGLJByEdit,
  47. getGLJClass: getGLJClass,
  48. insertGLJAsRation: insertGLJAsRation,
  49. getRationTypeGLJQuantity:getRationTypeGLJQuantity,
  50. getInfoFromProjectGLJ:getInfoFromProjectGLJ,
  51. createNewRecord:createNewRecord,
  52. getGLJSearchInfo:getGLJSearchInfo,
  53. updateRationGLJFromDoc:updateRationGLJFromDoc,
  54. getGLJLibByEngineerID:getGLJLibByEngineerID,
  55. prepareExtData:prepareExtData
  56. }
  57. let operationMap = {
  58. 'ut_create': create_ration_glj,
  59. 'ut_update': update_ration_glj,
  60. 'ut_delete': delete_ration_glj
  61. };
  62. let updateFunctionMap = {
  63. 'normalUpdate': normalUpdate
  64. };
  65. /**
  66. * 根据项目工料机ID和项目ID取消耗量
  67. *
  68. * @param {object} condition
  69. * @return Array
  70. */
  71. async function getQuantityByProjectGLJ(condition) {
  72. let query = {
  73. 'projectID': condition.projectID,
  74. };
  75. if(condition.projectGLJIDList){
  76. query['projectGLJID'] = {$in: condition.projectGLJIDList};
  77. }
  78. let startTime = +new Date();
  79. let results = await ration_glj.find(query, ['projectGLJID', 'quantity', 'rationID'], {sort: {projectGLJID: 1}});
  80. let rationList = _.uniq(_.map(results, 'rationID'));
  81. let getQuantity = +new Date();
  82. console.log("取工料机消耗量时间-----"+(getQuantity - startTime));
  83. let rationQuery = {
  84. 'projectID': condition.projectID,
  85. 'ID': {$in: rationList},
  86. 'deleteInfo': null
  87. };
  88. /* $and: [
  89. {'projectID': condition.projectID},
  90. {'ID': {$in: rationList}},
  91. {'deleteInfo': null}
  92. ]*/
  93. let rations = await ration.find(rationQuery, ['ID', 'quantity']);
  94. let rationsTime = +new Date();
  95. console.log("取定额消耗量时间-----"+(rationsTime - getQuantity));
  96. return combineQuantity(results, rations);
  97. }
  98. function combineQuantity(results, rations) {
  99. let resultList = [];
  100. let rationMap = _.indexBy(rations,'ID');
  101. for(let r of results){
  102. let tmp = {
  103. projectGLJID: r.projectGLJID,
  104. quantity: Number(r.quantity)
  105. }
  106. let ration = rationMap[r.rationID];//_.find(rations, {ID: r.rationID})
  107. if (ration) {
  108. tmp.rationID = ration.ID;
  109. tmp.rationQuantity = ration.quantity ? Number(ration.quantity) : undefined;
  110. }
  111. resultList.push(tmp);
  112. }
  113. return resultList;
  114. return resultList;
  115. }
  116. function get_lib_glj_info(ration_glj) {
  117. return function (result, cb) {
  118. std_glj_lib_gljList_model.findOne({'ID': ration_glj.GLJID}, (err, glj) => {
  119. if (err) {
  120. cb(err, '')
  121. } else if (glj) {
  122. ration_glj.name = glj.name;
  123. ration_glj.code = glj.code;
  124. ration_glj.original_code = glj.code;
  125. ration_glj.unit = glj.unit;
  126. ration_glj.specs = glj.specs;
  127. ration_glj.basePrice = glj.basePrice;
  128. ration_glj.marketPrice = glj.basePrice;
  129. ration_glj.shortName = glj.shortName;
  130. ration_glj.type = glj.gljType;
  131. ration_glj.repositoryId = glj.repositoryId;
  132. ration_glj.adjCoe = glj.adjCoe;
  133. getInfoFromProjectGLJ(ration_glj).then(function (info) {
  134. if (info) {
  135. let tem = {};
  136. tem.newRecode = createNewRecord(info);
  137. tem.showData = info;
  138. result.datas.push(tem);
  139. cb(null, result);
  140. } else {
  141. cb(new Error('get project glj error'), null);
  142. }
  143. });
  144. } else {
  145. cb(null, result);
  146. }
  147. })
  148. }
  149. }
  150. function createNewRecord(ration_glj) {
  151. let newRecoed = {};
  152. newRecoed.ID = ration_glj.ID;
  153. newRecoed.projectID = ration_glj.projectID;
  154. newRecoed.GLJID = ration_glj.GLJID;
  155. newRecoed.rationID = ration_glj.rationID;
  156. newRecoed.rationItemQuantity = ration_glj.rationItemQuantity;
  157. newRecoed.customQuantity = ration_glj.customQuantity;
  158. newRecoed.quantity = ration_glj.quantity;
  159. newRecoed.name = ration_glj.name;
  160. newRecoed.code = ration_glj.code;
  161. newRecoed.original_code = ration_glj.original_code;
  162. newRecoed.unit = ration_glj.unit;
  163. newRecoed.specs = ration_glj.specs;
  164. newRecoed.from = ration_glj.from ? ration_glj.from : 'std';
  165. newRecoed.createType = ration_glj.createType ? ration_glj.createType : 'normal';
  166. newRecoed.shortName = ration_glj.shortName;
  167. newRecoed.billsItemID = ration_glj.billsItemID;
  168. newRecoed.type = ration_glj.type;
  169. newRecoed.model = ration_glj.model;
  170. newRecoed.repositoryId = ration_glj.repositoryId;
  171. newRecoed.projectGLJID = ration_glj.projectGLJID;
  172. newRecoed.adjCoe = ration_glj.adjCoe;
  173. return newRecoed
  174. }
  175. async function getInfoFromProjectGLJ(ration_glj,unitPriceFileId,ext) {
  176. let data = getGLJSearchInfo(ration_glj);
  177. try {
  178. let projectGljModel = new GLJListModel();
  179. let result = await projectGljModel.addList(data,unitPriceFileId,ext);
  180. let typeString = result.type+"";
  181. ration_glj.marketPrice = result.unit_price.market_price;
  182. ration_glj.adjustPrice = result.unit_price.base_price;
  183. ration_glj.basePrice = result.unit_price.base_price;
  184. ration_glj.projectGLJID = result.id;
  185. if (typeString.startsWith("2")||typeString=='4'||typeString=='5') {//只有材料类型才显示是否暂估
  186. ration_glj.isEstimate = result.is_evaluate;
  187. }
  188. if (result.hasOwnProperty('subList') && result.subList.length > 0) {
  189. ration_glj.subList = getMixRatioShowDatas(result.subList);
  190. }
  191. return ration_glj;
  192. } catch (err) {
  193. logger.err(err);
  194. return null;
  195. }
  196. }
  197. function getMixRatioShowDatas(subList) {
  198. var temRationGLJs = [];
  199. for (let pg of subList) {
  200. var tem = {
  201. projectGLJID: pg.id,
  202. code: pg.code,
  203. name: pg.name,
  204. specs: pg.specs,
  205. unit: pg.unit,
  206. shortName: pg.unit_price.short_name,
  207. rationItemQuantity: pg.ratio_data.consumption,
  208. basePrice: pg.unit_price.base_price,
  209. marketPrice: pg.unit_price.market_price,
  210. adjustPrice: pg.adjust_price,
  211. isEstimate: pg.is_evaluate,
  212. isMixRatio: true,
  213. isAdd: pg.unit_price.is_add,
  214. GLJID: pg.glj_id
  215. }
  216. temRationGLJs.push(tem);
  217. }
  218. temRationGLJs = _.sortBy(temRationGLJs, 'code');
  219. return temRationGLJs;
  220. }
  221. function create_ration_glj(user_id, datas) {
  222. return function (callback) {
  223. let ration_glj_list = datas.ration_glj_list;
  224. var tasks = [];
  225. tasks.push(startingTask("get glj info"))
  226. for (let i = 0; i < ration_glj_list.length; i++) {
  227. ration_glj_list[i].ID = uuidV1();
  228. tasks.push(get_lib_glj_info(ration_glj_list[i]))
  229. }
  230. async_n.waterfall(tasks, (err, results) => {
  231. if (err) {
  232. callback(err, results)
  233. } else {
  234. let newRecords = [];
  235. let showDatas = [];
  236. for (let r of results.datas) {
  237. if (r) {
  238. newRecords.push(r.newRecode);
  239. showDatas.push(r.showData);
  240. }
  241. }
  242. if (newRecords.length > 0) {
  243. ration_glj.insertMany(newRecords, (err, doc) => {
  244. if (err) {
  245. callback(err, null);
  246. } else {
  247. let returndata = {
  248. updateTpye: commonConsts.UT_CREATE,
  249. moduleName: 'ration_glj',
  250. data: {
  251. newRecords: newRecords,
  252. showDatas: showDatas
  253. }
  254. }
  255. callback(null, returndata)
  256. }
  257. });
  258. } else {
  259. logger.info("can't find gljs")
  260. callback(null, null)
  261. }
  262. }
  263. })
  264. }
  265. }
  266. function update_ration_glj(user_id, datas) {
  267. if (datas.updateFunction) {
  268. return updateFunctionMap[datas.updateFunction](user_id, datas);
  269. } else {
  270. return normalUpdate(user_id, datas);
  271. }
  272. }
  273. function normalUpdate(user_id, datas) {
  274. return function (callback) {
  275. ration_glj.update(datas.query, datas.doc, (err, result) => {
  276. if (err) {
  277. callback(err, '');
  278. } else {
  279. let returndata = {
  280. moduleName: 'ration_glj',
  281. data: {
  282. updateTpye: commonConsts.UT_UPDATE,
  283. query: datas.query,
  284. doc: datas.doc
  285. }
  286. }
  287. callback(null, returndata)
  288. }
  289. })
  290. }
  291. }
  292. async function doCustomQuantityUpdate(datas) {
  293. let result = await ration_glj.findOneAndUpdate(datas.query, datas.doc);
  294. let cal_result = await glj_calculate_facade.calculateQuantity({
  295. projectID: datas.query.projectID,
  296. rationID: datas.query.rationID
  297. });
  298. cal_result.glj_result.forEach(function (item) {
  299. if (!item.doc.hasOwnProperty('customQuantity')) {
  300. item.doc.customQuantity = null;
  301. }
  302. });
  303. return cal_result;
  304. }
  305. function delete_ration_glj(user_id, datas) {
  306. return function (callback) {
  307. deleteByID(datas, callback);
  308. //callback(new Error("删除子数据失败!"),null)
  309. //这个方法已经不用,先注释,稳定后再删除
  310. /* if (datas.deleteType == "RATION") {
  311. deleteByRation(datas, callback);
  312. } else if (datas.deleteType == "BILL") {
  313. deleteByBill(user_id, datas, callback);
  314. } else {
  315. deleteByID(datas, callback);
  316. }*/
  317. }
  318. }
  319. function deleteByRation(datas, callback) {
  320. let data = datas.updateData;
  321. let tasks = [];
  322. tasks.push(deleteGLJList(data));
  323. tasks.push(ration_coe_facade.delete_ration_coe(data));
  324. tasks.push(quantity_detail_facade.deleteByRation(data));
  325. tasks.push(ration_installation_facade.deleteByRation(data));
  326. async_n.parallel(tasks, function (err, result) {
  327. commonCallback(callback, result, err)
  328. })
  329. }
  330. function deleteGLJList(data) {
  331. return function (callback) {
  332. ration_glj.deleteMany({projectID: data.projectID, rationID: data.ID}, (err, result) => {
  333. commonCallback(callback, result, err)
  334. });
  335. }
  336. }
  337. function deleteByBill(user_id, datas, callback) {
  338. let tasks = [];
  339. tasks.push(startingTask("deleteByBill"));
  340. tasks.push(getRationsByBill(datas));
  341. tasks.push(deleteRationsbyBill(user_id, datas));
  342. tasks.push(deleteByMultiRations(datas));
  343. async_n.waterfall(tasks, function (err, results) {
  344. if (err) {
  345. callback(err, '');
  346. } else {
  347. callback(null, results);
  348. }
  349. })
  350. }
  351. function deleteByID(datas, callback) {
  352. deleteAndUpdateState(datas).then(function (result) {
  353. if (result.err) {
  354. callback(result.err, '');
  355. } else {
  356. let returndata = {
  357. moduleName: 'ration_glj',
  358. data: {
  359. updateTpye: commonConsts.UT_DELETE,
  360. query: datas.query,
  361. adjustState: result.adjustState
  362. }
  363. }
  364. callback(null, returndata)
  365. }
  366. })
  367. }
  368. async function deleteGLJ(IDs) {
  369. await ration_glj.deleteMany({'ID': {$in: IDs}});
  370. }
  371. async function deleteAndUpdateState(datas) {
  372. let result = {
  373. err: null
  374. }
  375. try {
  376. await ration_glj.deleteOne(datas.query);
  377. let stateResult = await glj_calculate_facade.calculateQuantity({
  378. projectID: datas.query.projectID,
  379. rationID: datas.doc.rationID
  380. });
  381. result.adjustState = stateResult.adjustState;
  382. } catch (err) {
  383. result.err = err;
  384. }
  385. return result;
  386. }
  387. function startingTask(processName) {
  388. return function (asyncCallBack) {
  389. var result = {
  390. processName: processName,
  391. datas: []
  392. };
  393. asyncCallBack(null, result);
  394. };
  395. }
  396. function getRationsByBill(datas) {
  397. return function (results, callback) {
  398. ration.find({
  399. projectID: datas.updateData.projectID,
  400. billsItemID: datas.updateData.ID
  401. }, function (err, rations) {
  402. if (err) {
  403. callback(err, '')
  404. } else {
  405. results.rations = rations;
  406. callback(null, results)
  407. }
  408. })
  409. }
  410. }
  411. function deleteRationsbyBill(user_id, datas) {
  412. return function (results, callback) {
  413. let deleteInfo = {
  414. deleteInfo: {deleted: true, deleteDateTime: new Date(), deleteBy: user_id}
  415. };
  416. ration.update({
  417. projectID: datas.updateData.projectID,
  418. billsItemID: datas.updateData.ID
  419. }, deleteInfo, {multi: true}, (err, deleteresults) => {
  420. if (err) {
  421. callback(err, '');
  422. } else {
  423. callback(null, results);
  424. }
  425. });
  426. }
  427. }
  428. function deleteByMultiRations(datas) {
  429. return function (results, deleteCallBack) {
  430. var delete_tasks = [];
  431. var deleteOne = function (ration) {
  432. return function (callback) {
  433. ration_glj.deleteMany({projectID: ration.projectID, rationID: ration.ID}, function (err, result) {
  434. commonCallback(callback, result, err)
  435. });
  436. }
  437. }
  438. let rations = results.rations;
  439. for (let i = 0; i < rations.length; i++) {
  440. delete_tasks.push(deleteOne(rations[i]._doc));
  441. delete_tasks.push(ration_coe_facade.delete_ration_coe(rations[i]._doc));
  442. delete_tasks.push(quantity_detail_facade.deleteByRation(rations[i]._doc));
  443. delete_tasks.push(ration_installation_facade.deleteByRation(rations[i]._doc));
  444. }
  445. delete_tasks.push(quantity_detail_facade.deleteByBill(datas.updateData));
  446. async_n.parallel(delete_tasks, (err, results) => {
  447. if (err) {
  448. deleteCallBack(err, '')
  449. } else {
  450. deleteCallBack(null, results)
  451. }
  452. })
  453. }
  454. }
  455. /*
  456. function deleteByRation(doc) {
  457. return function (callback){
  458. ration_glj.deleteMany({projectID: doc.updateData.projectID, rationID: doc.updateData.ID},callback);
  459. }
  460. }
  461. */
  462. function save(user_id, datas, callback) {
  463. let operations = [];
  464. if (_.isArray(datas)) {
  465. for (let i = 0; i < datas.length; i++) {
  466. operations.push(operationMap[datas[i].updateType](user_id, datas[i]));
  467. }
  468. } else {
  469. operations.push(operationMap[datas.updateType](user_id, datas));
  470. }
  471. async_n.parallel(operations, function (err, results) {
  472. if (err) {
  473. callback(err, '');
  474. } else {
  475. if (results.length == 1) {
  476. callback(null, results[0])
  477. } else {
  478. callback(null, results)
  479. }
  480. }
  481. })
  482. }
  483. async function getLibInfo(req) {
  484. let gljLibId = null, engineerID, sessionCompilation = req.session.sessionCompilation;
  485. engineerID = req.params.engineerID;
  486. if(engineerID){
  487. gljLibId = await getGLJLibByEngineerID(engineerID);
  488. }else {
  489. throw new Error("工程专业ID为空!");
  490. }
  491. let data = {
  492. userID: req.session.sessionUser.id,
  493. gljLibId: gljLibId,
  494. compilationId: sessionCompilation._id
  495. };
  496. return data;
  497. }
  498. async function getGLJLibByEngineerID (engineerID) {
  499. let engineeringLibModel = new EngineeringLibModel() ;
  500. let engineeringInfo = await engineeringLibModel.findDataByCondition({'_id': engineerID});
  501. let gljLibId = engineeringInfo.glj_lib.length > 0 && typeof engineeringInfo.glj_lib !== 'undefined' ? engineeringInfo.glj_lib[0].id : null;
  502. return gljLibId
  503. }
  504. function getGLJData(info, callback) {
  505. let gljDao = new GljDao();
  506. let datas = {};
  507. let gljDistTypeCache = stdgljutil.getStdGljTypeCacheObj().toArray();
  508. datas.distTypeTree = gljDistTypeCache;
  509. async_n.parallel([
  510. async function (cb) {
  511. try {
  512. datas.treeData = await gljDao.getMixedTree(info.gljLibId, info.userID, info.compilationId);
  513. cb(null);
  514. } catch (err) {
  515. cb(err);
  516. }
  517. },
  518. function (cb) {
  519. gljDao.getGljItems(info.gljLibId, info.userID, info.compilationId, function (err, data) {
  520. if (err) {
  521. cb(err);
  522. } else {
  523. datas.stdGLJ = data.stdGljs;
  524. datas.complementaryGLJs = data.complementaryGljs;
  525. cb(null);
  526. }
  527. });
  528. }
  529. ], function (err) {
  530. if (err) {
  531. callback(true, null);
  532. }
  533. else {
  534. callback(false, datas);
  535. }
  536. })
  537. }
  538. function getGLJSearchInfo(ration_glj) {
  539. let data = {
  540. glj_id: ration_glj.GLJID,
  541. project_id: ration_glj.projectID,
  542. code: ration_glj.code,
  543. original_code: ration_glj.original_code,
  544. name: ration_glj.name,
  545. //shortName: ration_glj.shortName,
  546. specs: ration_glj.specs,
  547. unit: ration_glj.unit,
  548. type: ration_glj.subType ? ration_glj.subType : ration_glj.type,//如果有subType,则是通过插入定额级的工料机进来的
  549. model: ration_glj.model,
  550. type_of_work: ration_glj.subType ? ration_glj.subType : ration_glj.type,
  551. base_price: ration_glj.basePrice,
  552. market_price: ration_glj.marketPrice,
  553. repositoryId: ration_glj.repositoryId,
  554. adjCoe: ration_glj.adjCoe,
  555. materialType:ration_glj.materialType,
  556. materialCoe:ration_glj.materialCoe,
  557. grossWeightCoe:ration_glj.grossWeightCoe,
  558. purchaseStorageRate:ration_glj.purchaseStorageRate,
  559. offSiteTransportLossRate:ration_glj.offSiteTransportLossRate,
  560. handlingLossRate:ration_glj.handlingLossRate,
  561. from: ration_glj.from ? ration_glj.from : 'std'//std:标准工料机库, cpt:补充工料机库
  562. };
  563. let glj_type_object = glj_type_util.getStdGljTypeCacheObj();
  564. let type = glj_type_object.getItemById(data.type);
  565. data.shortName = type.shortName;
  566. if (data.from == 'cpt') {//从补充工料机来的数据即为新增数据
  567. data.is_add = 1;
  568. }
  569. return data;
  570. }
  571. async function prepareExtData(projectID,compilation) {
  572. let ext , unitFileId ;
  573. let property = await projectDao.getProjectProperty(projectID);
  574. ext = projectDao.getExtendData(property,compilation);
  575. unitFileId = property.unitPriceFile !== undefined ? property.unitPriceFile.id : 0;
  576. return [unitFileId,ext];
  577. }
  578. async function addGLJ(rgList,compilation) {
  579. if (rgList.length <= 0) return {};
  580. let newRecodes = await insertAddTypeGLJ(rgList,compilation);
  581. let stateResult = await glj_calculate_facade.calculateQuantity({
  582. projectID: rgList[0].projectID,
  583. rationID: rgList[0].rationID
  584. });
  585. let result = {
  586. newRecodes: newRecodes,
  587. showData: rgList,
  588. adjustState: stateResult.adjustState
  589. };
  590. return result;
  591. }
  592. async function insertAddTypeGLJ(rgList,compilation) {
  593. let newRecodes = [],GLJMap=null;
  594. let [unitFileId,ext] = await prepareExtData(rgList[0].projectID,compilation);
  595. for (let g of rgList) {
  596. let projectGljModel = new GLJListModel();
  597. let result = await projectGljModel.addList(getGLJSearchInfo(g),unitFileId,ext);
  598. let typeString = result.type+'';
  599. g.marketPrice = result.unit_price.market_price;
  600. g.adjustPrice = result.unit_price.base_price;
  601. g.basePrice = result.unit_price.base_price;
  602. g.isAdd = result.unit_price.is_add;
  603. g.projectGLJID = result.id;
  604. if (typeString.startsWith("2")||typeString=='4'||typeString=='5') {//只有材料类型才显示是否暂估
  605. g.isEstimate = result.is_evaluate;
  606. }
  607. g.ID = uuidV1();
  608. if (result.hasOwnProperty('subList') && result.subList.length > 0) {
  609. g.subList = getMixRatioShowDatas(result.subList);
  610. //对于混凝土,砂浆,配合比,组成物还要插入定额工料机
  611. if(gljUtil.isConcreteType(g.type)){
  612. if(GLJMap == null){
  613. let oldGLJList = await ration_glj.find({'rationID':g.rationID});
  614. GLJMap = _.indexBy(oldGLJList,"projectGLJID");
  615. }
  616. addMixRatioToRationGLJ(g,result.subList,newRecodes,GLJMap);
  617. }
  618. }
  619. newRecodes.push(createNewRecord(g));
  620. }
  621. await ration_glj.insertMany(newRecodes);
  622. return newRecodes;
  623. }
  624. async function deleteRationGLJ(data){
  625. let deleteIDs = [data.ID];
  626. if(gljUtil.isConcreteType(data.type)){//如果是混凝土、砂浆、配合比,还要删除没有被引用的组成物工料机
  627. let projectGljModel = new GLJListModel();
  628. let rationGLJList = await ration_glj.find({'rationID':data.rationID});
  629. let unitFileId = await projectDao.getUnitPriceFileId(data.projectID);
  630. let projectGLJMap = {},referenceMap={};
  631. let deleteMix = [];
  632. for(let r of rationGLJList){
  633. projectGLJMap[r.projectGLJID] = r;
  634. if(gljUtil.isConcreteType(r.type)){
  635. if(r.ID == data.ID){//是要删除的工料机
  636. deleteMix = await projectGljModel.getCompositionGLJByData(r,unitFileId);
  637. }else {
  638. let comList = await projectGljModel.getCompositionGLJByData(r,unitFileId);
  639. for(let c of comList){
  640. referenceMap[c.id] = c;
  641. }
  642. }
  643. }
  644. }
  645. for(let d of deleteMix){
  646. //删除不属于其它的组成物并且定额消耗为0
  647. if(referenceMap[d.id]) continue;
  648. if(projectGLJMap[d.id]&&(projectGLJMap[d.id].rationItemQuantity == '0'||projectGLJMap[d.id].rationItemQuantity == 0)){
  649. deleteIDs.push(projectGLJMap[d.id].ID);
  650. }
  651. }
  652. await ration_glj.deleteMany({'ID': {"$in": deleteIDs}});
  653. } else{
  654. await ration_glj.deleteOne({ID:data.ID});
  655. }
  656. let calcResult = await glj_calculate_facade.calculateQuantity({
  657. projectID: data.projectID,
  658. rationID: data.rationID
  659. });
  660. calcResult.deleteList = deleteIDs;
  661. return calcResult;
  662. }
  663. function addMixRatioToRationGLJ(g,subList,newRecodes,GLJMap){
  664. let newMap = {};
  665. for(let mr of subList ){
  666. //先查找该定额下是否已经有了工料机了,有就不用再插入了
  667. newMap[mr.id] = mr;//新增的定额工料机映射表
  668. if(GLJMap[mr.id]||_.find(newRecodes,{'projectGLJID':mr.id})) continue;
  669. //没有的情况下,生成一条定额工料机计录
  670. let newMr = {
  671. projectID:g.projectID,
  672. GLJID:mr.glj_id,
  673. rationID:g.rationID,
  674. rationItemQuantity:0,
  675. quantity:0,
  676. name:mr.name,
  677. code:mr.code,
  678. original_code:mr.original_code,
  679. unit:mr.unit,
  680. specs:mr.specs,
  681. from:mr.from,
  682. createType:'add',
  683. shortName:mr.unit_price.short_name,
  684. billsItemID:g.billsItemID,
  685. type:mr.type,
  686. model:mr.model,
  687. repositoryId:g.repositoryId,
  688. projectGLJID:mr.id,
  689. adjCoe:mr.adjCoe
  690. };
  691. newMr.ID = uuidV1();
  692. newRecodes.push(newMr);
  693. }
  694. return newMap;
  695. }
  696. async function replaceGLJByData(data,compilation) {
  697. let projectGljModel = new GLJListModel(),newRecodes=[],deleteList=[];
  698. let [unitFileId,ext] = await prepareExtData(data.projectID,compilation);
  699. let result = await projectGljModel.addList(getGLJSearchInfo(data),unitFileId,ext);
  700. data.projectGLJID = result.id;
  701. if(data.toCommercial == true){//从混凝土改成商品混凝土,
  702. let [contype,newR] = await concreteTypeToCommercial(data);
  703. newRecodes.push(newR);
  704. data=contype;
  705. }else {
  706. let [newList,tdelList] = await replaceMixRatio(data,result,unitFileId);
  707. newRecodes = newList;
  708. deleteList = tdelList;
  709. let updateResult = await ration_glj.findOneAndUpdate({ID: data.ID, projectID: data.projectID}, data);//更新定额工料机
  710. }
  711. return {data:data,newRecodes:newRecodes,deleteList:deleteList};
  712. }
  713. async function concreteTypeToCommercial(data) {
  714. //旧的自定义消耗量改为0
  715. let contype = await ration_glj.findOneAndUpdate({ID: data.originalID}, {customQuantity:'0'});
  716. //因为商品混凝土是没有组成物的,所以不用考虑组成物的情况
  717. let new_glj = createComercialConcreteData(data);
  718. await ration_glj.create(new_glj);
  719. return [contype,new_glj];
  720. }
  721. function createComercialConcreteData(data){
  722. data.ID = uuidV1();
  723. return createNewRecord(data);
  724. }
  725. async function replaceMixRatio(g,result,unitFileId){
  726. let newRecodes=[],deleteList = [];
  727. if(gljUtil.isConcreteType(g.type)||gljUtil.isCommercialConcreteType(g.type)){//混凝土大类,商品混凝土属于相同大类,替换前和替换后只判断一个就好了
  728. let IDMap = {}, projectGLJMap = {},referenceMap={},concreteList=[],newMap={};
  729. let projectGljModel = new GLJListModel();
  730. let rationGLJList = await ration_glj.find({'rationID':g.rationID});
  731. for(let r of rationGLJList){
  732. IDMap[r.ID] = r;
  733. projectGLJMap[r.projectGLJID] = r;
  734. if(gljUtil.isConcreteType(r.type)&&r.ID!=g.ID) concreteList.push(r) //除了本身,记录一下其它混凝土类型
  735. }
  736. if (result.hasOwnProperty('subList') && result.subList.length > 0){
  737. newMap = addMixRatioToRationGLJ(g,result.subList,newRecodes,projectGLJMap);//先生成要添加的工料机
  738. }
  739. let oldMixList = await projectGljModel.getCompositionGLJByData(IDMap[g.ID],unitFileId);
  740. for(let c of concreteList){//找出要删除的子定额工料机(没人引用,并且定额消耗量为0)
  741. let temList = await projectGljModel.getCompositionGLJByData(c,unitFileId);
  742. for(let t of temList){
  743. referenceMap[t.id] = t;
  744. }
  745. }
  746. for(let o of oldMixList){
  747. if(newMap[o.id]||referenceMap[o.id]) continue;//如果两个地方有一个存在,那么就不用删除
  748. //没有被其它地方引用并且定额消耗量为0,就删除对应的定额工料机
  749. if(projectGLJMap[o.id] && (projectGLJMap[o.id].rationItemQuantity == '0'||projectGLJMap[o.id].rationItemQuantity == 0)) deleteList.push(projectGLJMap[o.id].ID)
  750. }
  751. }
  752. if(deleteList.length > 0) await ration_glj.deleteMany({'ID': {"$in": deleteList}});//删除定额工料机
  753. if(newRecodes.length > 0) await ration_glj.insertMany(newRecodes);
  754. return [newRecodes,deleteList]
  755. }
  756. async function replaceGLJ(data,compilation) {
  757. let rdata = {};
  758. let r_result =await replaceGLJByData(data,compilation);
  759. data = r_result.data;
  760. let stateResult = await glj_calculate_facade.calculateQuantity({
  761. projectID: data.projectID,
  762. rationID: data.rationID
  763. }, null,true);
  764. rdata.data = data;
  765. rdata.adjustState = stateResult.adjustState;
  766. rdata.name = stateResult.rationName;
  767. rdata.newRecodes = r_result.newRecodes;
  768. rdata.deleteList = r_result.deleteList;
  769. rdata.glj_result = stateResult.glj_result;
  770. return rdata;
  771. }
  772. async function replaceMixRatioForMReplace(tasks,result,unitFileId) {
  773. let allNewRecodes = [],allDeleteList=[];
  774. for(let t of tasks){//要新增一条商品混凝土
  775. if(t.insertOne){
  776. t.insertOne.document.projectGLJID = result.id;
  777. t.insertOne.document = createComercialConcreteData(t.insertOne.document);
  778. allNewRecodes.push(t.insertOne.document);
  779. }else if(t.updateOne&&t.updateOne.update.isConcrete == true){//过滤掉只更新自定义消耗量的task
  780. let tem = _.cloneDeep(t.updateOne.update);
  781. tem.ID = t.updateOne.filter.ID;
  782. tem.rationID = t.updateOne.filter.rationID;
  783. delete t.updateOne.filter.rationID;
  784. delete t.updateOne.update.isConcrete;
  785. let [newRecodes,deleteList] = await replaceMixRatio(tem,result,unitFileId);
  786. allNewRecodes = allNewRecodes.concat(newRecodes);
  787. allDeleteList = allDeleteList.concat(deleteList);
  788. }
  789. }
  790. return {newRecodes:allNewRecodes,deleteList:allDeleteList}
  791. }
  792. async function mReplaceGLJ(data,compilation) {
  793. let mresult = {},mixResult = null,noNeedCal=true;
  794. let projectGljModel = new GLJListModel();
  795. let [unitFileId,ext] = await prepareExtData(data.doc.projectID,compilation);
  796. //
  797. let result = await projectGljModel.addList(getGLJSearchInfo(data.doc),unitFileId,ext);
  798. let typeString = result.type+'';
  799. let newDoc = {};
  800. newDoc.projectGLJID = result.id;
  801. let rationList = [];//await ration_glj.distinct('rationID', data.query);
  802. for(let t of data.tasks){
  803. if(t.updateOne){
  804. rationList.push(t.updateOne.filter.rationID);
  805. if(t.updateOne.update.code) t.updateOne.update.projectGLJID = result.id;//如果是不是只修改自定义消耗的task,更新项目工料机ID
  806. }
  807. }
  808. if(gljUtil.isConcreteType(result.unit_price.type)||gljUtil.isCommercialConcreteType(result.unit_price.type)) {
  809. mixResult = await replaceMixRatioForMReplace(data.tasks,result,unitFileId);
  810. noNeedCal = null;
  811. }
  812. await ration_glj.bulkWrite(data.tasks);
  813. let [stateList,glj_result] = await changAdjustState(data, rationList,noNeedCal);
  814. data.doc = newDoc;
  815. mresult.data = data;
  816. mresult.stateList = stateList;
  817. mresult.newRecodes = mixResult?mixResult.newRecodes:[];
  818. mresult.deleteList = mixResult?mixResult.deleteList:[];
  819. mresult.glj_result = glj_result;
  820. return mresult
  821. }
  822. async function updateRationGLJByEdit(data) {
  823. var doc = data.doc;
  824. var result;
  825. if (doc.hasOwnProperty('customQuantity')) {
  826. result = await doCustomQuantityUpdate(data)
  827. } else {
  828. result = await doRationGLJUpdate(data);
  829. }
  830. return result;
  831. }
  832. async function updateRationGLJFromDoc(rg,doc,priceInfo) {
  833. let gljListModel = new GLJListModel();
  834. let projectGLJ = getGLJSearchInfo(rg);
  835. for (let key in doc) {
  836. projectGLJ[key] = doc[key]
  837. }
  838. projectGLJ.base_price = priceInfo.base_price;
  839. projectGLJ.market_price = priceInfo.market_price;
  840. let projcetGLJ_n = await gljListModel.modifyGLJ(projectGLJ, rg);
  841. doc.code = projcetGLJ_n.code;
  842. doc.projectGLJID = projcetGLJ_n.id;
  843. if (projcetGLJ_n.unit_price.is_add == 1) {
  844. doc.createType = 'replace';
  845. doc.rcode = projcetGLJ_n.original_code;
  846. } else {
  847. doc.createType = 'normal';
  848. doc.rcode = '';
  849. }
  850. await ration_glj.findOneAndUpdate({ID:rg.ID}, doc);
  851. return [projcetGLJ_n,doc]
  852. }
  853. async function doRationGLJUpdate(data) {
  854. let resutl = {};
  855. let priceInfo = data.priceInfo;
  856. let rg = await ration_glj.findOne(data.query);
  857. let [projcetGLJ_n,doc] = await updateRationGLJFromDoc(rg,data.doc,priceInfo);
  858. //取价格
  859. let gljListModel = new GLJListModel();
  860. gljListModel.getGLJPrice(projcetGLJ_n);
  861. doc.basePrice = projcetGLJ_n.unit_price.base_price;
  862. doc.marketPrice = projcetGLJ_n.unit_price.market_price;
  863. doc.adjustPrice = projcetGLJ_n.adjust_price;
  864. doc.isAdd = projcetGLJ_n.unit_price.is_add;
  865. resutl.doc = doc;
  866. let stateResult = await glj_calculate_facade.calculateQuantity({
  867. projectID: data.query.projectID,
  868. rationID: data.query.rationID
  869. },null,true);
  870. resutl.adjustState = stateResult.adjustState;
  871. resutl.name = stateResult.rationName;
  872. return resutl;
  873. }
  874. async function getGLJClass(info, data) {
  875. let result = {
  876. exist: false
  877. }
  878. //检查补充工料机中是否已经存在一样的记录了
  879. let condition = {
  880. userId: info.userID,
  881. compilationId: info.compilationId,
  882. code: data.code,
  883. name: data.name,
  884. unit: data.unit,
  885. gljType: data.type,
  886. basePrice: data.basePrice
  887. }
  888. if (data.specs != null && data.specs != undefined && data.specs != '') {
  889. condition['specs'] = data.specs;
  890. }
  891. let glj = await complementaryGljModel.find(condition);
  892. if (glj.length > 0) { //如果已存在就直接返回,不用再新增了
  893. result.exist = true;
  894. return result
  895. }
  896. //查找工料机类型树
  897. let items = await compleClassModel.find({
  898. userId: info.userID,
  899. compilationId: info.compilationId
  900. });
  901. result.items = items;
  902. return result;
  903. }
  904. async function insertGLJAsRation(data,compilation) {
  905. let gljList = data.gljList;
  906. if (data.hasOwnProperty("selectedSerialNo")) { //如果需要,更新序列号。
  907. let query = {
  908. projectID: data.projectID,
  909. billsItemID: data.billsItemID,
  910. serialNo: {$gt: data.selectedSerialNo}
  911. }
  912. await ration.update(query, {$inc: {serialNo: gljList.length}}, {multi: true});
  913. }
  914. let [unitFileId,ext] = await prepareExtData(data.projectID,compilation);
  915. for (let glj of gljList) {
  916. let p_glj = getGLJSearchInfo(glj);
  917. let projectGljModel = new GLJListModel();
  918. let result = await projectGljModel.addList(p_glj,unitFileId,ext);//逐条添加到项目工料机
  919. let typeString = result.type+'';
  920. glj.marketPrice = result.unit_price.market_price;
  921. glj.adjustPrice = result.unit_price.base_price;
  922. glj.basePrice = result.unit_price.base_price;
  923. glj.isAdd = result.unit_price.is_add;
  924. glj.projectGLJID = result.id;
  925. if (typeString.startsWith("2")||typeString=='4'||typeString=='5') {//只有材料类型才显示是否暂估
  926. glj.isEstimate = result.is_evaluate;
  927. }
  928. }
  929. await ration.insertMany(gljList);
  930. return gljList;
  931. }
  932. async function getRationTypeGLJQuantity(projectID) {
  933. let rations = await ration.find({'projectID': projectID,'type':3,'deleteInfo': null}, ['ID', 'projectGLJID','quantity']);
  934. return rations;
  935. }
  936. async function changAdjustState(data, rationList,noNeedCal) {
  937. let stateList = [],glj_result=[];
  938. for (let r of rationList) {
  939. let stateResult = await glj_calculate_facade.calculateQuantity({
  940. projectID: data.query.projectID,
  941. rationID: r
  942. }, noNeedCal,true);
  943. if(stateResult){
  944. stateList.push({rationID: r, adjustState: stateResult.adjustState,name:stateResult.rationName});
  945. glj_result = glj_result.concat(stateResult.glj_result)
  946. }
  947. }
  948. return [stateList,glj_result];
  949. }
  950. async function getGLJDataByCodes(data,compilation) {
  951. let gljLibId = await getGLJLibByEngineerID(data.engineerID);
  952. let gljDatas = [];
  953. if(gljLibId){
  954. let stdList = await std_glj_lib_gljList_model.find({'repositoryId':gljLibId,code:{'$in':data.codes}});
  955. if(stdList.length > 0){
  956. let property = await projectDao.getProjectProperty(data.projectID);
  957. let ext = projectDao.getExtendData(property,compilation);//多单价处理
  958. for(let s of stdList){
  959. let tem = JSON.parse(JSON.stringify(s));
  960. if(ext && ext.priceField && tem && tem.priceProperty){
  961. tem.basePrice = tem.priceProperty[ext.priceField];
  962. }
  963. gljDatas.push(tem);
  964. }
  965. }
  966. }
  967. return gljDatas
  968. }
  969. async function testError() {
  970. throw new Error('test Error');
  971. }
  972. function getData(projectID, callback) {
  973. ration_glj.find({'projectID': projectID}, (err, datas) => {
  974. if (err) {
  975. callback(1, '', null);
  976. } else {
  977. callback(0, consts.projectConst.RATION_GLJ, datas);
  978. }
  979. })
  980. }
  981. function commonCallback(callback, result, err) {
  982. if (err) {
  983. callback(err, '');
  984. } else {
  985. callback(null, result);
  986. }
  987. }