/** * Created by Mai on 2017/1/18. */ import mongoose from 'mongoose'; import async_c from 'async'; import UnitPriceFileModel from "../../glj/models/unit_price_file_model"; import UnitPriceFiles from '../../glj/models/schemas/unit_price_file'; import {defaultDecimal, billsQuantityDecimal, basicInformation, projectFeature,displaySetting} from './project_property_template'; import fixedFlag from '../../common/const/bills_fixed'; let FeeRateFiles = mongoose.model('fee_rate_file'); let counter = require("../../../public/counter/counter.js"); let newProjController = require('../controllers/new_proj_controller'); let copyProjController = require('../controllers/copy_proj_controller'); let feeRateFacade = require('../../fee_rates/facade/fee_rates_facade'); let labourCoeFacade = require('../../main/facade/labour_coe_facade'); let calcProgramFacade = require('../../main/facade/calc_program_facade'); let logger = require("../../../logs/log_helper").logger; let BillsModel = require("../../main/models/bills").model; let Projects = require("./project_schema"); let projectType = { folder: 'Folder', tender: 'Tender', project: 'Project', engineering: 'Engineering', }; let fileType = { unitPriceFile: 'UnitPriceFile', feeRateFile: 'FeeRateFile' }; let ProjectsDAO = function(){}; ProjectsDAO.prototype.getUserProjects = async function(userId, compilation, callback){ try { let projects = await Projects.find({'$or': [{'userID': userId, 'compilation': compilation, 'deleteInfo': null}, {'userID': userId, 'compilation': compilation, 'deleteInfo.deleted': {'$in': [null, false]}}]}, '-_id'); for(let i = 0 , len = projects.length; i < len; i++){ let proj = projects[i]; let engineeringCost = await BillsModel.find({projectID: proj.ID, 'flags.flag': fixedFlag.ENGINEERINGCOST, 'fees.totalFee': {$exists: true}}); proj._doc.engineeringCost = engineeringCost.length > 0 ? engineeringCost[0].fees[0].totalFee : 0; } callback(0, '', projects); } catch (err){ callback(1, 'Error', null); } }; ProjectsDAO.prototype.getUserProject = function (userId, ProjId, callback) { Projects.findOne({userID: userId, ID: ProjId}, '-_id', function(err, template){ if (err) { callback(1, '找不到标段数据', null); } else { callback(0, '', template); } }); } ProjectsDAO.prototype.updateUserProjects = async function(userId, compilationId, datas, callback){ let data, project, updateLength = 0, hasError = false, deleteInfo = null, i, newProject; let updateAll = function (err) { if (!err){ updateLength += 1; if (updateLength === datas.length) { callback(0, '', datas); } } else { hasError = true; console.log(err); callback(1, '提交数据出错.', null); } }; if (datas){ for (i = 0; i < datas.length && !hasError; i++){ data = datas[i]; if (data.updateData.name !== undefined) { data.updateData.name = data.updateData.name.trim(); } if (data.updateType === 'update') { Projects.update({userID: userId, ID: data.updateData.ID}, data.updateData, updateAll); } else if (data.updateType === 'new') { data.updateData['userID'] = userId; data.updateData['compilation'] = compilationId; data.updateData['createDateTime'] = new Date(); // 如果没有选中单价文件则新增单价文件 if (data.updateData.projType === projectType.tender && data.updateData.property !== null && Object.keys(data.updateData.property.unitPriceFile).length > 0 && data.updateData.property.unitPriceFile.id === '') { let unitPriceFileModel = new UnitPriceFileModel(); let insertData = { name: data.updateData.name, project_id: data.updateData.ID, user_id: userId, root_project_id: data.updateData.property.rootProjectID }; let addResult = await unitPriceFileModel.add(insertData); if (!addResult) { callback(1, '新增单价文件失败.', null); return; } data.updateData.property.unitPriceFile.id = addResult.id; } if(data.updateData.projType === projectType.tender){ //小数位数 data.updateData.property.decimal = defaultDecimal; //清单工程量精度 data.updateData.property.billsQuantityDecimal = billsQuantityDecimal; //基本信息 basicInformation[0]['items'][1]['value'] = data.updateData.property.engineeringName || ''; data.updateData.property.basicInformation = basicInformation; //工程特征 data.updateData.property.projectFeature = projectFeature; //呈现选项 data.updateData.property.displaySetting = displaySetting; data.updateData.property.billsCalcMode = 0; data.updateData.property.zanguCalcMode = 0; } newProject = new Projects(data.updateData); // 查找同级是否存在同名数据 let exist = await this.isExist(userId, compilationId, data.updateData.name, data.updateData.ParentID); if (exist) { callback(1, '同级目录已存在相同名称数据.', null); return; } if(data.updateData.projType==='Tender'){ let feeRateFileID = await feeRateFacade.newFeeRateFile(userId, data.updateData); newProject.property.feeFile = feeRateFileID?feeRateFileID:-1; // 新建人工系数文件 CSL, 2017.10.13 let lcFile = await labourCoeFacade.newProjectLabourCoe(data.updateData); newProject.property.labourCoeFile = lcFile ? lcFile : null; // 新建计算程序文件 CSL, 2017.10.23 let cpFile = await calcProgramFacade.newProjectCalcProgramFile(data.updateData); newProject.property.calcProgramFile = cpFile ? cpFile : null; } newProject.save(async function (err, result) { if (!err && result._doc.projType === projectType.tender) { newProjController.copyTemplateData(result._doc.property, newProject.ID, updateAll); } else { updateAll(err); } }); } else if (data.updateType === 'delete') { deleteInfo = {}; deleteInfo['deleted'] = true; deleteInfo['deleteDateTime'] = new Date(); deleteInfo['deleteBy'] = userId; data.updateData['deleteInfo'] = deleteInfo; //Projects.update({userID: userId, ID: data.updateData.ID}, data.updateData, updateAll); //update try{ if(data.updateData.projType === projectType.project){ let engineerings = await Projects.find({userID: userId, ParentID: data.updateData.ID}); let isExist = false; if(engineerings.length > 0){ for(let j = 0, jLen = engineerings.length; j < jLen; j++){ let e_tenders = await Projects.find({userID: userId, ParentID: engineerings[j].ID}); if(e_tenders.length > 0){ isExist = true; break; } } } if(isExist){//fake await UnitPriceFiles.update({user_id: userId, root_project_id: data.updateData.ID}, {$set: {deleteInfo: deleteInfo}}, {multi: true}); await FeeRateFiles.update({userID: userId, rootProjectID: data.updateData.ID}, {$set: {deleteInfo: deleteInfo}}, {multi: true}); await Projects.update({userID: userId, ID: data.updateData.ID}, data.updateData, updateAll); } else {//true await UnitPriceFiles.remove({user_id: userId, root_project_id: data.updateData.ID}); await FeeRateFiles.remove({userID: userId, rootProjectID: data.updateData.ID}); //await Projects.update({userID: userId, NextSiblingID: data.updateData.ID, deleteInfo: null}, {$set: {NextSiblingID: data.NextSiblingID}}); await Projects.remove({userID: userId, ID: data.updateData.ID}, updateAll); } } else if(data.updateData.projType === projectType.engineering){ let tenders = await Projects.find({userID: userId, ParentID: data.updateData.ID}); if(tenders.length > 0){//fake await Projects.update({userID: userId, ID: data.updateData.ID}, data.updateData, updateAll); } else {//true //await Projects.update({userID: userId, NextSiblingID: data.updateData.ID, deleteInfo: null}, {$set: {NextSiblingID: data.NextSiblingID}}); await Projects.remove({userID: userId, ID: data.updateData.ID}, updateAll); } } else if(data.updateData.projType === projectType.tender){//fake await Projects.update({userID: userId, ID: data.updateData.ID}, data.updateData, updateAll); } else if(data.updateData.projType === projectType.folder){//true await Projects.remove({userID: userId, ID: data.updateData.ID}, updateAll); } else throw '未知文件类型,删除失败!'; } catch (error){ callback(1, error, null); } } else { hasError = true; callback(1, '提交数据错误.', null); } } } }; ProjectsDAO.prototype.udpateUserFiles = async function (userId, datas, callback){ let updateType = {update: 'update', delete: 'delete'}; let deleteInfo = Object.create(null); deleteInfo.deleted = true; deleteInfo.deleteBy = userId; deleteInfo.deleteDateTime = new Date(); try{ for(let i = 0, len = datas.length; i < len; i++){ let data = datas[i]; if(data.updateType === updateType.update && data.fileType === fileType.unitPriceFile){ await UnitPriceFiles.update({user_id: userId, id: parseInt(data.updateData.id)}, data.updateData); await Projects.update({userID: userId, 'property.unitPriceFile.id': data.updateData.id}, {$set: {'property.unitPriceFile.name': data.updateData.name}}); } else if(data.updateType === updateType.update && data.fileType === fileType.feeRateFile){ await FeeRateFiles.update({userID: userId, ID: data.updateData.ID}, data.updateData); await Projects.update({userID: userId, 'property.feeFile.id': data.updateData.ID}, {$set: {'property.feeFile.name': data.updateData.name}}); } else if(data.updateType === updateType.delete && data.fileType === fileType.unitPriceFile){ data.updateData.deleteInfo = deleteInfo; await UnitPriceFiles.update({user_id: userId, id: parseInt(data.updateData.id)}, data.updateData); await Projects.update({userID: userId, 'property.feeFile.id': data.updateData.id}, {$set: {'property.feeFile.name': data.updateData.name}}); } else if(data.updateType === updateType.delete && data.fileType === fileType.feeRateFile){ data.updateData.deleteInfo = deleteInfo; await FeeRateFiles.update({userID: userId, ID: data.updateData.ID}, data.updateData); } else throw '未知文件类型,删除失败' } callback(false, '删除成功', null); } catch(error){ callback(true, '删除失败', null); } }; ProjectsDAO.prototype.copyUserProjects = function (userId, datas, callback) { let data, project, updateLength = 0, hasError = false, deleteInfo = null, tempType = 1, i; let updateAll = function (err) { if (!err){ updateLength += 1; if (updateLength === datas.length) { callback(0, '', datas); } } else { hasError = true; callback(1, '提交数据出错.', null); } }; if (datas) { for (i = 0; i < datas.length && !hasError; i++) { data = datas[i]; if (data.updateType === 'update') { Projects.update({userID: userId, ID: data.updateData.ID}, data.updateData, updateAll) } else if (data.updateType === 'copy') { data.updateData['userID'] = userId; data.updateData['createDateTime'] = new Date(); let newProject = new Projects(data.updateData); newProject['srcProjectId'] = data.srcProjectId; newProject.save(function (err, result) { if (!err && result._doc.projType === 'Tender') { copyProjController.copyProjectData(newProject.srcProjectId, result._doc.ID, updateAll); } else { updateAll(err); } }); } else { hasError = true; callback(1, '提交数据错误', null); } } } }; ProjectsDAO.prototype.rename = async function (userId, compilationId, data, callback){ try { if (data.id === undefined || data.id === '') { throw '数据错误!'; } if (data.newName === undefined || data.newName === '') { throw '请填写名称!'; } data.newName = data.newName.trim(); // 查找同级是否存在同名数据 let exist = await this.isExist(userId, compilationId, data.newName, data.parentID); if (exist) { throw '同级目录已存在相同名称数据'; } Projects.update({userID: userId, ID: data.id}, {name: data.newName}, function(err){ if (err){ throw '项目不存在'; } }); } catch (error) { callback(1, error, null); return; } callback(0, ''); }; ProjectsDAO.prototype.beforeOpenProject = function (userId, projectId, updateData, callback){ updateData['recentDateTime'] = new Date(); Projects.update({userID: userId, ID: projectId}, updateData, function(err){ if (err){ callback(1, '项目不存在.'); } else { callback(0, ''); } }); }; ProjectsDAO.prototype.getNewProjectID = function (count, callback) { counter.counterDAO.getIDAfterCount(counter.moduleName.project, count, function (err, result) { let highID = result.value.sequence_value; if (!err) { callback(0, '', {lowID: highID - count + 1, highID: highID}); } else { callback(1, '获取主键失败', null); } }); }; ProjectsDAO.prototype.getProject = function (key, callback) { if (callback) { Projects.findOne({'_id': key}, function (err, result) { if (err) { callback(1, '查找标段失败'); } else { callback(0, result); } }); } else { return Projects.findOne({'ID': key}).exec(); } }; ProjectsDAO.prototype.getProjectsByIds = async function (userId, compilationId, ids){ return await Projects.find({userID: userId, compilation: compilationId, ID: {$in: ids}}); }; ProjectsDAO.prototype.getGCFiles = async function (fileType, userID){ let rst; if(fileType === 'UnitPriceFile'){ let unitPriceFileModel = new UnitPriceFileModel(); rst = await unitPriceFileModel.getGCUnitPriceFiles(userID); } else if(fileType === 'FeeRateFile'){ rst = await feeRateFacade.getGCFeeRateFiles(userID); } else { let isExist = false; for(let type in projectType){ if(projectType[type] === fileType) { isExist = true; break; } } if(!isExist) throw '不存在此项目类型!'; rst = await Projects.find({userID: userID, projType: fileType, 'deleteInfo.deleted': true}); } return rst; }; ProjectsDAO.prototype.getFirstNodeID = async function (userID, pid) { let nodes = await Projects.find({userID: userID, ParentID: pid, deleteInfo: null}); if(nodes.length === 0){ return -1; } else { let prefix = 'ID_'; let chain = Object.create(null); for(let i = 0, len = nodes.length; i < len; i++){ let nodeDoc = nodes[i]._doc; let node = Object.create(null); node.ID = nodeDoc.ID; node.NextSiblingID = nodeDoc.NextSiblingID; chain[prefix + node.ID] = node; } for(let i =0, len = nodes.length; i < len; i++){ let nodeDoc = nodes[i]._doc; let next = nodeDoc.NextSiblingID > 0 ? chain[prefix + nodeDoc.NextSiblingID] : null; chain[prefix + nodeDoc.ID].next = next; if(next){ next.pre = chain[prefix + nodeDoc.ID] } } for(let node in chain){ let pre = chain[node].pre || null; if(!pre){ return chain[node].ID; } } } }; ProjectsDAO.prototype.recGC = async function(userID, datas, callback){ let functions = []; let updateDatas = []; for(let i = 0, len = datas.length; i < len; i++){ if(datas[i].findData.ParentID !== undefined && datas[i].findData.NextSiblingID === -1 && !datas[i].findData.deleteInfo){//维护项目管理树 let findNode = await Projects.find(datas[i].findData); if(findNode.length > 0){ datas[i].findData = Object.create(null); datas[i].findData.ID = findNode[0].ID; updateDatas.push(datas[i]); } } else { if(datas[i].updateType === projectType.project && datas[i].updateData.NextSiblingID === undefined){//则为待查询NextSiblingID,前端无法查询 let projData = await Projects.find({userID: userID, ID: datas[i].findData.ID});//建设项目原本可能属于某文件夹、文件夹的存在需要判断 let projPid = projData[0].ParentID; if(projPid !== -1){ let projFolder = await Projects.find({userID: userID, ID: projPid}); if(projFolder.length === 0){//文件夹已不存在 projPid = -1; datas[i].updateData.ParentID = -1; } } let firstNodeID = await this.getFirstNodeID(userID, projPid); datas[i].updateData.NextSiblingID = firstNodeID; } updateDatas.push(datas[i]) } } for(let i = 0, len = updateDatas.length; i < len; i ++){ functions.push((function(data){ return function (cb) { if(data.updateType === fileType.unitPriceFile){ UnitPriceFiles.update({id: parseInt(data.findData.id)}, data.updateData, function (err) { if(err) cb(err); else { Projects.update({userID: userID, 'property.unitPriceFile.id': data.findData.id}, {$set: {'property.unitPriceFile.name': data.updateData.name}}, function (err) { if(err) cb(err); else cb(false); }); } }) } else if(data.updateType === fileType.feeRateFile){ FeeRateFiles.update(data.findData, data.updateData, function (err) { if(err) cb(err); else { Projects.update({userID: userID, 'property.feeFile.id': data.findData.ID}, {$set: {'property.feeFile.name': data.updateData.name}}, function (err) { if(err) cb(err); else cb(false); }); } }); } else{ if(data){ Projects.update(data.findData, data.updateData, function (err) { if(err)cb(err); else cb(false); }); } } } } )(updateDatas[i])); } async_c.parallel(functions, function (err, results) { if(err) callback(err, 'fail', null); else callback(0, 'success', null); }); }; /** * 整理工程专业对应标准库数据 * * @param {Object} data * @return {Boolean} */ ProjectsDAO.prototype.isExist = async function(userId, compilationId, name, parentID) { parentID = parseInt(parentID); if (name === '' || isNaN(parentID)) { return true; } let condition = {userID: userId, compilation: compilationId, ParentID: parentID, name: name, "$or":[{deleteInfo: null}, {"deleteInfo.deleted": false}]}; let count = await Projects.count(condition); return count > 0; }; /** * 获取对应建设项目下所有的单位工程id * * @param {Number} projectId * @return {Promise} */ ProjectsDAO.prototype.getTenderByProjectId = async function(projectId) { let result = []; // 首先获取对应的单位工程id let engineeringData = await Projects.find({ParentID: projectId}); if (engineeringData.length <= 0) { return result; } let engineeringIdList = []; for(let tmp of engineeringData) { engineeringIdList.push(tmp.ID); } // 查找对应的单位工程id let tenderData = await Projects.find({ParentID: {$in: engineeringIdList}}); if (tenderData.length <= 0) { return result; } for(let tmp of tenderData) { result.push(tmp.ID); } return result; }; /** * 根据单价文件id获取对应的标段数据 * * @param {Number} unitPriceFileId * @return {Promise} */ ProjectsDAO.prototype.getTenderByUnitPriceFileId = async function(unitPriceFileId) { let result = []; unitPriceFileId = parseInt(unitPriceFileId); if (isNaN(unitPriceFileId) && unitPriceFileId <= 0) { return result; } let condition = {projType: 'Tender', "property.unitPriceFile.id": unitPriceFileId}; result = await Projects.find(condition); return result; }; /** * 根据项目id获取单价文件列表id * * @param {Number} projectId * @return {Promise} */ ProjectsDAO.prototype.getUnitPriceFileId = async function(projectId) { let result = 0; let projectData = await Projects.findOne({ID: projectId}); if (projectData === null) { return result; } result = projectData.property.unitPriceFile !== undefined ? projectData.property.unitPriceFile.id : 0; return result; }; /** * 获取当前用户的建设项目数据 * * @param {Number} userId * @return {Promise} */ ProjectsDAO.prototype.getUserProjectData = async function(userId) { let projectList = await Projects.find({ '$or': [ {'userID': userId, 'deleteInfo': null, projType: 'Project'}, {'userID': userId, 'deleteInfo.deleted': {'$in': [null, false]}, projType: 'Project'} ] }, {_id: 0, name: 1, ID: 1}); return projectList; }; /** * 更改项目属性中的单价文件 * * @param {Number} projectId * @param {Object} changeInfo * @return {Promise} */ ProjectsDAO.prototype.changeUnitPriceFileInfo = async function(projectId, changeInfo) { projectId = parseInt(projectId); if (isNaN(projectId) || projectId <= 0) { return false; } let result = await Projects.update({ID: projectId}, {"property.unitPriceFile": changeInfo}); return result.ok === 1; }; /** * 更新项目属性 * * @param {Number} projectId - 项目id * @param {Object} propertyData - 项目属性数据 * @return {Promise} */ ProjectsDAO.prototype.updateProjectProperty = async function(projectId, propertyData) { projectId = parseInt(projectId); if (isNaN(projectId) || projectId <= 0 || propertyData.property === undefined || propertyData.data === undefined) { return false; } const updateData = {}; updateData["property." + propertyData.property] = propertyData.data; let result = await Projects.update({ID: projectId}, updateData); return result.ok === 1; }; module.exports ={ project: new ProjectsDAO(), projType: projectType, fileType: fileType };