|
@@ -51,6 +51,7 @@ module.exports={
|
|
|
uploadToken:uploadToken,
|
|
uploadToken:uploadToken,
|
|
|
downLoadProjectFile:downLoadProjectFile,
|
|
downLoadProjectFile:downLoadProjectFile,
|
|
|
importProcessChecking:importProcessChecking,
|
|
importProcessChecking:importProcessChecking,
|
|
|
|
|
+ importInterface,
|
|
|
copyConstructionProject,
|
|
copyConstructionProject,
|
|
|
isTenderOverrun,
|
|
isTenderOverrun,
|
|
|
getWelcomeInfo:getWelcomeInfo
|
|
getWelcomeInfo:getWelcomeInfo
|
|
@@ -65,12 +66,25 @@ let glj_facade = require('../../glj/facade/glj_facade');
|
|
|
let project_facade = require('../../main/facade/project_facade');
|
|
let project_facade = require('../../main/facade/project_facade');
|
|
|
let logger = require("../../../logs/log_helper").logger;
|
|
let logger = require("../../../logs/log_helper").logger;
|
|
|
const uuidV1 = require('uuid/v1');
|
|
const uuidV1 = require('uuid/v1');
|
|
|
|
|
+const billsUtil = require('../../../public/billsUtil');
|
|
|
let projectModel = mongoose.model('projects');
|
|
let projectModel = mongoose.model('projects');
|
|
|
let projectSettingModel = mongoose.model('proj_setting');
|
|
let projectSettingModel = mongoose.model('proj_setting');
|
|
|
let billsModel = mongoose.model('bills');
|
|
let billsModel = mongoose.model('bills');
|
|
|
let rationModel = mongoose.model('ration');
|
|
let rationModel = mongoose.model('ration');
|
|
|
let gljListModel = mongoose.model("glj_list");
|
|
let gljListModel = mongoose.model("glj_list");
|
|
|
let calcProgramsModel = mongoose.model('calc_programs');
|
|
let calcProgramsModel = mongoose.model('calc_programs');
|
|
|
|
|
+const {
|
|
|
|
|
+ defaultDecimal,
|
|
|
|
|
+ billsQuantityDecimal,
|
|
|
|
|
+ displaySetting,
|
|
|
|
|
+ calcOptions,
|
|
|
|
|
+ tenderSetting,
|
|
|
|
|
+ bookmarkSetting
|
|
|
|
|
+} = require('../models/project_property_template');
|
|
|
|
|
+const labourCoeFacade = require('../../main/facade/labour_coe_facade');
|
|
|
|
|
+const calcProgramFacade = require('../../main/facade/calc_program_facade');
|
|
|
|
|
+const mainColLibModel = mongoose.model('std_main_col_lib');
|
|
|
|
|
+const EngineeringLibModel = require("../../users/models/engineering_lib_model");
|
|
|
let labourCoesModel = mongoose.model('labour_coes');
|
|
let labourCoesModel = mongoose.model('labour_coes');
|
|
|
let feeRateModel = mongoose.model('fee_rates');
|
|
let feeRateModel = mongoose.model('fee_rates');
|
|
|
let feeRateFileModel = mongoose.model('fee_rate_file');
|
|
let feeRateFileModel = mongoose.model('fee_rate_file');
|
|
@@ -1723,12 +1737,12 @@ async function doDownLoadAndImport(privateDownloadUrl,info) {
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-async function importProcessChecking(data){
|
|
|
|
|
- let result = {error:0};
|
|
|
|
|
|
|
+async function importProcessChecking(data) {
|
|
|
|
|
+ let result = { error: 0 };
|
|
|
const query = data.key ? { key: data.key } : { userID: data.userID, compilationID: data.compilationID };
|
|
const query = data.key ? { key: data.key } : { userID: data.userID, compilationID: data.compilationID };
|
|
|
let log = await importLogsModel.findOne(query);
|
|
let log = await importLogsModel.findOne(query);
|
|
|
- if(log){
|
|
|
|
|
- if(log.status == "finish"){
|
|
|
|
|
|
|
+ if (log) {
|
|
|
|
|
+ if (log.status == "finish") {
|
|
|
result.status = "complete";
|
|
result.status = "complete";
|
|
|
await importLogsModel.remove(query);
|
|
await importLogsModel.remove(query);
|
|
|
// 获取导入的项目数据
|
|
// 获取导入的项目数据
|
|
@@ -1740,21 +1754,197 @@ async function importProcessChecking(data){
|
|
|
}
|
|
}
|
|
|
result.data = projects;
|
|
result.data = projects;
|
|
|
}
|
|
}
|
|
|
- }else if(log.status == "start"){
|
|
|
|
|
|
|
+ } else if (log.status == "start") {
|
|
|
result.status = "processing";
|
|
result.status = "processing";
|
|
|
result.content = log.content;
|
|
result.content = log.content;
|
|
|
- }else if(log.status == "error"){
|
|
|
|
|
|
|
+ } else if (log.status == "error") {
|
|
|
result.error = 1;
|
|
result.error = 1;
|
|
|
result.msg = log.errorMsg;
|
|
result.msg = log.errorMsg;
|
|
|
await importLogsModel.remove(query);
|
|
await importLogsModel.remove(query);
|
|
|
}
|
|
}
|
|
|
- }else {
|
|
|
|
|
|
|
+ } else {
|
|
|
result.status = "complete";
|
|
result.status = "complete";
|
|
|
}
|
|
}
|
|
|
return result;
|
|
return result;
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// 从cdn服务器下载文件,key就是文件名
|
|
|
|
|
+async function downloadFileSync(key) {
|
|
|
|
|
+ const filePath = path.join(__dirname, '../../../tmp/', key);
|
|
|
|
|
+ const bucketManager2 = new qiniu.rs.BucketManager(mac, null);
|
|
|
|
|
+ const publicBucketDomain = qiniu_config.Domain; // "http://serverupdate.smartcost.com.cn";//这里不支持https
|
|
|
|
|
+ const deadline = parseInt(Date.now() / 1000) + 3600; // 1小时过期
|
|
|
|
|
+ const privateDownloadUrl = bucketManager2.privateDownloadUrl(publicBucketDomain, key, deadline);
|
|
|
|
|
+ const stream = fs.createWriteStream(filePath);
|
|
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
|
|
+ request(privateDownloadUrl)
|
|
|
|
|
+ .on('error', reject)
|
|
|
|
|
+ .pipe(stream)
|
|
|
|
|
+ .on('close', () => {
|
|
|
|
|
+ // 读取文件返回字符串
|
|
|
|
|
+ const srcData = fs.readFileSync(stream.path, 'utf-8');
|
|
|
|
|
+ resolve({
|
|
|
|
|
+ path: stream.path,
|
|
|
|
|
+ srcData: srcData
|
|
|
|
|
+ });
|
|
|
|
|
+ })
|
|
|
|
|
+ .on('error', reject);
|
|
|
|
|
+ });
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 导入接口
|
|
|
|
|
+async function importInterface(key, session) {
|
|
|
|
|
+ const logData = {
|
|
|
|
|
+ key: key,
|
|
|
|
|
+ content: '正在导入接口文件,请稍候……',
|
|
|
|
|
+ userID: session.sessionUser.id,
|
|
|
|
|
+ compilationID: session.sessionCompilation._id,
|
|
|
|
|
+ status: 'start',
|
|
|
|
|
+ create_time: +new Date()
|
|
|
|
|
+ };
|
|
|
|
|
+ await importLogsModel.create(logData);
|
|
|
|
|
+ handleImportInterface(key, session);
|
|
|
|
|
+ return 'importing interface';
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+async function handleImportInterface(key, session) {
|
|
|
|
|
+ const doc = { status: 'finish' };
|
|
|
|
|
+ // 源文件内容文本
|
|
|
|
|
+ let downloadFilePath = '';
|
|
|
|
|
+ try {
|
|
|
|
|
+ const { path, srcData } = await downloadFileSync(key);
|
|
|
|
|
+ downloadFilePath = path;
|
|
|
|
|
+ if (!srcData) {
|
|
|
|
|
+ throw '无有效数据';
|
|
|
|
|
+ }
|
|
|
|
|
+ const userID = session.sessionUser.id;
|
|
|
|
|
+ const compilationID = session.sessionCompilation._id;
|
|
|
|
|
+ const importData = JSON.parse(srcData);
|
|
|
|
|
+ const tenderCount = importData.tenders.length;
|
|
|
|
|
+ if (await isTenderOverrun(tenderCount, session)) {
|
|
|
|
|
+ throw '您创建的项目个数超限,请联系我们的客服人员,或者导出建设项目保存到本地备份,删除云上数据。';
|
|
|
|
|
+ }
|
|
|
|
|
+ const overWriteUrl = session.sessionCompilation.overWriteUrl;
|
|
|
|
|
+ const projectID = await importInterfaceProject(importData, userID, compilationID, overWriteUrl);
|
|
|
|
|
+ doc.projectID = projectID;
|
|
|
|
|
+ } catch (err) {
|
|
|
|
|
+ console.log(err);
|
|
|
|
|
+ doc.errorMsg = typeof err === 'string' ? err : err.toString();
|
|
|
|
|
+ doc.status = 'error';
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ await importLogsModel.update({ key }, doc);
|
|
|
|
|
+ fs.unlinkSync(downloadFilePath);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/*
|
|
|
|
|
+* 接口导入 项目详细数据都导入完成了,再生成项目数据(项目管理界面数据)
|
|
|
|
|
+* */
|
|
|
|
|
+async function importInterfaceProject(importObj, userID, compilationID, overWriteUrl) {
|
|
|
|
|
+ const toInsertProjects = [importObj]; //待新增项目数据
|
|
|
|
|
+ let defaultCalcMode;
|
|
|
|
|
+ if (overWriteUrl) {
|
|
|
|
|
+ const overWrite = require('../../..' + overWriteUrl);
|
|
|
|
|
+ if(overWrite.defaultCalcMode) { // 重写清单计费取费方式
|
|
|
|
|
+ defaultCalcMode = overWrite.defaultCalcMode;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ await setupProject(importObj);
|
|
|
|
|
+ // 设置项目相关数据
|
|
|
|
|
+ for (const curTender of importObj.tenders) {
|
|
|
|
|
+ await setupProject(curTender);
|
|
|
|
|
+ // 插入单位工程的详细数据
|
|
|
|
|
+ await importTenderDetail(curTender);
|
|
|
|
|
+ delete curTender.bills;
|
|
|
|
|
+ toInsertProjects.push(curTender);
|
|
|
|
|
+ }
|
|
|
|
|
+ delete importObj.tenders;
|
|
|
|
|
+ // 项目内部数据设置、新增完毕后,插入项目本身的数据,更新前节点数据
|
|
|
|
|
+ const bulks = [];
|
|
|
|
|
+ // 如果有前节点,更新前节点
|
|
|
|
|
+ if (importObj.preID !== -1) {
|
|
|
|
|
+ bulks.push({
|
|
|
|
|
+ updateOne: { filter: { ID: importObj.preID }, update: { $set: { NextSiblingID: importObj.ID } } }
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ for (let insertP of toInsertProjects) {
|
|
|
|
|
+ bulks.push({
|
|
|
|
|
+ insertOne: { document: insertP }
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ if (bulks.length > 0) {
|
|
|
|
|
+ await projectModel.bulkWrite(bulks);
|
|
|
|
|
+ }
|
|
|
|
|
+ return importObj.ID; // 返回建设项目ID
|
|
|
|
|
+
|
|
|
|
|
+ //给项目数据设置一些需要的数据
|
|
|
|
|
+ async function setupProject(data) {
|
|
|
|
|
+ data.userID = userID;
|
|
|
|
|
+ data.compilation = compilationID;
|
|
|
|
|
+ data.fileVer = await index.getVersion();
|
|
|
|
|
+ data.createDateTime = new Date();
|
|
|
|
|
+ if (data.projType === 'Tender') {
|
|
|
|
|
+ await setupTender(data);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ //给单位工程设置一些数据
|
|
|
|
|
+ async function setupTender(data) {
|
|
|
|
|
+ if (!data.property.decimal) {
|
|
|
|
|
+ //小数位数 需要修改,所以深拷贝
|
|
|
|
|
+ data.property.decimal = JSON.parse(JSON.stringify(defaultDecimal));
|
|
|
|
|
+ }
|
|
|
|
|
+ //清单工程量精度 需要修改,所以深拷贝
|
|
|
|
|
+ data.property.billsQuantityDecimal = JSON.parse(JSON.stringify(billsQuantityDecimal));
|
|
|
|
|
+ // 清单工程量精度默认为3
|
|
|
|
|
+ const billsQuantityDecimalValue = data.property.billsQuantityDecimalValue || 3;
|
|
|
|
|
+ data.property.billsQuantityDecimal.forEach(data => data.decimal = billsQuantityDecimalValue);
|
|
|
|
|
+ //呈现选项
|
|
|
|
|
+ data.property.displaySetting = displaySetting;
|
|
|
|
|
+
|
|
|
|
|
+ data.property.billsCalcMode = defaultCalcMode || data.property.valuationType == 'bill' ? 2 : 1;
|
|
|
|
|
+ data.property.zanguCalcMode = 0;
|
|
|
|
|
+ //计算选项
|
|
|
|
|
+ data.property.calcOptions = calcOptions;
|
|
|
|
|
+ //锁定清单
|
|
|
|
|
+ data.property.lockBills = true;
|
|
|
|
|
+ //工料机单价调整系数
|
|
|
|
|
+ data.property.tenderSetting = tenderSetting;
|
|
|
|
|
+ // 书签
|
|
|
|
|
+ data.property.bookmarkSetting = bookmarkSetting;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+//插入单位工程内部详细数据
|
|
|
|
|
+async function importTenderDetail(tenderData) {
|
|
|
|
|
+ // 单价文件
|
|
|
|
|
+ const upFile = {
|
|
|
|
|
+ id: tenderData.property.unitPriceFile.id,
|
|
|
|
|
+ name: tenderData.name,
|
|
|
|
|
+ project_id: tenderData.ID,
|
|
|
|
|
+ user_id: tenderData.userID,
|
|
|
|
|
+ root_project_id: tenderData.property.rootProjectID
|
|
|
|
|
+ };
|
|
|
|
|
+ await unitPriceFileModel.create(upFile);
|
|
|
|
|
+ // 费率文件
|
|
|
|
|
+ const feeRateFileID = await feeRate_facade.newFeeRateFile(tenderData.userID, tenderData);
|
|
|
|
|
+ tenderData.property.feeFile = feeRateFileID ? feeRateFileID : -1;
|
|
|
|
|
+ // 人工系数文件
|
|
|
|
|
+ const lcFile = await labourCoeFacade.newProjectLabourCoe(tenderData);
|
|
|
|
|
+ tenderData.property.labourCoeFile = lcFile ? lcFile : null;
|
|
|
|
|
+ const cpFile = await calcProgramFacade.newProjectCalcProgramFile(tenderData);
|
|
|
|
|
+ tenderData.property.calcProgramFile = cpFile ? cpFile : null;
|
|
|
|
|
+ // 列设置
|
|
|
|
|
+ const engineeringModel = new EngineeringLibModel();
|
|
|
|
|
+ const engineering = await engineeringModel.getEngineering(tenderData.property.engineering_id);
|
|
|
|
|
+ const mainTreeCol = await mainColLibModel.findOne({ ID: tenderData.property.colLibID });
|
|
|
|
|
+ await projectSettingModel.create({ projectID: tenderData.ID, main_tree_col: mainTreeCol.main_tree_col, glj_col: engineering.glj_col });
|
|
|
|
|
+ // 清单
|
|
|
|
|
+ if (tenderData.bills && tenderData.bills.length) {
|
|
|
|
|
+ await billsModel.insertMany(tenderData.bills);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
async function copyConstructionProject(data){
|
|
async function copyConstructionProject(data){
|
|
|
let log_data = {
|
|
let log_data = {
|
|
|
key:data.key,
|
|
key:data.key,
|
|
@@ -2331,12 +2521,25 @@ async function getImportTemplateData(compilationID, valuationID, projectCount) {
|
|
|
const featureLibID = engineeringLib.feature_lib[0].id;
|
|
const featureLibID = engineeringLib.feature_lib[0].id;
|
|
|
const featureLib = await featureLibModel.findOne({ ID: featureLibID }).lean();
|
|
const featureLib = await featureLibModel.findOne({ ID: featureLibID }).lean();
|
|
|
const billsTemplateLibID = engineeringLib.tax_group[0].template_lib.id;
|
|
const billsTemplateLibID = engineeringLib.tax_group[0].template_lib.id;
|
|
|
- const billsTemplate = await stdBillsTemplateModel.find({ libID: billsTemplateLibID }).lean();
|
|
|
|
|
|
|
+ let billsTemplate = await stdBillsTemplateModel.find({ libID: billsTemplateLibID }, '-_id -libID').lean();
|
|
|
|
|
+ billsUtil.resetTreeData(billsTemplate, uuidV1); // 重新建立新的ID数据
|
|
|
|
|
+ const parentMap = {};
|
|
|
|
|
+ billsTemplate.forEach(bills => {
|
|
|
|
|
+ // 工程量清单单价分析默认勾选,导入必为工程量清单,因此清单模板单价分析全部勾选先
|
|
|
|
|
+ bills.unitPriceAnalysis = 1;
|
|
|
|
|
+ (parentMap[bills.ParentID] || (parentMap[bills.ParentID] = [])).push(bills);
|
|
|
|
|
+ });
|
|
|
|
|
+ const roots = parentMap['-1'];
|
|
|
|
|
+ roots.forEach(root => project_facade.setChildren(root, parentMap));
|
|
|
|
|
+ billsTemplate = project_facade.sortChildren(roots);
|
|
|
const projectCounter = await counter.counterDAO.getIDAfterCountSync(counter.moduleName.project, projectCount);
|
|
const projectCounter = await counter.counterDAO.getIDAfterCountSync(counter.moduleName.project, projectCount);
|
|
|
|
|
+ const tenderCount = projectCount - 1;
|
|
|
|
|
+ const unitFileCounter = await counter.counterDAO.getIDAfterCountSync(counter.moduleName.unit_price_file, tenderCount);
|
|
|
return {
|
|
return {
|
|
|
basicInfo: infoLib && infoLib.info || [],
|
|
basicInfo: infoLib && infoLib.info || [],
|
|
|
feature: featureLib && featureLib.feature || [],
|
|
feature: featureLib && featureLib.feature || [],
|
|
|
bills: billsTemplate,
|
|
bills: billsTemplate,
|
|
|
projectBeginID: projectCounter.sequence_value - projectCount + 1,
|
|
projectBeginID: projectCounter.sequence_value - projectCount + 1,
|
|
|
|
|
+ unitPriceFileBeginID: unitFileCounter.sequence_value - tenderCount + 1,
|
|
|
};
|
|
};
|
|
|
}
|
|
}
|