ration_item.js 57 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475
  1. /**
  2. * Created by Tony on 2017/4/28.
  3. */
  4. const mongoose = require('mongoose');
  5. let async = require("async");
  6. let moment = require('moment');
  7. let counter = require('../../../public/counter/counter');
  8. let gljDao = require('./glj_repository');
  9. let rationRepositoryDao = require('./repository_map');
  10. const scMathUtil = require('../../../public/scMathUtil').getUtil();
  11. const rationItemModel = mongoose.model('std_ration_lib_ration_items');
  12. const _rationItemModelBackup = mongoose.model('std_ration_lib_ration_items');
  13. // const _rationItemModelBackup = mongoose.model('std_ration_lib_ration_items_backup');
  14. const stdCoeModel = mongoose.model('std_ration_lib_coe_list');
  15. const stdRationLibModel = mongoose.model('std_ration_lib_map');
  16. const stdRationSectionModel = mongoose.model('std_ration_lib_ration_chapter_trees');
  17. const compleRationModel = mongoose.model('complementary_ration_items');
  18. import STDGLJListModel from '../../std_glj_lib/models/gljModel';
  19. import InstallationDao from '../models/installation';
  20. const installationDao = new InstallationDao();
  21. import GljDao from "../../std_glj_lib/models/gljModel";
  22. const stdGljDao = new GljDao();
  23. import stdgljutil from "../../../public/cache/std_glj_type_util";
  24. const stdGLJItemModel = mongoose.model('std_glj_lib_gljList');
  25. var rationItemDAO = function () { };
  26. async function getIDMapping(counterName, data) {
  27. const counterInfo = await counter.counterDAO.getIDAfterCount(counterName, data.length);
  28. const maxID = +counterInfo.sequence_value;
  29. const IDMapping = {};
  30. data.forEach((item, index) => {
  31. IDMapping[item.ID] = maxID - (data.length - 1) + index;
  32. });
  33. return IDMapping;
  34. }
  35. // 拷贝分类树
  36. async function copyClassData(sourceLibID, targetLibID) {
  37. const sourceClassData = await stdRationSectionModel.find({ rationRepId: sourceLibID }, '-_id').lean();
  38. const IDMapping = await getIDMapping(counter.moduleName.rationTree, sourceClassData);
  39. const insertData = sourceClassData.map(item => ({
  40. ...item,
  41. rationRepId: targetLibID,
  42. ID: IDMapping[item.ID],
  43. ParentID: IDMapping[item.ParentID] || -1,
  44. NextSiblingID: IDMapping[item.NextSiblingID] || -1,
  45. }));
  46. if (insertData.length) {
  47. await stdRationSectionModel.insertMany(insertData);
  48. }
  49. return IDMapping;
  50. }
  51. // 拷贝子目换算
  52. async function copyCoeData(sourceLibID, targetLibID) {
  53. const sourceCoeData = await stdCoeModel.find({ libID: sourceLibID }, '-_id').lean();
  54. const IDMapping = await getIDMapping(counter.moduleName.coeList, sourceCoeData);
  55. const insertData = sourceCoeData.map(item => ({
  56. ...item,
  57. libID: targetLibID,
  58. ID: IDMapping[item.ID],
  59. }));
  60. if (insertData.length) {
  61. await stdCoeModel.insertMany(insertData);
  62. }
  63. return IDMapping;
  64. }
  65. // 拷贝定额库
  66. rationItemDAO.prototype.copyLib = async function (sourceLibID, targetLibID, sourceGLJLibID, targetGLJLibID) {
  67. const sourceRationData = await rationItemModel.find({ rationRepId: sourceLibID }, '-_id').lean();
  68. const rationIDMapping = await getIDMapping(counter.moduleName.rations, sourceRationData);
  69. const classIDMapping = await copyClassData(sourceLibID, targetLibID);
  70. const coeIDMapping = await copyCoeData(sourceLibID, targetLibID);
  71. const sourceGLJData = await stdGLJItemModel.find({ repositoryId: sourceGLJLibID }, '-_id code ID').lean();
  72. const sourceGLJCodeMapping = {};
  73. sourceGLJData.forEach(glj => sourceGLJCodeMapping[glj.code] = glj.ID);
  74. const targetGLJData = await stdGLJItemModel.find({ repositoryId: targetGLJLibID }, '-_id code ID').lean();
  75. // 旧ID-新ID映射
  76. const gljIDMapping = {};
  77. targetGLJData.forEach(glj => {
  78. const orgID = sourceGLJCodeMapping[glj.code];
  79. if (orgID) {
  80. gljIDMapping[orgID] = glj.ID;
  81. }
  82. });
  83. sourceRationData.forEach(ration => {
  84. ration.rationRepId = targetLibID;
  85. ration.ID = rationIDMapping[ration.ID];
  86. ration.sectionId = classIDMapping[ration.sectionId];
  87. ration.rationCoeList.forEach(coe => {
  88. coe.ID = coeIDMapping[coe.ID];
  89. });
  90. const rationGLJList = [];
  91. ration.rationGljList.forEach(rGLJ => {
  92. const newGLJID = gljIDMapping[rGLJ.gljId];
  93. if (newGLJID) {
  94. rGLJ.gljId = newGLJID;
  95. rationGLJList.push(rGLJ);
  96. }
  97. });
  98. ration.rationGljList = rationGLJList;
  99. });
  100. if (sourceRationData.length) {
  101. await rationItemModel.insertMany(sourceRationData);
  102. }
  103. }
  104. rationItemDAO.prototype.overwriteRationGLJList = async function (sourceLibID, targetLibID) {
  105. const rations = await _rationItemModelBackup.find({ rationRepId: sourceLibID }, 'ID code rationGljList').lean();
  106. const bulks = [];
  107. rations.forEach(ration => {
  108. if (ration.rationGljList && ration.rationGljList.length) {
  109. ration.rationGljList.forEach(rGLJ => {
  110. delete rGLJ.gljCode;
  111. });
  112. bulks.push({
  113. updateOne: {
  114. filter: { rationRepId: targetLibID, code: ration.code },
  115. update: { $set: { rationGljList: ration.rationGljList } }
  116. }
  117. })
  118. }
  119. });
  120. if (bulks) {
  121. await rationItemModel.bulkWrite(bulks);
  122. }
  123. }
  124. rationItemDAO.prototype.handleGLJCode = async function (rationLibID, gljLibID) {
  125. const rations = await _rationItemModelBackup.find({ rationRepId: rationLibID }, 'ID rationGljList').lean();
  126. const gljs = await stdGLJItemModel.find({ repositoryId: gljLibID }, 'ID code').lean();
  127. const gljMap = {};
  128. gljs.forEach(glj => gljMap[glj.ID] = glj.code);
  129. const bulks = [];
  130. rations.forEach(ration => {
  131. if (ration.rationGljList && ration.rationGljList.length) {
  132. ration.rationGljList.forEach(rGLJ => {
  133. rGLJ.gljCode = gljMap[rGLJ.gljId];
  134. });
  135. bulks.push({
  136. updateOne: {
  137. filter: { ID: ration.ID },
  138. update: { $set: { rationGljList: ration.rationGljList } }
  139. }
  140. })
  141. }
  142. });
  143. if (bulks.length) {
  144. await _rationItemModelBackup.bulkWrite(bulks);
  145. }
  146. }
  147. rationItemDAO.prototype.handleGLJCodeID = async function (rationLibID, gljLibID) {
  148. const rations = await _rationItemModelBackup.find({ rationRepId: rationLibID }, 'ID rationGljList').lean();
  149. const gljs = await stdGLJItemModel.find({ repositoryId: gljLibID }, 'ID code').lean();
  150. const gljMap = {};
  151. gljs.forEach(glj => gljMap[glj.code] = glj.ID);
  152. const bulks = [];
  153. rations.forEach(ration => {
  154. if (ration.rationGljList && ration.rationGljList.length) {
  155. ration.rationGljList.forEach(rGLJ => {
  156. rGLJ.gljId = gljMap[rGLJ.gljCode];
  157. });
  158. bulks.push({
  159. updateOne: {
  160. filter: { ID: ration.ID },
  161. update: { $set: { rationGljList: ration.rationGljList } }
  162. }
  163. })
  164. }
  165. });
  166. if (bulks.length) {
  167. await _rationItemModelBackup.bulkWrite(bulks);
  168. }
  169. }
  170. // 处理部颁数据
  171. rationItemDAO.prototype.handleBBData = async function (rationLibID, gljLibID) {
  172. const rations = await rationItemModel.find({ rationRepId: rationLibID }, '-_id code ID rationGljList').lean();
  173. const types = [202, 203]
  174. const gljs = await stdGLJItemModel.find({ repositoryId: gljLibID, gljType: { $in: types }, 'component.0': { $exists: true } }, '-_id ID component').lean();
  175. const gljIDMap = {};
  176. gljs.forEach(glj => gljIDMap[glj.ID] = glj);
  177. const updateData = [];
  178. const errorRange = 0.04;
  179. for (const ration of rations) {
  180. if (!ration.rationGljList) {
  181. continue;
  182. }
  183. const componentAmtMap = {};
  184. for (const rGLJ of ration.rationGljList) {
  185. const stdGLJ = gljIDMap[rGLJ.gljId];
  186. if (!stdGLJ) {
  187. continue;
  188. }
  189. for (const c of stdGLJ.component) {
  190. const amt = c.consumeAmt * rGLJ.consumeAmt;
  191. if (componentAmtMap[c.ID]) {
  192. componentAmtMap[c.ID] += amt;
  193. } else {
  194. componentAmtMap[c.ID] = amt;
  195. }
  196. }
  197. }
  198. const newRationGljList = [];
  199. let isChanged = false;
  200. for (let i = 0; i < ration.rationGljList.length; i++) {
  201. const rGLJ = ration.rationGljList[i];
  202. if (rGLJ) {
  203. }
  204. if (componentAmtMap[rGLJ.gljId]) {
  205. isChanged = true;
  206. const diff = scMathUtil.roundTo(rGLJ.consumeAmt - componentAmtMap[rGLJ.gljId], -3);
  207. if (diff < 0) {
  208. console.log(`ration.code`);
  209. console.log(ration.code);
  210. }
  211. if (diff > errorRange) {
  212. // 扣减
  213. rGLJ.consumeAmt = diff;
  214. newRationGljList.push(rGLJ);
  215. }
  216. } else {
  217. newRationGljList.push(rGLJ);
  218. }
  219. }
  220. if (isChanged) {
  221. updateData.push({
  222. updateOne: {
  223. filter: { ID: ration.ID },
  224. update: { rationGljList: newRationGljList }
  225. }
  226. });
  227. }
  228. }
  229. if (updateData.length) {
  230. await rationItemModel.bulkWrite(updateData);
  231. }
  232. };
  233. /* rationItemDAO.prototype.copyLib = async function (sourceLibID, targetLibID) {
  234. // coe-list
  235. const coeIDMap = {};
  236. const newCoeData = [];
  237. const sourceCoeData = await _stdRationCoeModel.find({ libID: sourceLibID }, '-_id').lean();
  238. const coeCount = await counter.counterDAO.getIDAfterCount(counter.moduleName.coeList, sourceCoeData.length);
  239. const coeIdx = coeCount.sequence_value - (sourceCoeData.length - 1);
  240. sourceCoeData.forEach((coe, index) => {
  241. coeIDMap[coe.ID] = coeIdx + index;
  242. newCoeData.push({
  243. ...coe,
  244. libID: targetLibID,
  245. ID: coeIDMap[coe.ID]
  246. });
  247. });
  248. await stdRationCoeModel.insertMany(newCoeData);
  249. // ration-section
  250. const sectionIDMap = {};
  251. const newSectionData = [];
  252. const sourceSectionData = await _stdRationSectionModel.find({ rationRepId: sourceLibID }, '-_id').lean();
  253. const sectionCount = await counter.counterDAO.getIDAfterCount(counter.moduleName.rationTree, sourceSectionData.length);
  254. const sectionIdx = sectionCount.sequence_value - (sourceSectionData.length - 1);
  255. sourceSectionData.forEach((section, index) => {
  256. sectionIDMap[section.ID] = sectionIdx + index;
  257. });
  258. sourceSectionData.forEach(section => {
  259. newSectionData.push({
  260. ...section,
  261. rationRepId: targetLibID,
  262. ID: sectionIDMap[section.ID],
  263. ParentID: sectionIDMap[section.ParentID] || -1,
  264. NextSiblingID: sectionIDMap[section.NextSiblingID] || -1
  265. });
  266. });
  267. await stdRationSectionModel.insertMany(newSectionData);
  268. // glj
  269. const sourceGLJData = await stdGLJModel.find({ repositoryId: 182 }, '-_id').lean();
  270. const gljIDMap = {};
  271. sourceGLJData.forEach(glj => {
  272. gljIDMap[glj.orgID] = glj.ID;
  273. });
  274. const newGLJData = sourceGLJData.map(glj => {
  275. delete glj.orgID;
  276. return glj;
  277. });
  278. await stdGLJModel.remove({ repositoryId: 182 }); // 5412
  279. await stdGLJModel.insertMany(newGLJData);
  280. // ration
  281. const newRationData = [];
  282. const sourceRationData = await _rationItemModel.find({ rationRepId: sourceLibID }, '-_id').lean();
  283. const rationCount = await counter.counterDAO.getIDAfterCount(counter.moduleName.rations, sourceRationData.length);
  284. const rationIdx = rationCount.sequence_value - (sourceRationData.length - 1);
  285. sourceRationData.forEach((ration, index) => {
  286. const rationID = rationIdx + index;
  287. const sectionID = sectionIDMap[ration.sectionId];
  288. const newRationCoeList = (ration.rationCoeList || []).map(rCoe => ({
  289. no: rCoe.no,
  290. ID: coeIDMap[rCoe.ID]
  291. }));
  292. const newRationGLJList = (ration.rationGljList || []).map(rGLJ => ({
  293. ...rGLJ,
  294. gljId: gljIDMap[rGLJ.gljId],
  295. }));
  296. newRationData.push({
  297. ...ration,
  298. rationRepId: targetLibID,
  299. ID: rationID,
  300. sectionId: sectionID,
  301. rationCoeList: newRationCoeList,
  302. rationGljList: newRationGLJList
  303. });
  304. });
  305. await rationItemModel.insertMany(newRationData);
  306. }; */
  307. // 由于导入excel时,excel数据存在负的工程量,所以导入后一些定额人材机的消耗量可能为负,需要处理
  308. rationItemDAO.prototype.handleMinusQuantity = async function () {
  309. const updateTask = [];
  310. const repIDs = new Set();
  311. const rations = await rationItemModel.find({ 'rationGljList.consumeAmt': { $lt: 0 } }).lean();
  312. for (const ration of rations) {
  313. repIDs.add(ration.rationRepId);
  314. const rationGLJList = [];
  315. for (const rGLJ of ration.rationGljList) {
  316. rationGLJList.push({
  317. gljId: rGLJ.gljId,
  318. consumeAmt: Math.abs(rGLJ.consumeAmt),
  319. proportion: rGLJ.proportion
  320. });
  321. }
  322. updateTask.push({
  323. updateOne: {
  324. filter: { ID: ration.ID },
  325. update: { $set: { rationGljList: rationGLJList } }
  326. }
  327. });
  328. }
  329. if (updateTask.length) {
  330. await rationItemModel.bulkWrite(updateTask);
  331. }
  332. };
  333. rationItemDAO.prototype.prepareInitData = async function (rationRepId) {
  334. // 定额库
  335. const libTask = stdRationLibModel.findOne({ ID: rationRepId }, '-_id ID dispName gljLib');
  336. // 定额编码
  337. const codesTask = rationItemModel.find({ rationRepId }, '-_id code', { lean: true });
  338. // 定额章节树
  339. const sectionTreeTask = stdRationSectionModel.find({ rationRepId }, '-_id', { lean: true });
  340. // 安装增加费
  341. const installationTask = installationDao.getInstallation(rationRepId);
  342. const [libInfo, codesArr, sectionTree, installationList] = await Promise.all([libTask, codesTask, sectionTreeTask, installationTask]);
  343. const rationsCodes = codesArr.reduce((acc, cur) => {
  344. acc.push(cur.code);
  345. return acc;
  346. }, []);
  347. // 人材机分类树
  348. const gljLibId = libInfo.gljLib;
  349. const gljTreeTask = stdGljDao.getGljTreeSync(gljLibId);
  350. const gljTask = stdGljDao.getGljItemsSync(gljLibId);
  351. const [gljTree, gljList] = await Promise.all([gljTreeTask, gljTask]);
  352. const gljDistTypeList = stdgljutil.getStdGljTypeCacheObj().toArray();
  353. return {
  354. libInfo,
  355. rationsCodes,
  356. sectionTree,
  357. installationList,
  358. gljTree,
  359. gljList,
  360. gljDistTypeList
  361. };
  362. };
  363. rationItemDAO.prototype.getRationItemsByLib = async function (rationRepId, showHint = null, returnFields = '') {
  364. let rationLib = await stdRationLibModel.findOne({ ID: rationRepId, deleted: false });
  365. if (!rationLib) {
  366. return [];
  367. }
  368. let startDate = new Date();
  369. let rations = await rationItemModel.find({ rationRepId: rationRepId }, returnFields).lean();
  370. console.log(`Date: ${new Date() - startDate}====================================`);
  371. if (!showHint) {
  372. return rations;
  373. }
  374. else {
  375. const stdBillsLibListsModel = new STDGLJListModel();
  376. const stdGLJData = await stdBillsLibListsModel.getGljItemsByRepId(rationLib.gljLib, '-_id ID code name unit gljType');
  377. let gljMapping = {};
  378. for (let glj of stdGLJData) {
  379. gljMapping[glj.ID] = glj;
  380. }
  381. //设置悬浮
  382. for (let ration of rations) {
  383. let hintsArr = [];
  384. //对人材机进行排序
  385. ration.rationGljList.sort(function (a, b) {
  386. let gljA = gljMapping[a.gljId],
  387. gljB = gljMapping[b.gljId];
  388. if (gljA && gljB) {
  389. let aV = gljA.gljType + gljA.code,
  390. bV = gljB.gljType + gljB.code;
  391. if (aV > bV) {
  392. return 1;
  393. } else if (aV < bV) {
  394. return -1;
  395. }
  396. }
  397. return 0;
  398. });
  399. for (let rationGlj of ration.rationGljList) {
  400. let subGlj = gljMapping[rationGlj.gljId];
  401. if (subGlj) {
  402. hintsArr.push(` ${subGlj.code} ${subGlj.name}${subGlj.specs ? '&nbsp;&nbsp;&nbsp;' + subGlj.specs : ''}&nbsp;&nbsp&nbsp;${subGlj.unit}&nbsp;&nbsp;&nbsp;${rationGlj.consumeAmt}`);
  403. }
  404. }
  405. hintsArr.push(`基价 元 ${ration.basePrice}`);
  406. if (ration.jobContent && ration.jobContent.toString().trim() !== '') {
  407. hintsArr.push(`工作内容:`);
  408. hintsArr = hintsArr.concat(ration.jobContent.split('\n'));
  409. }
  410. if (ration.annotation && ration.annotation.toString().trim() !== '') {
  411. hintsArr.push(`附注:`);
  412. hintsArr = hintsArr.concat(ration.annotation.split('\n'));
  413. }
  414. ration.hint = hintsArr.join('<br>');
  415. }
  416. return rations;
  417. }
  418. };
  419. rationItemDAO.prototype.sortToNumber = function (datas) {
  420. for (let i = 0, len = datas.length; i < len; i++) {
  421. let data = datas[i]._doc;
  422. if (_exist(data, 'labourPrice')) {
  423. data['labourPrice'] = parseFloat(data['labourPrice']);
  424. }
  425. if (_exist(data, 'materialPrice')) {
  426. data['materialPrice'] = parseFloat(data['materialPrice']);
  427. }
  428. if (_exist(data, 'machinePrice')) {
  429. data['machinePrice'] = parseFloat(data['machinePrice']);
  430. }
  431. if (_exist(data, 'basePrice')) {
  432. data['basePrice'] = parseFloat(data['basePrice']);
  433. }
  434. if (_exist(data, 'rationGljList')) {
  435. for (let j = 0, jLen = data['rationGljList'].length; j < jLen; j++) {
  436. let raGljObj = data['rationGljList'][j]._doc;
  437. if (_exist(raGljObj, 'consumeAmt')) {
  438. raGljObj['consumeAmt'] = parseFloat(raGljObj['consumeAmt']);
  439. }
  440. }
  441. }
  442. }
  443. function _exist(data, attr) {
  444. return data && data[attr] !== undefined && data[attr];
  445. }
  446. };
  447. rationItemDAO.prototype.getRationItemsBySection = async function (rationRepId, sectionId, callback) {
  448. let me = this;
  449. try {
  450. let rations = await rationItemModel.find({ rationRepId: rationRepId, sectionId: sectionId });
  451. me.sortToNumber(rations);
  452. let matchRationIDs = [],
  453. matchRations = [];
  454. for (let ration of rations) {
  455. if (ration.rationTemplateList) {
  456. for (let rt of ration.rationTemplateList) {
  457. if (rt.rationID) {
  458. matchRationIDs.push(rt.rationID);
  459. }
  460. }
  461. }
  462. }
  463. if (matchRationIDs.length > 0) {
  464. matchRations = await rationItemModel.find({ ID: { $in: matchRationIDs } }, '-_id ID code name');
  465. }
  466. for (let mr of matchRations) {
  467. for (let ration of rations) {
  468. if (ration.rationTemplateList) {
  469. for (let rt of ration.rationTemplateList) {
  470. if (rt.rationID && rt.rationID === mr.ID) {
  471. rt.code = mr.code ? mr.code : '';
  472. rt.name = mr.name ? mr.name : '';
  473. }
  474. }
  475. }
  476. }
  477. }
  478. callback(false, "Get items successfully", rations);
  479. } catch (err) {
  480. console.log(err);
  481. callback(true, "Fail to get items", "");
  482. }
  483. /* rationItemModel.find({"rationRepId": rationRepId, "sectionId": sectionId, "$or": [{"isDeleted": null}, {"isDeleted": false} ]},function(err,data){
  484. if(err) callback(true, "Fail to get items", "");
  485. else {
  486. me.sortToNumber(data);
  487. callback(false,"Get items successfully", data);
  488. }
  489. })*/
  490. };
  491. rationItemDAO.prototype.mixUpdateRationItems = function (rationLibId, lastOpr, sectionId, updateItems, addItems, rIds, callback) {
  492. var me = this;
  493. if (updateItems.length == 0 && rIds.length == 0) {
  494. me.addRationItems(rationLibId, lastOpr, sectionId, addItems, callback);
  495. } else {
  496. me.removeRationItems(rationLibId, lastOpr, rIds, function (err, message, docs) {
  497. if (err) {
  498. callback(true, "Fail to remove", false);
  499. } else {
  500. me.updateRationItems(rationLibId, lastOpr, sectionId, updateItems, function (err, results) {
  501. if (err) {
  502. console.log(err);
  503. callback(true, "Fail to save", false);
  504. } else {
  505. if (addItems && addItems.length > 0) {
  506. me.addRationItems(rationLibId, lastOpr, sectionId, addItems, callback);
  507. } else {
  508. callback(false, "Save successfully", results);
  509. }
  510. }
  511. });
  512. }
  513. })
  514. }
  515. };
  516. rationItemDAO.prototype.removeRationItems = function (rationLibId, lastOpr, rIds, callback) {
  517. if (rIds.length > 0) {
  518. rationItemModel.collection.remove({ ID: { $in: rIds } }, null, function (err, docs) {
  519. if (err) {
  520. callback(true, "Fail to remove", false);
  521. } else {
  522. rationRepositoryDao.updateOprArr({ ID: rationLibId }, lastOpr, moment(Date.now()).format('YYYY-MM-DD HH:mm:ss'), function (err) {
  523. if (!err) {
  524. rationItemModel.update({ rationRepId: rationLibId }, { $pull: { rationTemplateList: { rationID: { $in: rIds } } } }, function (theErr) {
  525. if (!theErr) {
  526. callback(false, "Remove successfully", docs);
  527. } else {
  528. callback(true, "Fail to remove", false);
  529. }
  530. });
  531. } else {
  532. callback(true, "Fail to remove", false);
  533. }
  534. })
  535. }
  536. })
  537. } else {
  538. callback(false, "No records were deleted!", null);
  539. }
  540. };
  541. rationItemDAO.prototype.getRationItemsByCode = function (repId, code, callback) {
  542. rationItemModel.find({ "rationRepId": repId, "code": { '$regex': code, $options: '$i' }, "$or": [{ "isDeleted": null }, { "isDeleted": false }] }, function (err, data) {
  543. if (err) callback(true, "Fail to get items", "")
  544. else callback(false, "Get items successfully", data);
  545. })
  546. };
  547. rationItemDAO.prototype.findRation = function (repId, keyword, callback) {
  548. var filter = {
  549. 'rationRepId': repId,
  550. '$and': [{
  551. '$or': [{ 'code': { '$regex': keyword, $options: '$i' } }, { 'name': { '$regex': keyword, $options: '$i' } }]
  552. }, {
  553. '$or': [{ 'isDeleted': { "$exists": false } }, { 'isDeleted': null }, { 'isDeleted': false }]
  554. }]
  555. };
  556. rationItemModel.find(filter, function (err, data) {
  557. if (err) {
  558. callback(true, 'Fail to find ration', null);
  559. } else {
  560. callback(false, '', data);
  561. }
  562. })
  563. }
  564. rationItemDAO.prototype.getRationItem = async function (repId, code) {
  565. let ration = await rationItemModel.findOne({ rationRepId: repId, code: code });
  566. return ration;
  567. };
  568. rationItemDAO.prototype.getRationByID = async function (ID) {
  569. let ration = await rationItemModel.findOne({ ID: +ID }).lean();
  570. return ration;
  571. };
  572. rationItemDAO.prototype.addRationItems = function (rationLibId, lastOpr, sectionId, items, callback) {
  573. if (items && items.length > 0) {
  574. counter.counterDAO.getIDAfterCount(counter.moduleName.rations, items.length, function (err, result) {
  575. var maxId = result.sequence_value;
  576. var arr = [];
  577. for (var i = 0; i < items.length; i++) {
  578. var obj = new rationItemModel(items[i]);
  579. obj.ID = (maxId - (items.length - 1) + i);
  580. obj.sectionId = sectionId;
  581. obj.rationRepId = rationLibId;
  582. arr.push(obj);
  583. }
  584. rationItemModel.collection.insert(arr, null, function (err, docs) {
  585. if (err) {
  586. callback(true, "Fail to save", false);
  587. } else {
  588. rationRepositoryDao.updateOprArr({ ID: rationLibId }, lastOpr, moment(Date.now()).format('YYYY-MM-DD HH:mm:ss'), function (err) {
  589. if (err) {
  590. callback(true, "Fail to sava operator", false);
  591. }
  592. else {
  593. callback(false, "Save successfully", docs);
  594. }
  595. })
  596. }
  597. })
  598. });
  599. } else {
  600. callback(true, "Source error!", false);
  601. }
  602. };
  603. rationItemDAO.prototype.updateRationItems = function (rationLibId, lastOpr, sectionId, items, callback) {
  604. console.log('enter============');
  605. var functions = [];
  606. for (var i = 0; i < items.length; i++) {
  607. functions.push((function (doc) {
  608. return function (cb) {
  609. var filter = {};
  610. if (doc.ID) {
  611. filter.ID = doc.ID;
  612. } else {
  613. filter.sectionId = sectionId;
  614. if (rationLibId) filter.rationRepId = rationLibId;
  615. filter.code = doc.code;
  616. }
  617. rationItemModel.update(filter, doc, cb);
  618. };
  619. })(items[i]));
  620. }
  621. functions.push((function () {
  622. return function (cb) {
  623. rationRepositoryDao.updateOprArr({ ID: rationLibId }, lastOpr, moment(Date.now()).format('YYYY-MM-DD HH:mm:ss'), function (err) {
  624. if (err) {
  625. cb(err);
  626. }
  627. else {
  628. cb(null);
  629. }
  630. });
  631. }
  632. })());
  633. async.parallel(functions, function (err, results) {
  634. callback(err, results);
  635. });
  636. };
  637. //ration round func
  638. function round(v, e) {
  639. var t = 1;
  640. for (; e > 0; t *= 10, e--);
  641. for (; e < 0; t /= 10, e++);
  642. return Math.round(v * t) / t;
  643. }
  644. function calcRation(gljArr) {
  645. let labourPrc = [],
  646. materialPrc = [],
  647. machinePrc = [],
  648. managePrc = [],
  649. profitPrc = [],
  650. riskPrc = [],
  651. singlePrc,
  652. updatePrc = { labourPrice: 0, materialPrice: 0, machinePrice: 0, managePrice: 0, profitPrice: 0, riskPrice: 0, basePrice: 0 };
  653. gljArr.forEach(function (gljItem) {
  654. if (gljItem.gljParentType !== -1) {
  655. singlePrc = scMathUtil.roundTo(gljItem.basePrice * gljItem.consumeAmt, -3);
  656. if (gljItem.gljParentType === 1) {
  657. labourPrc.push(singlePrc);
  658. }
  659. else if (gljItem.gljParentType === 2) {
  660. materialPrc.push(singlePrc);
  661. }
  662. else if (gljItem.gljParentType === 3) {
  663. machinePrc.push(singlePrc);
  664. }
  665. else if (gljItem.gljParentType === 6) {
  666. managePrc.push(singlePrc);
  667. }
  668. else if (gljItem.gljParentType === 7) {
  669. profitPrc.push(singlePrc);
  670. }
  671. else if (gljItem.gljParentType === 8) {
  672. riskPrc.push(singlePrc);
  673. }
  674. }
  675. });
  676. if (labourPrc.length > 0) {
  677. let sumLaP = 0;
  678. for (let i = 0; i < labourPrc.length; i++) {
  679. sumLaP = scMathUtil.roundTo(sumLaP + labourPrc[i], -6);
  680. }
  681. updatePrc.labourPrice = scMathUtil.roundTo(sumLaP, -2);
  682. updatePrc.basePrice = scMathUtil.roundTo(updatePrc.basePrice + updatePrc.labourPrice, -2);
  683. }
  684. if (materialPrc.length > 0) {
  685. let sumMtP = 0;
  686. for (let i = 0; i < materialPrc.length; i++) {
  687. sumMtP = scMathUtil.roundTo(sumMtP + materialPrc[i], -6);
  688. }
  689. updatePrc.materialPrice = scMathUtil.roundTo(sumMtP, -2);
  690. updatePrc.basePrice = scMathUtil.roundTo(updatePrc.basePrice + updatePrc.materialPrice, -2);
  691. }
  692. if (machinePrc.length > 0) {
  693. let sumMaP = 0;
  694. for (let i = 0; i < machinePrc.length; i++) {
  695. sumMaP = scMathUtil.roundTo(sumMaP + machinePrc[i], -6);
  696. }
  697. updatePrc.machinePrice = scMathUtil.roundTo(sumMaP, -2);
  698. updatePrc.basePrice = scMathUtil.roundTo(updatePrc.basePrice + updatePrc.machinePrice, -2);
  699. }
  700. if (managePrc.length > 0) {
  701. let sumMgP = 0;
  702. for (let i = 0; i < managePrc.length; i++) {
  703. sumMgP = scMathUtil.roundTo(sumMgP + managePrc[i], -6);
  704. }
  705. updatePrc.managePrice = scMathUtil.roundTo(sumMgP, -2);
  706. updatePrc.basePrice = scMathUtil.roundTo(updatePrc.basePrice + updatePrc.managePrice, -2);
  707. }
  708. if (profitPrc.length > 0) {
  709. let sumPfP = 0;
  710. for (let i = 0; i < profitPrc.length; i++) {
  711. sumPfP = scMathUtil.roundTo(sumPfP + profitPrc[i], -6);
  712. }
  713. updatePrc.profitPrice = scMathUtil.roundTo(sumPfP, -2);
  714. updatePrc.basePrice = scMathUtil.roundTo(updatePrc.basePrice + updatePrc.profitPrice, -2);
  715. }
  716. if (riskPrc.length > 0) {
  717. let sumRkP = 0;
  718. for (let i = 0; i < riskPrc.length; i++) {
  719. sumRkP = scMathUtil.roundTo(sumRkP + riskPrc[i], -6);
  720. }
  721. updatePrc.riskPrice = scMathUtil.roundTo(sumRkP, -2);
  722. updatePrc.basePrice = scMathUtil.roundTo(updatePrc.basePrice + updatePrc.riskPrice, -2);
  723. }
  724. return updatePrc;
  725. }
  726. rationItemDAO.prototype.updateRationBasePrc = function (basePrcArr, overWriteUrl, callback) {
  727. async.each(basePrcArr, function (basePrcObj, finalCb) {
  728. let adjGljId = basePrcObj.gljId, adjBasePrice = basePrcObj.basePrice, adjGljType = basePrcObj.gljType;
  729. async.waterfall([
  730. function (cb) {
  731. if (typeof basePrcObj.delete !== 'undefined' && basePrcObj.delete === 1) {
  732. rationItemModel.find({ 'rationGljList.gljId': adjGljId }, { ID: 1, rationGljList: 1 }, function (err, result) {
  733. if (err) {
  734. cb(err);
  735. }
  736. else {
  737. //删除
  738. rationItemModel.update({ 'rationGljList.gljId': adjGljId }, { $pull: { rationGljList: { gljId: adjGljId } } }, { multi: true }, function (err) {
  739. if (err) {
  740. cb(err);
  741. }
  742. else {
  743. //补充定额
  744. compleRationModel.find({ 'rationGljList.gljId': adjGljId }, { ID: 1, rationGljList: 1 }, function (err, compleRst) {
  745. if (err) {
  746. cb(err);
  747. }
  748. else {
  749. compleRationModel.update({ 'rationGljList.gljId': adjGljId }, { $pull: { rationGljList: { gljId: adjGljId } } }, { multi: true }, function (err) {
  750. if (err) {
  751. cb(err);
  752. }
  753. else {
  754. for (let i = 0, len = compleRst.length; i < len; i++) {
  755. compleRst[i]._doc.type = 'complementary';
  756. }
  757. cb(null, result.concat(compleRst));
  758. }
  759. });
  760. }
  761. });
  762. }
  763. });
  764. }
  765. });
  766. }
  767. else {
  768. rationItemModel.find({ 'rationGljList.gljId': adjGljId }, { ID: 1, rationGljList: 1 }, function (err, result) {
  769. if (err) {
  770. cb(err);
  771. }
  772. else {
  773. compleRationModel.find({ 'rationGljList.gljId': adjGljId }, { ID: 1, rationGljList: 1 }, function (err, compleRst) {
  774. if (err) {
  775. cb(err);
  776. }
  777. else {
  778. for (let i = 0, len = compleRst.length; i < len; i++) {
  779. compleRst[i]._doc.type = 'complementary';
  780. }
  781. cb(null, result.concat(compleRst));
  782. }
  783. });
  784. }
  785. });
  786. }
  787. },
  788. function (result, cb) {
  789. let compleRTasks = [], stdRTasks = [];
  790. //重算时需要用到的所有工料机,一次性取
  791. let compleGljIds = [], stdGljIds = [];
  792. for (let ration of result) {
  793. for (let glj of ration.rationGljList) {
  794. if (glj.type !== undefined && glj.type === 'complementary') {
  795. compleGljIds.push(glj.gljId);
  796. }
  797. else {
  798. stdGljIds.push(glj.gljId);
  799. }
  800. }
  801. }
  802. gljDao.getStdCompleGljItems(compleGljIds, stdGljIds, function (err, allGljs) {
  803. if (err) {
  804. cb(err);
  805. }
  806. else {
  807. let gljIndex = {};
  808. for (let glj of allGljs) {
  809. gljIndex[glj.ID] = glj;
  810. }
  811. async.each(result, function (rationItem, ecb) {
  812. let rationGljList = rationItem.rationGljList;
  813. let gljArr = [];
  814. for (let i = 0; i < rationGljList.length; i++) {
  815. let theGlj = gljIndex[rationGljList[i].gljId];
  816. if (theGlj !== undefined && theGlj) {
  817. let gljParentType = -1;
  818. if (theGlj.ID === adjGljId) {
  819. theGlj.gljType = adjGljType;
  820. }
  821. if (theGlj.gljType <= 3) {
  822. gljParentType = theGlj.gljType;
  823. } else if (theGlj.gljType > 200 && theGlj.gljType < 300) {
  824. gljParentType = 2;
  825. } else if (theGlj.gljType > 300 && theGlj.gljType < 400) {
  826. gljParentType = 3;
  827. } else if (theGlj.gljType === 6) { //管理费
  828. gljParentType = 6;
  829. } else if (theGlj.gljType === 7) { //利润
  830. gljParentType = 7;
  831. } else if (theGlj.gljType === 8) { //风险费
  832. gljParentType = 8;
  833. }
  834. if (theGlj)
  835. if (theGlj.ID === adjGljId) {
  836. gljArr.push({ gljId: theGlj.ID, basePrice: adjBasePrice, gljParentType: gljParentType, unit: theGlj.unit });
  837. } else {
  838. if (theGlj.priceProperty && Object.keys(theGlj.priceProperty).length > 0) {
  839. gljArr.push({
  840. gljId: theGlj.ID,
  841. basePrice: parseFloat(theGlj.priceProperty.price1),
  842. gljParentType: gljParentType,
  843. unit: theGlj.unit
  844. });
  845. } else {
  846. gljArr.push({
  847. gljId: theGlj.ID,
  848. basePrice: parseFloat(theGlj.basePrice),
  849. gljParentType: gljParentType,
  850. unit: theGlj.unit
  851. });
  852. }
  853. }
  854. }
  855. }
  856. gljArr.forEach(function (gljItem) {
  857. rationGljList.forEach(function (rationGlj) {
  858. if (gljItem.gljId === rationGlj.gljId) {
  859. gljItem.consumeAmt = parseFloat(rationGlj.consumeAmt);
  860. }
  861. })
  862. });
  863. let updatePrc = null;
  864. let overWriteCalc = false; //需要重写算法
  865. if (overWriteUrl) {
  866. let overWriteExports = require(overWriteUrl);
  867. if (typeof overWriteExports.calcRation !== 'undefined') {
  868. overWriteCalc = true;
  869. updatePrc = overWriteExports.calcRation(gljArr, scMathUtil);
  870. }
  871. }
  872. if (!overWriteCalc) {
  873. updatePrc = calcRation(gljArr);
  874. }
  875. let task = {
  876. updateOne: {
  877. filter: {
  878. ID: rationItem.ID
  879. },
  880. update: {
  881. labourPrice: updatePrc.labourPrice.toString(),
  882. materialPrice: updatePrc.materialPrice.toString(),
  883. machinePrice: updatePrc.machinePrice.toString(),
  884. basePrice: updatePrc.basePrice.toString()
  885. }
  886. }
  887. };
  888. //updateDataBase
  889. if (rationItem._doc.type !== undefined && rationItem._doc.type === 'complementary') {
  890. compleRTasks.push(task);
  891. ecb(null);
  892. }
  893. else {
  894. stdRTasks.push(task);
  895. ecb(null);
  896. }
  897. }, async function (err) {
  898. if (err) {
  899. cb(err);
  900. }
  901. else {
  902. //do sth
  903. try {
  904. if (compleRTasks.length > 0) {
  905. await compleRationModel.bulkWrite(compleRTasks);
  906. }
  907. if (stdRTasks.length > 0) {
  908. await rationItemModel.bulkWrite(stdRTasks);
  909. }
  910. }
  911. catch (e) {
  912. cb(err);
  913. }
  914. cb(null);
  915. }
  916. });
  917. }
  918. });
  919. },
  920. ], function (err) {
  921. if (err) {
  922. finalCb(err);
  923. }
  924. else {
  925. finalCb(null);
  926. }
  927. });
  928. }, function (err) {
  929. if (err) {
  930. callback(err, 'Error');
  931. }
  932. else {
  933. callback(null, '');
  934. }
  935. });
  936. };
  937. rationItemDAO.prototype.getRationGljIds = function (data, callback) {
  938. let repId = data.repId;
  939. rationItemModel.find({ rationRepId: repId }, function (err, result) {
  940. if (err) {
  941. callback(err, 'Error', null);
  942. }
  943. else {
  944. let rstIds = [], newRst = [];
  945. result.forEach(function (data) {
  946. if (data.rationGljList.length > 0) {
  947. data.rationGljList.forEach(function (gljObj) {
  948. rstIds.push(gljObj.gljId);
  949. })
  950. }
  951. });
  952. for (let i = 0; i < rstIds.length; i++) {
  953. if (newRst.indexOf(rstIds[i]) === -1) {
  954. newRst.push(rstIds[i]);
  955. }
  956. }
  957. callback(null, '', newRst);
  958. }
  959. });
  960. };
  961. rationItemDAO.prototype.getRationsCodes = function (data, callback) {
  962. let repId = data.repId;
  963. rationItemModel.find({ rationRepId: repId, isDeleted: false }, function (err, result) {
  964. if (err) {
  965. callback(err, 'Error', null);
  966. }
  967. else {
  968. let rstCodes = [];
  969. result.forEach(function (rationItem) {
  970. rstCodes.push(rationItem.code);
  971. });
  972. callback(null, 'get all rationCodes success', rstCodes);
  973. }
  974. })
  975. };
  976. rationItemDAO.prototype.updateJobContent = function (lastOpr, repId, updateArr, callback) {
  977. rationRepositoryDao.updateOprArr({ ID: repId }, lastOpr, moment(Date.now()).format('YYYY-MM-DD HH:mm:ss'), function (err) {
  978. async.each(updateArr, function (obj, cb) {
  979. rationItemModel.update({ rationRepId: repId, code: obj.code }, { $set: { jobContent: obj.jobContent } }, function (err) {
  980. if (err) {
  981. cb(err);
  982. }
  983. else {
  984. cb(null);
  985. }
  986. })
  987. }, function (err) {
  988. if (err) {
  989. callback(err);
  990. }
  991. else {
  992. callback(null);
  993. }
  994. });
  995. });
  996. }
  997. rationItemDAO.prototype.updateAnnotation = function (lastOpr, repId, updateArr, callback) {
  998. rationRepositoryDao.updateOprArr({ ID: repId }, lastOpr, moment(Date.now()).format('YYYY-MM-DD HH:mm:ss'), function (err) {
  999. async.each(updateArr, function (obj, cb) {
  1000. rationItemModel.update({ rationRepId: repId, code: obj.code }, { $set: { annotation: obj.annotation } }, function (err) {
  1001. if (err) {
  1002. cb(err);
  1003. }
  1004. else {
  1005. cb(null);
  1006. }
  1007. })
  1008. }, function (err) {
  1009. if (err) {
  1010. callback(err);
  1011. }
  1012. else {
  1013. callback(null);
  1014. }
  1015. });
  1016. });
  1017. };
  1018. //更新定额下模板关联
  1019. rationItemDAO.prototype.updateRationTemplate = async function (rationRepId, rationID, templateData) {
  1020. //自动匹配定额
  1021. let matachCodes = [],
  1022. matchRations = [];
  1023. //要保存的数据
  1024. let saveData = [];
  1025. for (let data of templateData) {
  1026. if (data.code) {
  1027. matachCodes.push(data.code);
  1028. }
  1029. }
  1030. matachCodes = Array.from(new Set(matachCodes));
  1031. if (matachCodes.length > 0) {
  1032. matchRations = await rationItemModel.find({ rationRepId: rationRepId, code: { $in: matachCodes } }, '-_id ID code name');
  1033. }
  1034. let validData = [];
  1035. //设置展示数据
  1036. for (let data of templateData) {
  1037. let match = false;
  1038. for (let ration of matchRations) {
  1039. if (data.code && data.code === ration.code) {
  1040. match = true;
  1041. data.name = ration.name;
  1042. data.rationID = ration.ID;
  1043. break;
  1044. }
  1045. }
  1046. if (!match) {
  1047. data.code = '';
  1048. data.name = '';
  1049. }
  1050. if (data.type || data.code || data.name || data.billsLocation) {
  1051. validData.push(data);
  1052. }
  1053. }
  1054. for (let data of validData) {
  1055. saveData.push({ rationID: data.rationID ? data.rationID : null, type: data.type, billsLocation: data.billsLocation });
  1056. }
  1057. //更新
  1058. await rationItemModel.update({ ID: rationID }, { $set: { rationTemplateList: saveData } });
  1059. return validData;
  1060. };
  1061. // 根据章节列表批量更新定额
  1062. rationItemDAO.prototype.updateRationBySection = async function (rationRepId, sectionList, updateData) {
  1063. await rationItemModel.updateMany({ rationRepId, sectionId: { $in: sectionList } }, updateData);
  1064. }
  1065. //计算导入数据的价格
  1066. rationItemDAO.prototype.calcForRation = function (stdGljList, ration, overWriteUrl) {
  1067. let rationGljList = ration.rationGljList,
  1068. gljArr = [];
  1069. for (let rationGlj of rationGljList) {
  1070. let glj = stdGljList[rationGlj.gljId];
  1071. let gljPType = parseInt(glj.gljType.toString().match(/\d+?/)[0]);
  1072. let newGlj = {
  1073. gljId: glj.ID,
  1074. consumeAmt: rationGlj.consumeAmt,
  1075. gljParentType: gljPType,
  1076. unit: glj.unit
  1077. };
  1078. newGlj.basePrice = glj.priceProperty && Object.keys(glj.priceProperty).length > 0
  1079. ? parseFloat(glj.priceProperty.price1)
  1080. : parseFloat(glj.basePrice);
  1081. gljArr.push(newGlj);
  1082. }
  1083. let updatePrc = null;
  1084. let overWriteCalc = false; //需要重写算法
  1085. if (overWriteUrl) {
  1086. let overWriteExports = require(overWriteUrl);
  1087. if (typeof overWriteExports.calcRation !== 'undefined') {
  1088. overWriteCalc = true;
  1089. updatePrc = overWriteExports.calcRation(gljArr, scMathUtil);
  1090. }
  1091. }
  1092. if (!overWriteCalc) {
  1093. updatePrc = calcRation(gljArr);
  1094. }
  1095. ration.labourPrice = updatePrc.labourPrice.toString();
  1096. ration.materialPrice = updatePrc.materialPrice.toString();
  1097. ration.machinePrice = updatePrc.machinePrice.toString();
  1098. ration.basePrice = updatePrc.basePrice.toString();
  1099. };
  1100. /**
  1101. * 根据条件获取定额数据
  1102. *
  1103. * @param {Object} condition
  1104. * @param {Object} fields
  1105. * @param {String} indexBy
  1106. * @return {Promise|Array}
  1107. */
  1108. rationItemDAO.prototype.getRationItemByCondition = async function (condition, fields = null, indexBy = null) {
  1109. let result = [];
  1110. if (Object.keys(condition).length <= 0) {
  1111. return result;
  1112. }
  1113. result = await rationItemModel.find(condition, fields).sort({ code: 1 });
  1114. if (indexBy !== null && result.length > 0) {
  1115. let tmpResult = {};
  1116. for (let tmp of result) {
  1117. tmpResult[tmp[indexBy]] = tmp;
  1118. }
  1119. result = tmpResult;
  1120. }
  1121. return result;
  1122. };
  1123. /**
  1124. * 从excel中批量新增数据
  1125. *
  1126. * @param {Number} rationRepId
  1127. * @param {Array} data
  1128. * @return {bool}
  1129. */
  1130. rationItemDAO.prototype.batchAddFromExcel = async function (rationRepId, data) {
  1131. if (data.length <= 0) {
  1132. return false;
  1133. }
  1134. // 获取定额库相关数据
  1135. const rationRepository = await rationRepositoryDao.getRepositoryById(rationRepId);
  1136. if (rationRepository.length !== 1 || rationRepository[0].gljLib === undefined) {
  1137. return false;
  1138. }
  1139. // 获取标准工料机库数据
  1140. const stdBillsLibListsModel = new STDGLJListModel();
  1141. const stdGLJData = await stdBillsLibListsModel.getGljItemsByRepId(rationRepository[0].gljLib);
  1142. // 整理标准工料机库数据
  1143. let stdGLJList = {};
  1144. let stdGLJListByID = {};
  1145. for (const tmp of stdGLJData) {
  1146. stdGLJList[tmp.code.toString()] = tmp.ID;
  1147. stdGLJListByID[tmp.ID] = tmp;
  1148. }
  1149. let lastData = {};
  1150. // 定额xx下提示的次数
  1151. let lastFailCount = 0;
  1152. const rationData = [];
  1153. // 编码列表,用于查找库中是否有对应数据
  1154. let rationCodeList = [];
  1155. let gljCodeList = [];
  1156. // 插入失败的工料机列表(用于提示)
  1157. let failGLJList = [];
  1158. for (const tmp of data) {
  1159. if (tmp.length <= 0) {
  1160. continue;
  1161. }
  1162. // 如果第一个字段为null则是工料机数据,放入上一个数据的工料机字段
  1163. if (!tmp[0] && Object.keys(lastData).length > 0) {
  1164. // 如果不存在对应的工料机库数据则跳过
  1165. if (!stdGLJList[tmp[1]]) {
  1166. if (lastFailCount === 0) {
  1167. failGLJList.push('定额' + lastData.code + '下的');
  1168. lastFailCount++;
  1169. }
  1170. //const failString = '定额' + lastData.code + '下的' + tmp[1];
  1171. failGLJList.push(tmp[1]);
  1172. continue;
  1173. }
  1174. const tmpRationGlj = {
  1175. gljId: stdGLJList[tmp[1]],
  1176. consumeAmt: Math.abs(tmp[4]),
  1177. proportion: 0,
  1178. };
  1179. lastData.rationGljList.push(tmpRationGlj);
  1180. if (gljCodeList.indexOf(tmp[1]) < 0) {
  1181. gljCodeList.push(tmp[1]);
  1182. }
  1183. continue;
  1184. }
  1185. if (tmp[0] === '定额' && Object.keys(lastData).length > 0) {
  1186. rationData.push(lastData);
  1187. }
  1188. lastFailCount = 0;
  1189. // 组装数据
  1190. lastData = {
  1191. code: tmp[1],
  1192. name: tmp[2],
  1193. unit: tmp[3],
  1194. caption: tmp[2],
  1195. rationRepId: rationRepId,
  1196. sectionId: 0,
  1197. labourPrice: '0',
  1198. materialPrice: '0',
  1199. machinePrice: '0',
  1200. basePrice: '0',
  1201. rationGljList: []
  1202. };
  1203. // 防止重复加入
  1204. if (rationCodeList.indexOf(tmp[1]) < 0) {
  1205. rationCodeList.push(tmp[1]);
  1206. }
  1207. }
  1208. // 最后一个入数组
  1209. rationData.push(lastData);
  1210. // 查找数据库中是否已存在待插入数据
  1211. const condition = {
  1212. rationRepId: rationRepId,
  1213. code: { $in: rationCodeList }
  1214. };
  1215. const existCodeList = await this.getRationItemByCondition(condition, ['code'], 'code');
  1216. // 过滤插入数据
  1217. let insertData = [];
  1218. //已存在定额,则更新价格及rationGLjList字段
  1219. let updateData = [];
  1220. for (const ration of rationData) {
  1221. if (existCodeList[ration.code] !== undefined) {
  1222. updateData.push(ration);
  1223. continue;
  1224. }
  1225. insertData.push(ration);
  1226. }
  1227. //更新定额
  1228. let updateBulk = [];
  1229. for (let ration of updateData) {
  1230. this.calcForRation(stdGLJListByID, ration);
  1231. updateBulk.push({
  1232. updateOne: {
  1233. filter: { rationRepId: rationRepId, code: ration.code },
  1234. update: {
  1235. $set: {
  1236. rationGljList: ration.rationGljList, labourPrice: ration.labourPrice, materialPrice: ration.materialPrice,
  1237. machinePrice: ration.machinePrice, basePrice: ration.basePrice
  1238. }
  1239. }
  1240. }
  1241. });
  1242. }
  1243. //更新数据库
  1244. if (updateBulk.length > 0) {
  1245. await rationItemModel.bulkWrite(updateBulk);
  1246. }
  1247. // 如果都已经存在,直接返回
  1248. if (insertData.length <= 0) {
  1249. return failGLJList;
  1250. }
  1251. //计算价格
  1252. for (let ration of insertData) {
  1253. this.calcForRation(stdGLJListByID, ration);
  1254. }
  1255. // 组织id
  1256. const counterInfo = await counter.counterDAO.getIDAfterCount(counter.moduleName.rations, insertData.length);
  1257. let maxId = counterInfo.sequence_value;
  1258. maxId = parseInt(maxId);
  1259. let count = 0;
  1260. for (const index in insertData) {
  1261. insertData[index].ID = maxId - (insertData.length - 1) + count;
  1262. count++;
  1263. }
  1264. // 插入数据库
  1265. await rationItemModel.create(insertData);
  1266. return failGLJList;
  1267. };
  1268. /**
  1269. * 导出到excel的数据
  1270. *
  1271. * @param {Number} rationRepId
  1272. * @return {Array}
  1273. */
  1274. rationItemDAO.prototype.exportExcelData = async function (rationRepId) {
  1275. const condition = {
  1276. rationRepId: rationRepId
  1277. };
  1278. const rationDataList = await this.getRationItemByCondition(condition, ['name', 'code', 'ID', 'sectionId', 'feeType', 'caption', 'basePrice', 'jobContent', 'annotation']);
  1279. // 整理数据
  1280. let rationData = [];
  1281. for (const tmp of rationDataList) {
  1282. const sectionId = tmp.sectionId <= 0 || tmp.sectionId === undefined ? null : tmp.sectionId;
  1283. const feeType = tmp.feeType === '' || tmp.feeType === undefined ? null : tmp.feeType;
  1284. const ration = [sectionId, feeType, tmp.ID, tmp.code, tmp.name, tmp.caption, tmp.basePrice, tmp.jobContent, tmp.annotation];
  1285. rationData.push(ration);
  1286. }
  1287. const excelData = [['树ID', '取费专业', '定额ID', '定额编码', '定额名', '定额显示名称', '基价', '工作内容', '附注']];
  1288. excelData.push.apply(excelData, rationData);
  1289. return excelData;
  1290. //根据编号排序,优先级:number-number-..., number, Anumber....
  1291. /*let regConnector = /-/g,
  1292. regLetter = /[a-z,A-Z]/g,
  1293. regNum = /\d+/g;
  1294. rationData.sort(function (a, b) {
  1295. let aCode = a[3],
  1296. bCode = b[3],
  1297. rst = 0;
  1298. function compareConnector(arrA, arrB) {
  1299. let lessArr = arrA.length <= arrB ? arrA : arrB;
  1300. for (let i = 0; i < lessArr.length; i++) {
  1301. let result = compareUnit(arrA[i], arrB[i]);
  1302. if (result !== 0) {
  1303. return result;
  1304. } else {
  1305. }
  1306. }
  1307. function compareUnit(uA, uB) {
  1308. let uAV = parseFloat(uA),
  1309. uBV = parseFloat(uB);
  1310. if (uAV > uBV) {
  1311. return 1;
  1312. } else if (uAV < uBV) {
  1313. return -1;
  1314. }
  1315. return 0;
  1316. }
  1317. }
  1318. if (regConnector.test(a) && !regConnector.test(b)) {
  1319. rst = -1;
  1320. } else if (!regConnector.test(a) && regConnector.test(b)) {
  1321. rst = 1;
  1322. } else if (regConnector.test(a) && regConnector.test(b)) {
  1323. }
  1324. });
  1325. rationData.sort(function (a, b) {
  1326. let aCode = a[3],
  1327. bCode = b[3],
  1328. rst = 0,
  1329. splitA = aCode.split('-'),
  1330. splitB = bCode.split('-');
  1331. if(splitA[0] > splitB[0]){
  1332. rst = 1;
  1333. }
  1334. else if(splitA[0] < splitB[0]){
  1335. rst = -1;
  1336. }
  1337. else {
  1338. if(splitA[1] && splitB[1]){
  1339. let floatA = parseFloat(splitA[1]),
  1340. floatB = parseFloat(splitB[1]);
  1341. if(floatA > floatB){
  1342. rst = 1;
  1343. }
  1344. else if(floatA < floatB){
  1345. rst = -1;
  1346. }
  1347. }
  1348. }
  1349. return rst;
  1350. });*/
  1351. /*const excelData = [['树ID', '取费专业', '定额ID', '定额编码', '定额名', '定额显示名称', '基价']];
  1352. excelData.push.apply(excelData, rationData);
  1353. return excelData;*/
  1354. };
  1355. /**
  1356. * 批量更改章节id
  1357. *
  1358. * @param {Object} data
  1359. * @return {bool}
  1360. */
  1361. rationItemDAO.prototype.batchUpdateSectionIdFromExcel = async function (data) {
  1362. if (data.length <= 0) {
  1363. return false;
  1364. }
  1365. // 批量执行update
  1366. let bulkOprs = [],
  1367. sectionIDs = [];
  1368. for (const tmp of data) {
  1369. let rationId = parseInt(tmp[2]);
  1370. rationId = isNaN(rationId) || rationId <= 0 ? 0 : rationId;
  1371. let sectionId = parseInt(tmp[0]);
  1372. sectionId = isNaN(sectionId) || sectionId <= 0 ? 0 : sectionId;
  1373. if (sectionId <= 0 || rationId <= 0) {
  1374. continue;
  1375. }
  1376. sectionIDs.push(sectionId);
  1377. // 取费专业
  1378. let feeType = isNaN(tmp[1]) ? undefined : +(tmp[1] || '');
  1379. let name = tmp[4];
  1380. name = name ? name : '';
  1381. let caption = tmp[5];
  1382. caption = caption ? caption : '';
  1383. let jobContent = tmp[7] ? tmp[7] : '';
  1384. let annotation = tmp[8] ? tmp[8] : '';
  1385. bulkOprs.push({
  1386. updateOne: {
  1387. filter: { ID: rationId },
  1388. update: {
  1389. $set: {
  1390. sectionId,
  1391. feeType,
  1392. name,
  1393. caption,
  1394. jobContent,
  1395. annotation
  1396. }
  1397. }
  1398. }
  1399. });
  1400. }
  1401. if (bulkOprs.length <= 0) {
  1402. throw '无有效数据(树ID、定额ID不为空、且为数值)';
  1403. }
  1404. await rationItemModel.bulkWrite(bulkOprs);
  1405. // 更新章节树工作内容、附注节点选项(全设置为ALL)
  1406. sectionIDs = Array.from(new Set(sectionIDs));
  1407. if (sectionIDs.length) {
  1408. await stdRationSectionModel.updateMany(
  1409. { ID: { $in: sectionIDs } },
  1410. {
  1411. $set: {
  1412. jobContentSituation: 'ALL',
  1413. annotationSituation: 'ALL'
  1414. }
  1415. }
  1416. )
  1417. }
  1418. };
  1419. module.exports = new rationItemDAO();