12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106 |
- /**
- * Created by zhang on 2018/2/9.
- */
- //先导出后require可以解决循环引用问题
- module.exports = {
- replaceRations: replaceRations,
- addNewRation:addNewRation,
- addMultiRation: addMultiRation,
- deleteMultiRation:deleteMultiRation,
- getSameSectionRations:getSameSectionRations,
- getExtendData:getExtendData,
- getDefaultProgramID:getDefaultProgramID,
- deleteSubListByQuery:deleteSubListByQuery,
- updateCoeAdjust:updateCoeAdjust
- };
- let mongoose = require('mongoose');
- const SearchDao = require('../../complementary_ration_lib/models/searchModel');
- const GLJListModel = require("../../glj/models/glj_list_model");
- const scMathUtil = require('../../../public/scMathUtil').getUtil();
- let ration_glj_facade = require("../../ration_glj/facade/ration_glj_facade");
- let glj_calculate_facade = require("../../ration_glj/facade/glj_calculate_facade");
- let quantity_detail = require("../facade/quantity_detail_facade");
- let ration_glj = mongoose.model('ration_glj');
- let ration_coe = mongoose.model('ration_coe');
- let ration_model = require('../models/ration');
- let bill_model = require('../models/bills');
- let decimal_facade = require('./decimal_facade');
- let installationFeeModel = mongoose.model("installation_fee");
- let rationInstallationModel = mongoose.model('ration_installation');
- let rationTemplateModel = mongoose.model('ration_template');
- const uuidV1 = require('uuid/v1');
- let std_glj_lib_gljList_model = mongoose.model('std_glj_lib_gljList');
- let complementary_glj_model = mongoose.model('complementary_glj_lib');
- let rationItemModel = mongoose.model("std_ration_lib_ration_items");
- let complementaryRationModel = mongoose.model('complementary_ration_items');
- let coeMolde = mongoose.model('std_ration_lib_coe_list');
- let compleCoeModel = mongoose.model('complementary_ration_coe_list');
- let projectGLJModel = mongoose.model("glj_list");
- let mixRatioModel = mongoose.model("mix_ratio");
- let complementaryGljLibModel = mongoose.model('complementary_glj_lib');
- let counterModel = mongoose.model('counter');
- let unitPriceModel = mongoose.model('unit_price');
- let chongqingOverWrite = require("../../../web/over_write/js/chongqing_2018.js");
- let _= require('lodash');
- const projectDao = require('../../pm/models/project_model').project;
- let projectModel = mongoose.model('projects');
- async function addNewRation(data,compilation) {
- let query = data.itemQuery;
- let stdRation = null;
- let startTime = +new Date();
- if(query){
- let searchDao = new SearchDao();
- stdRation = await searchDao.getRationItem(query.userID, compilation._id, [query.rationRepId],query.code, query.ID);
- //data.newData.code = query.code;
- }
- let stdRationTime = +new Date();
- console.log("取std定额时间-------------------------------"+(stdRationTime - startTime));
- if(data.brUpdate.length>0){
- await updateSerialNo(data.brUpdate);
- }
- let newRation =await insertNewRation(data.newData,data.defaultLibID,stdRation,data.calQuantity);
- let addRationGLJTime = +new Date();
- console.log("插入新定额时间-------------------------------"+(addRationGLJTime - stdRationTime));
- if(stdRation){
- return await addRationSubList(stdRation,newRation,data.needInstall,compilation);
- }else {
- return {ration:newRation};
- }
- }
- async function addMultiRation(datas,compilation) {
- const task = [];
- for (const data of datas) {
- task.push(addNewRation(data, compilation));
- }
- return await Promise.all(task);
- }
- async function deleteMultiRation(rations) {//这里是只有删除的情况,删除定额的同时删除定额下挂的其它子项目
- if(rations.length > 0){//删除定额下的
- let rationIDS = _.map(rations,'ID');
- await deleteSubListByQuery({projectID:rations[0].projectID,rationID:{"$in": rationIDS}});
- await ration_model.model.deleteMany({ID:{"$in": rationIDS}});
- }
- }
- async function getSameSectionRations(data,userId,compilationId){
- //let userId
- //要先根据定额获取所属章节的ID
- let from = data.from; //定额类型,是标准的还是用户定义的
- let code = data.code;
- let libID = data.libID;
- let sectionId,rations=[];
- if(from == 'std'){
- let ration = await rationItemModel.findOne({rationRepId:libID,code:code},['sectionId']);
- sectionId = ration? ration.sectionId:null;
- }else {
- let ration = await complementaryRationModel.findOne({userId:userId,compilationId: compilationId,code:code},['sectionId']);
- sectionId = ration?ration.sectionId:null;
- }
- if(sectionId){
- if (from == 'std') {
- rations = await rationItemModel.find({sectionId: sectionId});
- } else {
- rations = await complementaryRationModel.find({userId: userId, sectionId: sectionId});
- }
- rations = _.sortBy(rations,'code');
- }
- return rations
- }
- async function updateSerialNo(serialNoUpdate){
- let tasks=[];
- for(let data of serialNoUpdate){
- let task={
- updateOne:{
- filter:{
- ID:data.ID,
- projectID:data.projectID
- },
- update :{
- serialNo:data.serialNo
- }
- }
- };
- tasks.push(task);
- }
- await ration_model.model.bulkWrite(tasks);
- }
- async function insertNewRation(newData,defaultLibID,std,calQuantity) {//插入新的定额
- let startTime = +new Date();
- if(std){
- newData.code = std.code;
- newData.name = std.name;
- newData.caption = std.caption;
- newData.unit = std.unit;
- newData.libID = std.rationRepId;
- newData.stdID = std.ID;
- newData.content = std.jobContent;
- newData.annotation = std.annotation;
- if (std.chapter) {
- newData.comments = std.chapter.explanation;
- newData.ruleText = std.chapter.ruleText;
- }
- newData.prefix = '';
- newData.from = std.type === 'complementary' ? 'cpt' : 'std';
- if(defaultLibID !== std.rationRepId){//定额是默认定额库中的时,只显示编号;
- newData.prefix = '借';//定额不是默认定额库中的、且不是补充定额库中的时, 在定额编号前显示“借”。
- if(newData.from === 'cpt') newData.prefix = '补';//定额是补充定额库中的时,在定额编号前显示“补”;
- }
- if(std.feeType == undefined || std.feeType == null || std.feeType ==''){//定额取费专业为空的情况下,取项目属性中的定额取费专业ID
- newData.programID = await getProgramForProject(newData.projectID);
- }else {
- newData.programID = std.feeType;
- }
- newData.manageFeeRate = std.manageFeeRate;
- newData.rationAssList = createRationAss(std);
- // calculate ration Quantity
- }
- if(calQuantity){
- await CalculateQuantity(newData,newData.billsItemID,newData.projectID);
- }
- let addRationGLJTime = +new Date();
- console.log("计算消耗量时间-------------------------------"+(addRationGLJTime - startTime));
- await ration_model.model.insertMany(newData);
- return newData;
- /*ration_model.model.create(newData);
- return newData;*/
- }
- async function replaceRations(userID,data,compilation) {
- let searchDao = new SearchDao();
- let recodes = [];
- for(let recode of data.nodeInfo){
- let stdRation = await searchDao.getRationItem(userID,compilation._id,data.libIDs,recode.newCode, null);
- let newRecode = await replaceRation(recode,stdRation,data.defaultLibID,data.projectID,data.calQuantity,compilation,data.cleanzmhs);
- if(newRecode){
- recodes.push(newRecode);
- }else {
- break;
- }
- }
- return recodes;
- }
- async function getDefaultProgramID(data) {
- let searchDao = new SearchDao();
- let programID;
- let std = await searchDao.getRationItem(data.userID,data.compilationId,[data.libID],data.code, null);
- if(std == null||std ==undefined || std.feeType == undefined || std.feeType == null || std.feeType ==''){//定额取费专业为空的情况下,取项目属性中的定额取费专业ID
- programID = await getProgramForProject(data.projectID);
- }else {
- programID = std.feeType;
- }
- return programID;
- }
- async function replaceRation(nodeInfo,stdRation,defaultLibID,projectID,calQuantity,compilation,cleanzmhs) {
- if(nodeInfo.newCode == null||nodeInfo.newCode ==""){//说明是删除编号,则要变成一条空定额
- await deleRationSubRecode(projectID,nodeInfo.ID);//删除定额下挂的各种数据,如定额工料机等
- return await setEmptyRation(projectID,nodeInfo.ID);
- }else if(stdRation){
- await deleRationSubRecode(projectID,nodeInfo.ID,cleanzmhs);//删除定额下挂的各种数据,如定额工料机等
- let newRation = await updateRation(stdRation,defaultLibID,nodeInfo.ID,nodeInfo.billsItemID,projectID,calQuantity,cleanzmhs);//生成并插入新的定额
- return await addRationSubList(stdRation,newRation,nodeInfo.needInstall,compilation,cleanzmhs);
- }else {
- return null;
- }
- }
- async function addRationSubList(stdRation,newRation,needInstall,compilation,cleanzmhs=false) {
- let startTime = +new Date();
- let [ration_gljs,projectGLJList] = await addRationGLJ(stdRation,newRation,compilation);
- let addRationGLJTime = +new Date();
- console.log("添加定额工料机时间-----"+(addRationGLJTime - startTime));
- let ration_coes = await addRationCoe(stdRation,newRation,compilation);
- let addRationCoeTime = +new Date();
- console.log("添加定额coe时间-----"+(addRationCoeTime - addRationGLJTime));
- let ration_installations = [];
- let ration_template = [];
- if(cleanzmhs == false){//清除子目换算即cleanzmh==true时 模板子目、安装增加费不用恢复成标准的
- if(needInstall && stdRation.type == 'std'){//只有标准的定额才有安装增加费,补充的定额没有安装增加费
- ration_installations = await addRationInstallFee(stdRation,newRation);
- }
- let addRationInstallFeeTime = +new Date();
- console.log("添加定额install时间-----"+(addRationInstallFeeTime - addRationCoeTime));
- //添加定额模板子目
- ration_template = await addRationTemplate(stdRation,newRation);
- }else if(newRation.areaIncreaseFee == true){//清空子目换算时,如果有面积增加费,子目调整状态要生成
- let t = await glj_calculate_facade.calculateQuantity({rationID:newRation.ID},true);
- newRation.adjustState = t.adjustState;
- }
- return {ration:newRation,ration_gljs:ration_gljs,ration_coes:ration_coes,ration_installations:ration_installations,ration_templates:ration_template?[ration_template]:[],projectGLJList:projectGLJList};
- }
- async function addRationInstallFee(std,newRation) {
- let install_fee_list = [];
- if(std.hasOwnProperty('rationInstList') && std.rationInstList.length > 0){
- let installFee = await installationFeeModel.findOne({'projectID': newRation.projectID});
- if(!installFee) return;//如果没有找到项目对应的安装增加费,则不添加
- for(let ri of std.rationInstList){
- let feeItem = _.find(installFee.installFeeItem,{'ID':ri.feeItemId});
- let section = _.find(installFee.installSection,{'ID':ri.sectionId});
- if(feeItem&§ion){
- let tem_r_i = {
- libID:installFee.libID,
- projectID:newRation.projectID,
- rationID:newRation.ID,
- feeItemId:feeItem.ID,
- sectionId:section.ID,
- itemName:feeItem.feeItem,
- feeType:feeItem.feeType,
- sectionName:section.name,
- unifiedSetting:1,
- ruleId:''
- };
- if(feeItem.isCal==1&§ion.feeRuleId&§ion.feeRuleId!=''){//勾选记取时并且有规则ID时才读取
- let feeRule = _.find(installFee.feeRule,{'ID':section.feeRuleId});
- if(feeRule){
- tem_r_i.ruleId = feeRule.ID;
- }
- }
- tem_r_i.ID = uuidV1();
- install_fee_list.push(tem_r_i);
- }
- }
- if(install_fee_list.length>0){
- await rationInstallationModel.insertMany(install_fee_list);
- }
- }
- return install_fee_list;
- }
- async function addRationTemplate(std,newRation) {
- let templateList = [];
- if(std.hasOwnProperty('rationTemplateList') && std.rationTemplateList.length > 0){
- for(let tem of std.rationTemplateList){
- let re_ration = await rationItemModel.findOne({rationRepId:std.rationRepId,ID:tem.rationID});
- if(re_ration){
- let template = {
- billID:"",
- fxID:"",
- quantity:"0",
- coe:"0"
- };
- template.code = re_ration.code;
- template.name = re_ration.name;
- template.type = tem.type;
- template.unit = re_ration.unit;
- template.billsLocation = tem.billsLocation;
- template.defaultLocation = tem.billsLocation;
- templateList.push(template)
- }
- }
- }
- if(templateList.length > 0){
- let ration_template = {};
- ration_template.ID = uuidV1();
- ration_template.projectID = newRation.projectID;
- ration_template.rationID = newRation.ID;
- ration_template.createLocation = 1; //默认模板子目分别放在措施项目下
- ration_template.templateList = templateList;
- await rationTemplateModel.create(ration_template);
- return ration_template;
- }
- return null;
- }
- async function addRationCoe(std,newRation,compilation) {
- let ration_coe_list = [];
- let seq = 0;
- let stdCoeIDs = [];//与comCoeIDs两者不共存
- let comCoeIDs = [];
- let coeMap={};
- if(std.hasOwnProperty('rationCoeList')&&std.rationCoeList.length>0){//添加标准库的工料机
- for(let sub of std.rationCoeList){
- std.type === 'std'?stdCoeIDs.push(sub.ID):comCoeIDs.push(sub.ID);
- }
- let libCoeList = [];
- let seqLibIDs = [];
- if (std.type === 'std'){
- libCoeList = await coeMolde.find({'ID':{'$in':stdCoeIDs}}).lean();
- seqLibIDs = stdCoeIDs;
- }else{
- libCoeList = await compleCoeModel.find({'ID':{'$in':comCoeIDs}}).lean();
- seqLibIDs = comCoeIDs;
- }
- for(let lib of libCoeList){
- coeMap[lib.ID] = lib;
- }
- for(let ID of seqLibIDs){
- let libCoe = coeMap[ID];
- if(libCoe){
- let newCoe = {};
- newCoe.ID = uuidV1();
- newCoe.coeID = ID;
- newCoe.seq = seq;
- newCoe.name = libCoe.name;
- newCoe.content = libCoe.content;
- newCoe.original_code = libCoe.original_code;
- newCoe.option_codes = libCoe.option_codes;
- newCoe.option_list = libCoe.option_list;
- newCoe.isAdjust=0;
- newCoe.coes = libCoe.coes;
- newCoe.rationID = newRation.ID;
- newCoe.projectID = newRation.projectID;
- seq++;
- ration_coe_list.push(newCoe);
- }
- }
- }
- let lastCoe = await getCustomerCoe(newRation.projectID,newRation.ID,seq,compilation);//这个地方加载overWrite需要一些时间
- ration_coe_list.push(lastCoe);
- await ration_coe.insertMany(ration_coe_list);
- return ration_coe_list;
- }
- function getCustomerCoeData() {
- var coeList = [
- {amount:1, operator:'*', gljCode:null, coeType:'定额'},
- { amount:1, operator:'*', gljCode:null, coeType:'人工'},
- { amount:1, operator:'*', gljCode:null, coeType:'材料'},
- { amount:1, operator:'*', gljCode:null, coeType:'机械'},
- { amount:1, operator:'*', gljCode:null, coeType:'主材'},
- { amount:1, operator:'*', gljCode:null, coeType:'设备'}
- ];
- return coeList;
- };
- async function getCustomerCoe(projectID,rationID,seq,compilation){//取自定义乘系数,根据编办不同,内容可能不同
- //生成默认的自定义乘系数
- let lastCoe ={
- coeID:-1,
- name : '自定义系数',
- content:'人工×1,材料×1,机械×1,主材×1,设备×1',
- isAdjust:1,
- seq:seq,
- rationID : rationID,
- projectID : projectID
- };
- lastCoe.ID = uuidV1();
- lastCoe.coes = getCustomerCoeData();
- try {
- //查看编办中有没有重写路径
- if(compilation.overWriteUrl && compilation.overWriteUrl!=""){
- if(compilation.overWriteUrl.indexOf("chongqing_2018")!= -1){
- console.log("重庆overwrite");
- let overWrite = chongqingOverWrite
- if(overWrite.getCusCoeContent) lastCoe.content = overWrite.getCusCoeContent();
- if(overWrite.getCustomerCoeData) lastCoe.coes = overWrite.getCustomerCoeData();
- }
-
- }
- return lastCoe
- }catch (err){
- console.log("读取自定义系数重写文件失败");
- console.log(err.message);
- return lastCoe
- }
- }
- //对于多单价,多组成物消耗量的编办,通过这个方法获取单价、组成物消耗量的字段,
- function getExtendData(property,compilation) {
- return projectDao.getExtendData(property,compilation);
- }
- async function addRationGLJ(std,newRation,compilation) {
- let newRationGLJList = [];
- let rationGLJShowList = [];
- let projectGLJList = [];
- let gljKeyMap = {};
- let mixRatioMap={};
- let gljCodes=[];
- let unitPriceFileId = 0;
- let property = await projectDao.getProjectProperty(newRation.projectID);
- if(property){
- unitPriceFileId = property.unitPriceFile !== undefined ? property.unitPriceFile.id : 0;
- }
- let ext = getExtendData(property,compilation);
- let first = +new Date();
- if(std.hasOwnProperty('rationGljList') && std.rationGljList.length > 0){
- let stdGLJID =[];//标准工料机ID数组
- let cptGLJID=[];//补充工料机ID数组
- //let stdGLJID = _.map(std.rationGljList,'gljId');
- for(let tem_g of std.rationGljList){
- if(tem_g.type == 'complementary'){
- cptGLJID.push(tem_g.gljId);
- }else {
- stdGLJID.push(tem_g.gljId);
- }
- }
- let stdGLJList = stdGLJID.length > 0 ? await std_glj_lib_gljList_model.find({'ID':{'$in':stdGLJID}}):[];//速度优化-------先一次性取出所有的工料机列表
- let stdGLJMap = _.indexBy(stdGLJList, 'ID');
- let cptGLJList = cptGLJID.length > 0 ? await complementary_glj_model.find({'userId':std.userId,'ID':{'$in':cptGLJID}}):[];
- let cptGLJMap = _.indexBy(cptGLJList, 'ID');
- let stdGLJMapTime = +new Date();
- console.log("找到工料机映射表时间-------------------------------"+(stdGLJMapTime - first));
- for(let sub of std.rationGljList){
- let newGLJ = {};
- newGLJ.ID = uuidV1();
- newGLJ.projectID = newRation.projectID;
- newGLJ.GLJID = sub.gljId;
- newGLJ.rationID = newRation.ID;
- newGLJ.billsItemID = newRation.billsItemID;
- newGLJ.rationItemQuantity = sub.consumeAmt;
- newGLJ.quantity = sub.consumeAmt;
- newGLJ.glj_repository_id = std.rationRepId;
- let std_glj = null;
- if(sub.type == 'complementary'){//有可能来自标准工料机库或补充工料机库
- std_glj = cptGLJMap[sub.gljId];
- newGLJ.from = 'cpt';
- }else {
- std_glj = stdGLJMap[sub.gljId];
- newGLJ.from = 'std';
- }
- //多单价情况处理
- if(ext && ext.priceField && std_glj && std_glj.priceProperty && std_glj.priceProperty[ext.priceField] !== null && std_glj.priceProperty[ext.priceField] !== undefined){
- std_glj.basePrice = std_glj.priceProperty[ext.priceField];
- }
- if(std_glj){
- newGLJ.name = std_glj.name;
- newGLJ.code = std_glj.code;
- newGLJ.original_code = std_glj.code;
- newGLJ.unit = std_glj.unit;
- newGLJ.specs = std_glj.specs;
- newGLJ.model = std_glj.model;
- newGLJ.basePrice = std_glj.basePrice;
- newGLJ.marketPrice = std_glj.basePrice;
- newGLJ.taxRate= std_glj.taxRate;
- newGLJ.shortName = std_glj.shortName;
- newGLJ.type = std_glj.gljType;
- newGLJ.repositoryId = std_glj.repositoryId;
- newGLJ.adjCoe = std_glj.adjCoe;
- newGLJ.materialType = std_glj.materialType;
- newGLJ.materialCoe = std_glj.materialCoe;
- newGLJ.materialIndexType = std_glj.materialIndexType;
- newGLJ.materialIndexUnit = std_glj.materialIndexUnit;
- newGLJ.materialIndexCoe = std_glj.materialIndexCoe;
- newGLJ.createType = 'normal';
- let tindex = getIndex(newGLJ);
- if(std_glj.component && std_glj.component.length > 0) mixRatioMap[tindex] = std_glj.component;
- let tdata = ration_glj_facade.getGLJSearchInfo(newGLJ);
- gljKeyMap[tindex] = tdata;
- gljCodes.push(tdata.code);
- newRationGLJList.push(newGLJ);
- // let [info,projectGLJ] = await ration_glj_facade.getInfoFromProjectGLJ(newGLJ,unitPriceFileId,ext);
- // newGLJ = ration_glj_facade.createNewRecord(info);
- // newRationGLJList.push(newGLJ);
- // rationGLJShowList.push(info);
- // projectGLJList.push(projectGLJ)
- }
- //let InfoFromProjectGLJ = +new Date();
- //console.log("找到项目工料机时间-------------------------------"+(InfoFromProjectGLJ - std_gljTime));
- }
- [newRationGLJList, projectGLJList] = await getProjectGLJinfo(newRation.projectID,newRationGLJList,gljKeyMap,gljCodes,mixRatioMap,unitPriceFileId,ext);
- }
- let before = +new Date();
- console.log("总查询时间为-------------------------------"+(before-first));
- if(newRationGLJList.length>0){
- await ration_glj.insertMany(newRationGLJList);
- }
- let after = +new Date();
- console.log("实际插入时间为-------------------------------"+(after-before));
- console.log("总操作时间为-------------------------------"+(after-first));
- return [newRationGLJList,projectGLJList]
- }
- async function getProjectGLJinfo(projectID,t_newRationGLJList,gljKeyMap,gljCodes,mixRatioMap,unitPriceFileId,ext){//批量插入或查找项目工料机信息
- //先根据工料机编号在项目工料机中查找工料机是否存在
- let projectGLJMap={};
- let projectGLJList = [];
- let newProjectGLJList=[];//工料机ID要重新去取
- let connectKeyList = [];
- let newRationGLJList = [];
- let gljListModel = new GLJListModel();
- let t_projectGLJList = await projectGLJModel.find({'project_id':projectID,'code':{'$in':gljCodes}}).lean();
- for(let pg of t_projectGLJList){
- let pindex = getIndex(pg);
- projectGLJMap[pindex] = pg;
- }
- for(let key in gljKeyMap){
- if(!projectGLJMap[key]){//如果项目工料机不存在,则添加
- newProjectGLJList.push(gljKeyMap[key]);
- projectGLJMap[key] = gljKeyMap[key];
- }
- //查看组成物
- if(gljListModel.ownCompositionTypes.indexOf(gljKeyMap[key].type)!=-1){//有组成物的类型
- connectKeyList.push(key);
- }
- }
- let [existMixRatioMap,mixRatioInsertData,missCodeList] = await getMixRatioInfo(projectID,projectGLJMap,newProjectGLJList,mixRatioMap,connectKeyList,unitPriceFileId,ext);
- if(missCodeList.length > 0) gljCodes = gljCodes.concat(missCodeList);
-
-
- let [unitPriceMap,newUnitPriceList] = await getUnitPriceData(newProjectGLJList,gljCodes,unitPriceFileId);
- if(newUnitPriceList.length > 0) await unitPriceModel.insertMany(newUnitPriceList);
- if(mixRatioInsertData.length > 0) await mixRatioModel.insertMany(mixRatioInsertData);
- //插入项目工料机
- if(newProjectGLJList.length > 0){
- await setIDfromCounter("glj_list",newProjectGLJList);
- await projectGLJModel.insertMany(newProjectGLJList);
- }
- //组装数据
- for(let ration_glj of t_newRationGLJList){
- let rkey = getIndex(ration_glj);
- let pglj = projectGLJMap[rkey];
- let subList = [];
- setUnitPrice(pglj,unitPriceMap);
- if(existMixRatioMap[rkey]){//如果有组成物
- for(let m of existMixRatioMap[rkey]){
- let mpglj = projectGLJMap[getIndex(m)]
- if(mpglj){
- let cglj = _.clone(mpglj);
- setUnitPrice(cglj,unitPriceMap);
- cglj.ratio_data = m;
- subList.push(cglj);
- }else{
- throw `组成物${m.name}对应的项目工料机没有找到`;
- }
- }
- pglj.subList =subList;
- }
- ration_glj.projectGLJID = pglj.id;
- newRationGLJList.push(ration_glj_facade.createNewRecord(ration_glj));
- projectGLJList.push(pglj);
- }
- return [newRationGLJList, projectGLJList];
- function setUnitPrice(p,unitPriceMap){
- p.unit_price = unitPriceMap[getIndex(p)];
- }
- }
- async function getUnitPriceData(newProjectGLJList,gljCodes,unitPriceFileId){
- let unitPriceMap = {};
- let newUnitPriceList = [];
- let unitPriceList = await unitPriceModel.find({unit_price_file_id: unitPriceFileId,'code':{'$in':gljCodes}}).lean();
- for(let u of unitPriceList){
- unitPriceMap[getIndex(u)]=u;
- }
- for(let np of newProjectGLJList){
- let pkey = getIndex(np);
- if(unitPriceMap[pkey]) continue;
- let insertData = {
- code: np.code,
- base_price: np.base_price,
- market_price: np.market_price,
- unit_price_file_id: unitPriceFileId,
- name: np.name,
- taxRate:np.taxRate,
- specs:np.specs?np.specs:'',
- original_code:np.original_code,
- unit:np.unit?np.unit:'',
- type: np.type,
- short_name: np.shortName !== undefined ? np.shortName : '',
- glj_id: np.glj_id,
- is_add:0,
- grossWeightCoe:np.grossWeightCoe,
- purchaseStorageRate:np.purchaseStorageRate,
- offSiteTransportLossRate:np.offSiteTransportLossRate,
- handlingLossRate:np.handlingLossRate
- };
- if(np.from=='cpt') insertData.is_add=1;//如果是来自补充工料机,则都添加新增标记
- if(insertData.code != insertData.original_code) insertData.is_add=1;//添加的时候如果是复制整块来的,可能在源项目中是新增的工料机,这里也要添上(暂时可能还用不到)
- newUnitPriceList.push(insertData);
- unitPriceMap[pkey] = insertData;
- }
- if(newUnitPriceList.length > 0) await setIDfromCounter("unit_price",newUnitPriceList);
- return [unitPriceMap,newUnitPriceList];
- }
- async function getMixRatioInfo(projectID,projectGLJMap,newProjectGLJList,mixRatioMap,connectKeyList,unitPriceFileId,ext){//取组成物信息,得到缺少的组成物情况
- let missCodeList = []; //所有组成物信息的编码,用来统一查询对应的项目工料机是否存在
- let existMixRatioMap ={};
- let codeMap={};//用来去重
- let mixRatioInsertData = [];
- // 1. 先检查现在的组成物表中,是否有相关信息 - 生成映射记录
- if(connectKeyList.length > 0){//有组成物的话从数据库中取出组成物信息
- let mixRatioList = await mixRatioModel.find({'unit_price_file_id': unitPriceFileId,'connect_key': {'$in':connectKeyList}}).lean();
- for(let m of mixRatioList){
- //组成物信息分组,查看哪些是已经存在的
- existMixRatioMap[m.connect_key]?existMixRatioMap[m.connect_key].push(m):existMixRatioMap[m.connect_key]=[m];
- //查看组成物对应的项目工料机是否存在,如果不存在,要插入项目工料机
- let mkey = getIndex(m);
- if(!projectGLJMap[mkey] && !codeMap[m.code]){//如果之前查出来的项目工料机中不包含组成物的信息,要加到missCode里面再查找一次项目工料机看是否存在
- missCodeList.push(m.code);
- codeMap[m.code] = true;
- }
- }
- // 2 将第一步得到的映射表 与在标准库查询父工料机得到的映射表对比,得出哪些组物成还需要添加,获得库ID
- let stdIDs = [];
- let comIDs = [];
- let missMixRatioGroup = [];
- for(let ck of connectKeyList){//查看项目中组成物信息是否已经存在,如果不存在,则用插定额时获取的组成物信息从数据库中获取
- if(!existMixRatioMap[ck] && mixRatioMap[ck] && mixRatioMap[ck].length > 0){//组成物信息不存在
- let pglj = projectGLJMap[ck];//取出父数据
- let from = pglj.from === undefined|| pglj.from ===null || pglj.from === ""?'std' : pglj.from;
- for(let c of mixRatioMap[ck]){
- if(from == "std"){//标准的工料机只来自标准的
- stdIDs.push(c.ID);
- }else{
- c.isStd?stdIDs.push(c.ID):comIDs.push(c.ID);
- }
- }
- missMixRatioGroup.push({'connect_key':ck,'list':mixRatioMap[ck],'from':from});
- }
- }
- //3.统一查询所有组成物在标准库中的详细信息
- let stdMixMap = {};
- //整理需插入的组成物列表的数据
- //来自标准工料机
- if(stdIDs.length > 0){
- stdIDs = _.uniq(stdIDs);//去重
- let stdMixList = await std_glj_lib_gljList_model.find({'ID':{'$in':stdIDs}}).lean();
- for(let sm of stdMixList){
- stdMixMap[sm.ID] = sm;
- let skey = getIndex(sm,['code','name','specs','unit','gljType']);
- if(!projectGLJMap[skey] && !codeMap[sm.code]){
- missCodeList.push(sm.code);
- codeMap[sm.code] = true;
- }
- }
- }
- //来自组成物工料机
- let comMixMap = {};
- if(comIDs.length > 0){
- comIDs = _.uniq(comIDs);//去重
- let comMixList = await complementaryGljLibModel.find({'ID':{'$in':comIDs}}).lean();
- for(let cm of comMixList){
- comMixMap[cm.ID] = cm;
- let ckey = getIndex(cm,['code','name','specs','unit','gljType']);
- if(!projectGLJMap[ckey] && codeMap[cm.code]){
- missCodeList.push(cm.code);
- codeMap[cm.code] = true;
- }
- }
- }
-
- //4.生成需要插入组成物表的数据
- for(let mg of missMixRatioGroup){//整理需要插入组成物列表的数据
- for(let tc of mg.list){
- let consumpiton = tc.consumeAmt;
- //只有标准的工料机的组成物才会有多单价、多组成物消耗量的情况
- if(mg.from == 'std' && ext && ext.quantityField &&( tc.consumeAmtProperty[ext.quantityField]!= undefined && tc.consumeAmtProperty[ext.quantityField]!=null)){
- consumpiton = tc.consumeAmtProperty[ext.quantityField];
- }
- let mfrom = mg.from == 'std' || tc.isStd?'std':'cpt';
- let tmp = mfrom == 'std'?stdMixMap[tc.ID]:comMixMap[tc.ID];//取出之前库中查到的工料机
- let mixRatioData = {
- consumption: consumpiton,
- glj_id: tmp.ID,
- unit_price_file_id: unitPriceFileId,
- connect_key: mg.connect_key,
- type: tmp.gljType,
- code: tmp.code,
- specs:tmp.specs?tmp.specs:"",
- name:tmp.name,
- unit:tmp.unit?tmp.unit:'',
- from:mfrom
- };
- mixRatioInsertData.push(mixRatioData);
- }
- }
- if(mixRatioInsertData.length > 0) await setIDfromCounter("mix_ratio",mixRatioInsertData,existMixRatioMap,'connect_key');
- //await mixRatioModel.insertMany(mixRatioInsertData); 因为没有事务添加组成物数据要放在添加单价文件数据之后
-
- //5.查询组成物对应的项目工料机是否存在,如果不存在,生成项目工料机信息
- let projectGLJList = await projectGLJModel.find({'project_id':projectID,'code':{'$in':missCodeList}}).lean();
- for(let pg of projectGLJList){
- let pindex = getIndex(pg);
- projectGLJMap[pindex] = pg;
- }
- let lessMix = [];//组成物表存在,项目工料机不存在的数据
- let lessMixMap = {};//防止重复添加
- for(let connect_key in existMixRatioMap){
- let mixRatios = existMixRatioMap[connect_key];
- for(let m of mixRatios){
- let mk = getIndex(m);
- if(!projectGLJMap[mk] && !lessMixMap[mk]){//如果组成物对应的项目工料机不存在
- let nglj = null;
- if(m.from == 'std'){//这里有值,说明是刚添加到组成物文件中的数据
- nglj = stdMixMap[m.glj_id];
- }else if(m.from == 'cpt'){//这里有值,说明是刚添加到组成物文件中的数据
- nglj = comMixMap[m.glj_id];
- }
- if(nglj){
- nglj.from = m.from;
- let np = getProjectGLJNewData(nglj,projectID,ext);
- newProjectGLJList.push(np);
- projectGLJMap[mk] = np;
- }else{//这里没找到,说明是组成物文件里有,但是项目工料机没有的数据
- lessMix.push(m);
- }
- lessMixMap[mk] = true;//只要处理过一次,就不用再重新处理了,机械组成物,比如柴油这些,会出现多次
- }
- }
- }
- //6. 组成物文件里有,但是项目工料机没有的数据(共用单价文件等情况产生)
- let lessIDList=[];
- let uniqMap ={};//去重
- let lessStdMix = [];//防止组成物中改了名称等,但是通过glj_id取出来的是还没改前的原始数据
- if(lessMix.length > 0){
- for(let lm of lessMix){
- let parentglj = projectGLJMap[lm.connect_key];
- if(!parentglj) throw `含有组成物工料机${lm.connect_key},没有找到,添加定额失败`;
- if((parentglj.from == "std" || lm.from == "std") && lm.code!="80CCS"){//车船税特殊处理
- if(!uniqMap[lm.glj_id]){
- lessIDList.push(lm.glj_id);
- uniqMap[lm.glj_id] = lm;
- }
- lessStdMix.push(lm);
- }else {//来自组成物的直接设置
- lm.from = 'cpt';
- lm.gljType = lm.type;
- let t_mg = getProjectGLJNewData(lm,projectID);
- newProjectGLJList.push(t_mg);
- projectGLJMap[getIndex(lm)] = t_mg;
- }
- }
- }
- if(lessIDList.length > 0){
- let less_stds = await std_glj_lib_gljList_model.find({'ID':{'$in':lessIDList}}).lean();
- let less_stds_map = {};
- for(let les of less_stds){
- less_stds_map[les.ID] = les;
- }
- for(let t_l_m of lessStdMix){
- let t_nglj = less_stds_map[t_l_m.glj_id];
- t_nglj.from = 'std';
- //防止组成物中改了名称等,但是通过glj_id取出来的是还没改前的原始数据
- t_nglj.name = t_l_m.name;
- t_nglj.code = t_l_m.code;
- t_nglj.gljType = t_l_m.type;
- t_nglj.specs = t_l_m.specs;
- t_nglj.unit = t_l_m.unit;
- let t_np = getProjectGLJNewData(t_nglj,projectID,ext);
- newProjectGLJList.push(t_np);
- projectGLJMap[getIndex(t_l_m)] = t_np;
- }
- }
- }
- return [existMixRatioMap,mixRatioInsertData,missCodeList]
- }
- function getProjectGLJNewData(tmp,projectId,ext){
- let gljData = {
- glj_id: tmp.ID,
- repositoryId:tmp.repositoryId,
- project_id: projectId,
- code: tmp.code,
- name: tmp.name,
- specs: tmp.specs?tmp.specs:'',
- unit: tmp.unit === undefined ? '' : tmp.unit,
- type: tmp.gljType,
- adjCoe:tmp.adjCoe,
- original_code:tmp.code,
- materialType: tmp.materialType, //三材类别
- materialCoe: tmp.materialCoe,
- base_price: tmp.basePrice,
- market_price: tmp.basePrice,
- is_evaluate:0,
- is_eval_material:0,
- no_tax_eqp:0,
- is_adjust_price:0,
- is_main_material:0,
- is_contractor_material:0,
- supply_quantity:0,
- supply:0,
- from:tmp.from?tmp.from:"std"
- };
- // 现在定额库可以引用其他费用定额的,比如广东可能套用部颁的定额,因此就算广东费用定额是多单价的,也可能会引用单个单价的人材机
- if(gljData.from == 'std' && ext && ext.priceField &&( tmp.priceProperty && tmp.priceProperty[ext.priceField]!= undefined && tmp.priceProperty[ext.priceField]!=null)){
- const basePrice = scMathUtil.roundTo(tmp.priceProperty[ext.priceField],-6);
- gljData.base_price = basePrice;
- gljData.market_price = basePrice;
- }
- return gljData;
- }
- async function setIDfromCounter(name,list,map,keyfield){//map,keyfield
- let update = {$inc: {sequence_value: list.length}};
- let condition = {_id: name};
- let options = {new: true};
- // 先查找更新
- let counter = await counterModel.findOneAndUpdate(condition, update, options);
- let firstID = counter.sequence_value - (list.length - 1);
- for(let a of list){
- a.id = firstID;
- firstID+=1
- if(map && keyfield){
- let key = a[keyfield];
- map[key]?map[key].push(a):map[key]=[a]
- }
- }
- }
- async function deleRationSubRecode(projectID,rationID,cleanzmhs=false) {//删除挂在定额下的数据,如工程量明细,定额工料机等
- let delete_query={projectID: projectID, rationID: rationID};
- //删除工程量明细
- await deleteSubListByQuery(delete_query,cleanzmhs) ;
- }
- async function deleteSubListByQuery(delete_query,cleanzmhs=false) {
- if(cleanzmhs == false){//清空子目换算即cleanzmh==true时不需要清空工程量明细、模板关联子目、安装增加费
- await quantity_detail.deleteByQuery(delete_query) ;//删除工程量明细
- await rationInstallationModel.deleteMany(delete_query);//删除安装增加费
- await rationTemplateModel.deleteMany(delete_query);//删除模板关联子目
- }
- //to do稳定土也要删除
- await ration_coe.deleteMany(delete_query);//删除附注条件
- await ration_glj.deleteMany(delete_query);//删除定额工料机
- }
- async function updateCoeAdjust(data,compilation) {
- let replace = [],projectGLJList=[];
- await ration_coe.update({ID:data.ID},data.doc);
- //添加单个工料机的情况
- if (data.add.length > 0){
- let [tg,pl] = await ration_glj_facade.insertAddTypeGLJ(data.add,compilation);
- if(pl.length > 0) projectGLJList = projectGLJList.concat(pl);
- }
- if(data.delete.length > 0) await ration_glj_facade.deleteGLJ(data.delete);
- //替换工料机的情况
- if (data.replace.length > 0){
- for(let r of data.replace){
- let [rg,pg] = await ration_glj_facade.replaceGLJByData(r,compilation);
- replace.push(rg) ;
- projectGLJList.push(pg);
- }
- }
- let cal_result = await glj_calculate_facade.calculateQuantity({projectID:data.projectID,rationID:data.rationID},null,true);
- let coe = {
- query:{ID:data.ID,projectID:data.projectID},
- doc:data.doc
- };
- let ration_glj ={
- quantityRefresh:true,
- glj_result:cal_result.glj_result
- };
- let ration = {
- ID:cal_result.rationID,
- adjustState:cal_result.adjustState,
- name:cal_result.rationName
- };
- return {coe:coe,ration_glj:ration_glj,ration:ration,add:data.add,delete:data.delete,replace:replace,projectGLJList:projectGLJList}
- }
- async function updateRation(std,defaultLibID,rationID,billsItemID,projectID,calQuantity,cleanzmh=false) {
- // insertNewRation
- let ration ={};
- ration.code = std.code;
- ration.name = std.name;
- ration.caption = std.caption;
- ration.unit = std.unit;
- if (std.type === 'std') {
- ration.libID = std.rationRepId;
- ration.stdID = std.ID;
- }
- ration.content = std.jobContent;
- ration.manageFeeRate = std.manageFeeRate;
- ration.adjustState = '';
- ration.isFromDetail=0;
- ration.isSubcontract=false;
- ration.fees=[];
- if (std.chapter) {
- ration.comments = std.chapter.explanation;
- ration.ruleText = std.chapter.ruleText;
- }
- ration.from = std.type === 'complementary' ? 'cpt' : 'std';
- //定额前缀 none:0, complementary:1, borrow: 2
- ration.prefix = '';
- if(parseInt(defaultLibID) !== std.rationRepId){//定额是默认定额库中的时,只显示编号;
- ration.prefix = '借';//定额不是默认定额库中的、且不是补充定额库中的时, 在定额编号前显示“借”。
- if(ration.from === 'cpt') ration.prefix = '补';//定额是补充定额库中的时,在定额编号前显示“补”;
- }
- ration.rationAssList = createRationAss(std);//生成辅助定额
- if(cleanzmh==false){//如果是清空子目换算,即cleanzmh==true 保留定额工程量、工程量表达式、含量(分解系数)、取费专业(取费类别)
- if(std.feeType == undefined || std.feeType == null || std.feeType ==''){//定额取费专业为空的情况下,取项目属性中的定额取费专业ID
- ration.programID = await getProgramForProject(projectID);
- }else {
- ration.programID = std.feeType;
- }
- if(calQuantity){
- await CalculateQuantity(ration,billsItemID,projectID);
- }
- }
- let unsetObject = {
- "marketUnitFee":1,
- 'marketTotalFee':1,
- "maskName":1
- };
- let newRation = await ration_model.model.findOneAndUpdate({ID:rationID,projectID:projectID},{"$set":ration,"$unset":unsetObject},{new: true});//;
- return newRation;
- }
- async function setEmptyRation(projectID,rationID){
- let ration ={};
- ration.code = "";
- ration.name = "";
- ration.caption = "";
- ration.unit = "";
- ration.libID = null;
- ration.content = "";
- ration.adjustState = '';
- ration.isFromDetail=0;
- ration.isSubcontract=false;
- ration.fees=[];
- ration.comments = "";
- ration.ruleText = "";
- ration.quantity="";
- ration.contain="";
- ration.quantityEXP="";
- ration.from = 'std';
- //定额前缀 none:0, complementary:1, borrow: 2
- ration.prefix = '';
- ration.rationAssList = [];
- ration.marketUnitFee ="";
- ration.marketTotalFee ="";
- ration.maskName = "";
- ration.targetTotalFee ='';
- ration.targetUnitFee = "";
- ration.deleteInfo = null;
- ration.quantityCoe = {};
- ration.rationQuantityCoe="";
- ration.tenderQuantity = "";
- ration.programID = null;
- let newRation = await ration_model.model.findOneAndUpdate({ID:rationID,projectID:projectID},{"$set":ration},{new: true});//;
- return {ration:newRation,ration_gljs:[],ration_coes:[],ration_installs:[]};
- }
- function createRationAss(std) {
- let rationAssList = [];//生成辅助定额
- if(std.hasOwnProperty('rationAssList')&&std.rationAssList.length>0){
- let assGroup = _.groupBy(std.rationAssList,'name');
- for(let key in assGroup){
- let assList = assGroup[key];
- let ass = assList[0];
- ass._doc.actualValue = ass.stdValue;
- ass._doc.isAdjust = 0;
- if(_.isString(ass._doc.assistCode)) ass._doc.assistCode = ass._doc.assistCode.replace("\n","");
- if(_.isString(ass._doc.thirdRationCode)) ass._doc.thirdRationCode = ass._doc.thirdRationCode.replace("\n","");
- if(assList.length > 1){
- ass._doc.groupList = JSON.parse(JSON.stringify(assList)) ;
- ass._doc.maxValue = assList[assList.length-1]._doc.maxValue;
- }
- rationAssList.push(ass);
- }
- }
- return rationAssList;
- }
- async function CalculateQuantity (ration,billsItemID,projectID) {
- // calculate ration Quantity
- let project = await projectModel.findOne({ID:projectID});
- let decimalObject =await decimal_facade.getProjectDecimal(projectID,project);
- let quantity_decimal = (decimalObject&&decimalObject.ration&&decimalObject.ration.quantity)?decimalObject.ration.quantity:3;
- let pbill = await bill_model.model.findOne({projectID:projectID,ID:billsItemID});
- let t_unit = ration.unit?ration.unit.replace(/^\d+/,""):"";
- if(t_unit!=pbill.unit){//如果定额工程量的单位去除前面的数字后不等于清单单位,定额工程量保持不变
- return ;
- }
- let billsQuantity = pbill.quantity ? pbill.quantity : 0;
- let bill_decimal = await decimal_facade.getBillsQuantityDecimal(projectID,pbill.unit,project);
- billsQuantity=scMathUtil.roundForObj(billsQuantity,bill_decimal);
- ration.quantityEXP="QDL";
- ration.quantity = scMathUtil.roundForObj(billsQuantity / FilterNumberFromUnit(ration.unit),quantity_decimal);//不管是否打勾都做转换
- ration.contain = scMathUtil.roundForObj(ration.quantity/billsQuantity,6);
- };
- async function getProgramForProject(projectID){
- let project = await projectModel.findOne({ID:projectID});
- return project.property.engineering;
- }
- function FilterNumberFromUnit (unit) {
- let reg = new RegExp('^[0-9]+');
- if (reg.test(unit)) {
- return parseInt(unit.match(reg)[0]);
- } else {
- return 1;
- }
- };
- function getIndex(obj,tpops){
- let pops = tpops?tpops:['code','name','specs','unit','type'];
- let t_index = '';
- let k_arr=[];
- for(let p of pops){
- let tmpK = (obj[p]==undefined||obj[p]==null||obj[p]=='')?'null':obj[p];
- k_arr.push(tmpK);
- }
- t_index=k_arr.join("|-|");
- return t_index;
- }
|