/**
* Created by Tony on 2017/4/28.
*/
const mongoose = require('mongoose');
let async = require("async");
let moment = require('moment');
let counter = require('../../../public/counter/counter');
let gljDao = require('./glj_repository');
let rationRepositoryDao = require('./repository_map');
const scMathUtil = require('../../../public/scMathUtil').getUtil();
const rationItemModel = mongoose.model('std_ration_lib_ration_items');
const stdRationLibModel = mongoose.model('std_ration_lib_map');
const stdRationSectionModel = mongoose.model('std_ration_lib_ration_chapter_trees');
const compleRationModel = mongoose.model('complementary_ration_items');
import STDGLJListModel from '../../std_glj_lib/models/gljModel';
import InstallationDao from '../models/installation';
const installationDao = new InstallationDao();
import GljDao from "../../std_glj_lib/models/gljModel";
const stdGljDao = new GljDao();
import stdgljutil from "../../../public/cache/std_glj_type_util";
var rationItemDAO = function(){};
rationItemDAO.prototype.prepareInitData = async function (rationRepId) {
// 定额库
const libTask = stdRationLibModel.findOne({ID: rationRepId}, '-_id ID dispName gljLib');
// 定额编码
const codesTask = rationItemModel.find({rationRepId}, '-_id code', {lean: true});
// 定额章节树
const sectionTreeTask = stdRationSectionModel.find({rationRepId}, '-_id', {lean: true});
// 安装增加费
const installationTask = installationDao.getInstallation(rationRepId);
const [libInfo, codesArr, sectionTree, installationList] = await Promise.all([libTask, codesTask, sectionTreeTask, installationTask]);
const rationsCodes = codesArr.reduce((acc, cur) => {
acc.push(cur.code);
return acc;
}, []);
// 人材机分类树
const gljLibId = libInfo.gljLib;
const gljTreeTask = stdGljDao.getGljTreeSync(gljLibId);
const gljTask = stdGljDao.getGljItemsSync(gljLibId);
const [gljTree, gljList] = await Promise.all([gljTreeTask, gljTask]);
const gljDistTypeList = stdgljutil.getStdGljTypeCacheObj().toArray();
return {
libInfo,
rationsCodes,
sectionTree,
installationList,
gljTree,
gljList,
gljDistTypeList
};
};
rationItemDAO.prototype.getRationItemsByLib = async function (rationRepId, showHint = null, returnFields = '') {
let rationLib = await stdRationLibModel.findOne({ID: rationRepId, deleted: false});
if(!rationLib){
return [];
}
let startDate = new Date();
let rations = await rationItemModel.find({rationRepId: rationRepId}, returnFields);
console.log(`Date: ${new Date() - startDate}====================================`);
if(!showHint){
return rations;
}
else {
const stdBillsLibListsModel = new STDGLJListModel();
const stdGLJData = await stdBillsLibListsModel.getGljItemsByRepId(rationLib.gljLib, '-_id ID code name unit gljType');
let gljMapping = {};
for(let glj of stdGLJData){
gljMapping[glj.ID] = glj;
}
//设置悬浮
for(let ration of rations){
let hintsArr = [];
//对人材机进行排序
ration.rationGljList.sort(function (a, b) {
let gljA = gljMapping[a.gljId],
gljB = gljMapping[b.gljId];
if(gljA && gljB){
let aV = gljA.gljType + gljA.code,
bV = gljB.gljType + gljB.code;
if(aV > bV) {
return 1;
} else if(aV < bV) {
return -1;
}
}
return 0;
});
for(let rationGlj of ration.rationGljList){
let subGlj = gljMapping[rationGlj.gljId];
if(subGlj){
hintsArr.push(` ${subGlj.code} ${subGlj.name}${subGlj.specs ? ' ' + subGlj.specs : ''}   ${subGlj.unit} ${rationGlj.consumeAmt}`);
}
}
hintsArr.push(`基价 元 ${ration.basePrice}`);
if(ration.jobContent && ration.jobContent.toString().trim() !== ''){
hintsArr.push(`工作内容:`);
hintsArr = hintsArr.concat(ration.jobContent.split('\n'));
}
if(ration.annotation && ration.annotation.toString().trim() !== ''){
hintsArr.push(`附注:`);
hintsArr = hintsArr.concat(ration.annotation.split('\n'));
}
ration._doc.hint = hintsArr.join('
');
}
return rations;
}
};
rationItemDAO.prototype.sortToNumber = function (datas) {
for(let i = 0, len = datas.length; i < len; i++){
let data = datas[i]._doc;
if(_exist(data, 'labourPrice')){
data['labourPrice'] = parseFloat(data['labourPrice']);
}
if(_exist(data, 'materialPrice')){
data['materialPrice'] = parseFloat(data['materialPrice']);
}
if(_exist(data, 'machinePrice')){
data['machinePrice'] = parseFloat(data['machinePrice']);
}
if(_exist(data, 'basePrice')){
data['basePrice'] = parseFloat(data['basePrice']);
}
if(_exist(data, 'rationGljList')){
for(let j = 0, jLen = data['rationGljList'].length; j < jLen; j++){
let raGljObj = data['rationGljList'][j]._doc;
if(_exist(raGljObj, 'consumeAmt')){
raGljObj['consumeAmt'] = parseFloat(raGljObj['consumeAmt']);
}
}
}
}
function _exist(data, attr){
return data && data[attr] !== undefined && data[attr];
}
};
rationItemDAO.prototype.getRationItemsBySection = async function(rationRepId, sectionId,callback){
let me = this;
try {
let rations = await rationItemModel.find({rationRepId: rationRepId, sectionId: sectionId});
me.sortToNumber(rations);
let matchRationIDs = [],
matchRations = [];
for (let ration of rations) {
if (ration.rationTemplateList) {
for (let rt of ration.rationTemplateList) {
if (rt.rationID) {
matchRationIDs.push(rt.rationID);
}
}
}
}
if (matchRationIDs.length > 0) {
matchRations = await rationItemModel.find({ID: {$in: matchRationIDs}}, '-_id ID code name');
}
for (let mr of matchRations) {
for (let ration of rations) {
if (ration.rationTemplateList) {
for (let rt of ration.rationTemplateList) {
if (rt.rationID && rt.rationID === mr.ID) {
rt.code = mr.code ? mr.code : '';
rt.name = mr.name ? mr.name : '';
}
}
}
}
}
callback(false,"Get items successfully", rations);
} catch (err) {
console.log(err);
callback(true, "Fail to get items", "");
}
/* rationItemModel.find({"rationRepId": rationRepId, "sectionId": sectionId, "$or": [{"isDeleted": null}, {"isDeleted": false} ]},function(err,data){
if(err) callback(true, "Fail to get items", "");
else {
me.sortToNumber(data);
callback(false,"Get items successfully", data);
}
})*/
};
rationItemDAO.prototype.mixUpdateRationItems = function(rationLibId, lastOpr, sectionId, updateItems, addItems, rIds, callback){
var me = this;
if (updateItems.length == 0 && rIds.length == 0) {
me.addRationItems(rationLibId, lastOpr, sectionId, addItems, callback);
} else {
me.removeRationItems(rationLibId, lastOpr, rIds, function(err, message, docs) {
if (err) {
callback(true, "Fail to remove", false);
} else {
me.updateRationItems(rationLibId, lastOpr, sectionId, updateItems, function(err, results){
if (err) {
callback(true, "Fail to save", false);
} else {
if (addItems && addItems.length > 0) {
me.addRationItems(rationLibId, lastOpr, sectionId, addItems, callback);
} else {
callback(false, "Save successfully", results);
}
}
});
}
})
}
};
rationItemDAO.prototype.removeRationItems = function(rationLibId, lastOpr, rIds,callback){
if (rIds.length > 0) {
rationItemModel.collection.remove({ID: {$in: rIds}}, null, function(err, docs){
if (err) {
callback(true, "Fail to remove", false);
} else {
rationRepositoryDao.updateOprArr({ID: rationLibId}, lastOpr, moment(Date.now()).format('YYYY-MM-DD HH:mm:ss'), function (err) {
if(!err){
rationItemModel.update({rationRepId: rationLibId}, {$pull: {rationTemplateList: {rationID: {$in: rIds}}}}, function (theErr) {
if (!theErr) {
callback(false, "Remove successfully", docs);
} else {
callback(true, "Fail to remove", false);
}
});
} else {
callback(true, "Fail to remove", false);
}
})
}
})
} else {
callback(false, "No records were deleted!", null);
}
};
rationItemDAO.prototype.getRationItemsByCode = function(repId, code,callback){
rationItemModel.find({"rationRepId": repId, "code": {'$regex': code, $options: '$i'}, "$or": [{"isDeleted": null}, {"isDeleted": false}]},function(err,data){
if(err) callback(true, "Fail to get items", "")
else callback(false,"Get items successfully", data);
})
};
rationItemDAO.prototype.findRation = function (repId, keyword, callback) {
var filter = {
'rationRepId': repId,
'$and': [{
'$or': [{'code': {'$regex': keyword, $options: '$i'}}, {'name': {'$regex': keyword, $options: '$i'}}]
}, {
'$or': [{'isDeleted': {"$exists":false}}, {'isDeleted': null}, {'isDeleted': false}]
}]
};
rationItemModel.find(filter, function (err, data) {
if (err) {
callback(true, 'Fail to find ration', null);
} else {
callback(false, '', data);
}
})
}
rationItemDAO.prototype.getRationItem = async function (repId, code) {
let ration = await rationItemModel.findOne({rationRepId: repId, code: code});
return ration;
};
rationItemDAO.prototype.addRationItems = function(rationLibId, lastOpr, sectionId, items,callback){
if (items && items.length > 0) {
counter.counterDAO.getIDAfterCount(counter.moduleName.rations, items.length, function(err, result){
var maxId = result.sequence_value;
var arr = [];
for (var i = 0; i < items.length; i++) {
var obj = new rationItemModel(items[i]);
obj.ID = (maxId - (items.length - 1) + i);
obj.sectionId = sectionId;
obj.rationRepId = rationLibId;
arr.push(obj);
}
rationItemModel.collection.insert(arr, null, function(err, docs){
if (err) {
callback(true, "Fail to save", false);
} else {
rationRepositoryDao.updateOprArr({ID: rationLibId}, lastOpr, moment(Date.now()).format('YYYY-MM-DD HH:mm:ss'), function (err) {
if(err){
callback(true, "Fail to sava operator", false);
}
else{
callback(false, "Save successfully", docs);
}
})
}
})
});
} else {
callback(true, "Source error!", false);
}
};
rationItemDAO.prototype.updateRationItems = function(rationLibId, lastOpr, sectionId, items,callback){
console.log('enter============');
var functions = [];
for (var i=0; i < items.length; i++) {
functions.push((function(doc) {
return function(cb) {
var filter = {};
if (doc.ID) {
filter.ID = doc.ID;
} else {
filter.sectionId = sectionId;
if (rationLibId) filter.rationRepId = rationLibId;
filter.code = doc.code;
}
rationItemModel.update(filter, doc, cb);
};
})(items[i]));
}
functions.push((function () {
return function (cb) {
rationRepositoryDao.updateOprArr({ID: rationLibId}, lastOpr, moment(Date.now()).format('YYYY-MM-DD HH:mm:ss'), function (err) {
if(err){
cb(err);
}
else{
cb(null);
}
});
}
})());
async.parallel(functions, function(err, results) {
callback(err, results);
});
};
//ration round func
function round(v,e){
var t=1;
for(;e>0;t*=10,e--);
for(;e<0;t/=10,e++);
return Math.round(v*t)/t;
}
function calcRation(gljArr) {
let labourPrc = [],
materialPrc = [],
machinePrc = [],
managePrc = [],
profitPrc = [],
riskPrc = [],
singlePrc,
updatePrc = {labourPrice: 0, materialPrice: 0, machinePrice: 0, managePrice: 0, profitPrice: 0, riskPrice: 0, basePrice: 0};
gljArr.forEach(function (gljItem) {
if(gljItem.gljParentType !== -1){
singlePrc = scMathUtil.roundTo(gljItem.basePrice * gljItem.consumeAmt, -3);
if(gljItem.gljParentType === 1){
labourPrc.push(singlePrc);
}
else if(gljItem.gljParentType ===2){
materialPrc.push(singlePrc);
}
else if(gljItem.gljParentType === 3){
machinePrc.push(singlePrc);
}
else if(gljItem.gljParentType === 6){
managePrc.push(singlePrc);
}
else if(gljItem.gljParentType === 7){
profitPrc.push(singlePrc);
}
else if(gljItem.gljParentType === 8){
riskPrc.push(singlePrc);
}
}
});
if(labourPrc.length > 0){
let sumLaP = 0;
for(let i=0; i 0){
let sumMtP = 0;
for(let i= 0; i 0){
let sumMaP = 0;
for(let i =0; i< machinePrc.length; i++){
sumMaP = scMathUtil.roundTo(sumMaP + machinePrc[i], -6);
}
updatePrc.machinePrice = scMathUtil.roundTo(sumMaP, -2);
updatePrc.basePrice = scMathUtil.roundTo(updatePrc.basePrice + updatePrc.machinePrice, -2);
}
if(managePrc.length > 0){
let sumMgP = 0;
for(let i =0; i< managePrc.length; i++){
sumMgP = scMathUtil.roundTo(sumMgP + managePrc[i], -6);
}
updatePrc.managePrice = scMathUtil.roundTo(sumMgP, -2);
updatePrc.basePrice = scMathUtil.roundTo(updatePrc.basePrice + updatePrc.managePrice, -2);
}
if(profitPrc.length > 0){
let sumPfP = 0;
for(let i =0; i< profitPrc.length; i++){
sumPfP = scMathUtil.roundTo(sumPfP + profitPrc[i], -6);
}
updatePrc.profitPrice = scMathUtil.roundTo(sumPfP, -2);
updatePrc.basePrice = scMathUtil.roundTo(updatePrc.basePrice + updatePrc.profitPrice, -2);
}
if(riskPrc.length > 0){
let sumRkP = 0;
for(let i =0; i< riskPrc.length; i++){
sumRkP = scMathUtil.roundTo(sumRkP + riskPrc[i], -6);
}
updatePrc.riskPrice = scMathUtil.roundTo(sumRkP, -2);
updatePrc.basePrice = scMathUtil.roundTo(updatePrc.basePrice + updatePrc.riskPrice, -2);
}
return updatePrc;
}
rationItemDAO.prototype.updateRationBasePrc = function (basePrcArr, overWriteUrl, callback) {
async.each(basePrcArr, function (basePrcObj, finalCb) {
let adjGljId = basePrcObj.gljId, adjBasePrice = basePrcObj.basePrice, adjGljType = basePrcObj.gljType;
async.waterfall([
function (cb) {
if(typeof basePrcObj.delete !== 'undefined' && basePrcObj.delete === 1){
rationItemModel.find({'rationGljList.gljId': adjGljId},{ID: 1, rationGljList: 1}, function (err, result) {
if(err){
cb(err);
}
else{
//删除
rationItemModel.update({'rationGljList.gljId': adjGljId}, {$pull: {rationGljList: {gljId: adjGljId}}}, {multi: true}, function (err) {
if(err){
cb(err);
}
else{
//补充定额
compleRationModel.find({'rationGljList.gljId': adjGljId},{ID: 1, rationGljList: 1}, function (err, compleRst) {
if(err){
cb(err);
}
else {
compleRationModel.update({'rationGljList.gljId': adjGljId}, {$pull: {rationGljList: {gljId: adjGljId}}}, {multi: true}, function (err) {
if(err){
cb(err);
}
else {
for(let i = 0, len = compleRst.length; i < len; i++){
compleRst[i]._doc.type = 'complementary';
}
cb(null, result.concat(compleRst));
}
});
}
});
}
});
}
});
}
else{
rationItemModel.find({'rationGljList.gljId': adjGljId}, {ID: 1, rationGljList: 1}, function (err, result) {
if(err){
cb(err);
}
else{
compleRationModel.find({'rationGljList.gljId': adjGljId}, {ID: 1, rationGljList: 1}, function (err, compleRst) {
if(err){
cb(err);
}
else {
for(let i = 0, len = compleRst.length; i < len; i++){
compleRst[i]._doc.type = 'complementary';
}
cb(null, result.concat(compleRst));
}
});
}
});
}
},
function (result, cb) {
let compleRTasks = [], stdRTasks = [];
//重算时需要用到的所有工料机,一次性取
let compleGljIds = [], stdGljIds = [];
for(let ration of result){
for(let glj of ration.rationGljList){
if(glj.type !== undefined && glj.type === 'complementary'){
compleGljIds.push(glj.gljId);
}
else {
stdGljIds.push(glj.gljId);
}
}
}
gljDao.getStdCompleGljItems(compleGljIds, stdGljIds, function (err, allGljs) {
if(err){
cb(err);
}
else {
let gljIndex = {};
for(let glj of allGljs){
gljIndex[glj.ID] = glj;
}
async.each(result, function (rationItem, ecb) {
let rationGljList = rationItem.rationGljList;
let gljArr = [];
for(let i=0; i 200 && theGlj.gljType < 300){
gljParentType = 2;
} else if(theGlj.gljType > 300 && theGlj.gljType < 400){
gljParentType = 3;
} else if(theGlj.gljType === 6){ //管理费
gljParentType = 6;
} else if(theGlj.gljType === 7){ //利润
gljParentType = 7;
} else if(theGlj.gljType === 8){ //风险费
gljParentType = 8;
}
if(theGlj)
if(theGlj.ID === adjGljId){
gljArr.push({gljId: theGlj.ID, basePrice: adjBasePrice, gljParentType: gljParentType, unit: theGlj.unit});
} else {
if(theGlj.priceProperty && Object.keys(theGlj.priceProperty).length > 0){
gljArr.push({
gljId: theGlj.ID,
basePrice: parseFloat(theGlj.priceProperty.price1),
gljParentType: gljParentType,
unit: theGlj.unit});
} else {
gljArr.push({
gljId: theGlj.ID,
basePrice: parseFloat(theGlj.basePrice),
gljParentType: gljParentType,
unit: theGlj.unit});
}
}
}
}
gljArr.forEach(function (gljItem) {
rationGljList.forEach(function (rationGlj) {
if(gljItem.gljId === rationGlj.gljId){
gljItem.consumeAmt = parseFloat(rationGlj.consumeAmt);
}
})
});
let updatePrc = null;
let overWriteCalc = false; //需要重写算法
if (overWriteUrl) {
let overWriteExports = require(overWriteUrl);
if (typeof overWriteExports.calcRation !== 'undefined') {
overWriteCalc = true;
updatePrc = overWriteExports.calcRation(gljArr, scMathUtil);
}
}
if (!overWriteCalc) {
updatePrc = calcRation(gljArr);
}
let task = {
updateOne: {
filter: {
ID: rationItem.ID
},
update: {
labourPrice: updatePrc.labourPrice.toString(),
materialPrice: updatePrc.materialPrice.toString(),
machinePrice: updatePrc.machinePrice.toString(),
basePrice: updatePrc.basePrice.toString()
}
}
};
//updateDataBase
if(rationItem._doc.type !== undefined && rationItem._doc.type === 'complementary'){
compleRTasks.push(task);
ecb(null);
}
else {
stdRTasks.push(task);
ecb(null);
}
}, async function(err){
if(err){
cb(err);
}
else {
//do sth
try{
if(compleRTasks.length > 0){
await compleRationModel.bulkWrite(compleRTasks);
}
if(stdRTasks.length > 0){
await rationItemModel.bulkWrite(stdRTasks);
}
}
catch(e){
cb(err);
}
cb(null);
}
});
}
});
},
], function (err) {
if(err){
finalCb(err);
}
else{
finalCb(null);
}
});
}, function (err) {
if(err){
callback(err, 'Error');
}
else{
callback(null, '');
}
});
};
rationItemDAO.prototype.getRationGljIds = function (data, callback) {
let repId = data.repId;
rationItemModel.find({rationRepId: repId}, function (err, result) {
if(err){
callback(err, 'Error', null);
}
else{
let rstIds = [], newRst = [];
result.forEach(function (data) {
if(data.rationGljList.length >0){
data.rationGljList.forEach(function (gljObj) {
rstIds.push(gljObj.gljId);
})
}
});
for(let i= 0; i< rstIds.length; i++){
if(newRst.indexOf(rstIds[i]) === -1){
newRst.push(rstIds[i]);
}
}
callback(null, '', newRst);
}
});
};
rationItemDAO.prototype.getRationsCodes = function (data, callback) {
let repId = data.repId;
rationItemModel.find({rationRepId: repId, isDeleted: false}, function (err, result) {
if(err){
callback(err, 'Error', null);
}
else{
let rstCodes = [];
result.forEach(function (rationItem) {
rstCodes.push(rationItem.code);
});
callback(null, 'get all rationCodes success', rstCodes);
}
})
};
rationItemDAO.prototype.updateJobContent = function (lastOpr, repId, updateArr, callback) {
rationRepositoryDao.updateOprArr({ID: repId}, lastOpr, moment(Date.now()).format('YYYY-MM-DD HH:mm:ss'), function (err) {
async.each(updateArr, function (obj, cb) {
rationItemModel.update({rationRepId: repId, code: obj.code}, {$set: {jobContent: obj.jobContent}}, function (err) {
if(err){
cb(err);
}
else{
cb(null);
}
})
}, function (err) {
if(err){
callback(err);
}
else{
callback(null);
}
});
});
}
rationItemDAO.prototype.updateAnnotation = function (lastOpr, repId, updateArr, callback) {
rationRepositoryDao.updateOprArr({ID: repId}, lastOpr, moment(Date.now()).format('YYYY-MM-DD HH:mm:ss'), function (err) {
async.each(updateArr, function (obj, cb) {
rationItemModel.update({rationRepId: repId, code: obj.code}, {$set: {annotation: obj.annotation}}, function (err) {
if(err){
cb(err);
}
else{
cb(null);
}
})
}, function (err) {
if(err){
callback(err);
}
else{
callback(null);
}
});
});
};
//更新定额下模板关联
rationItemDAO.prototype.updateRationTemplate = async function (rationRepId, rationID, templateData) {
//自动匹配定额
let matachCodes = [],
matchRations = [];
//要保存的数据
let saveData = [];
for (let data of templateData) {
if (data.code) {
matachCodes.push(data.code);
}
}
matachCodes = Array.from(new Set(matachCodes));
if (matachCodes.length > 0) {
matchRations = await rationItemModel.find({rationRepId: rationRepId, code: {$in: matachCodes}}, '-_id ID code name');
}
let validData = [];
//设置展示数据
for (let data of templateData) {
let match = false;
for (let ration of matchRations) {
if (data.code && data.code === ration.code) {
match = true;
data.name = ration.name;
data.rationID = ration.ID;
break;
}
}
if (!match) {
data.code = '';
data.name = '';
}
if (data.type || data.code || data.name || data.billsLocation) {
validData.push(data);
}
}
for (let data of validData) {
saveData.push({rationID: data.rationID ? data.rationID : null, type: data.type, billsLocation: data.billsLocation});
}
//更新
await rationItemModel.update({ID: rationID}, {$set: {rationTemplateList: saveData}});
return validData;
};
// 根据章节列表批量更新定额
rationItemDAO.prototype.updateRationBySection = async function (rationRepId, sectionList, updateData) {
await rationItemModel.updateMany({rationRepId, sectionId: {$in: sectionList}}, updateData);
}
//计算导入数据的价格
rationItemDAO.prototype.calcForRation = function (stdGljList, ration, overWriteUrl) {
let rationGljList = ration.rationGljList,
gljArr = [];
for(let rationGlj of rationGljList) {
let glj = stdGljList[rationGlj.gljId];
let gljPType = parseInt(glj.gljType.toString().match(/\d+?/)[0]);
let newGlj = {
gljId: glj.ID,
consumeAmt: rationGlj.consumeAmt,
gljParentType: gljPType,
unit: glj.unit
};
newGlj.basePrice = glj.priceProperty && Object.keys(glj.priceProperty).length > 0
? parseFloat(glj.priceProperty.price1)
: parseFloat(glj.basePrice);
gljArr.push(newGlj);
}
let updatePrc = null;
let overWriteCalc = false; //需要重写算法
if (overWriteUrl) {
let overWriteExports = require(overWriteUrl);
if (typeof overWriteExports.calcRation !== 'undefined') {
overWriteCalc = true;
updatePrc = overWriteExports.calcRation(gljArr, scMathUtil);
}
}
if (!overWriteCalc) {
updatePrc = calcRation(gljArr);
}
ration.labourPrice = updatePrc.labourPrice.toString();
ration.materialPrice = updatePrc.materialPrice.toString();
ration.machinePrice = updatePrc.machinePrice.toString();
ration.basePrice = updatePrc.basePrice.toString();
};
/**
* 根据条件获取定额数据
*
* @param {Object} condition
* @param {Object} fields
* @param {String} indexBy
* @return {Promise|Array}
*/
rationItemDAO.prototype.getRationItemByCondition = async function (condition, fields = null, indexBy = null) {
let result = [];
if (Object.keys(condition).length <= 0) {
return result;
}
result = await rationItemModel.find(condition, fields).sort({code: 1});
if (indexBy !== null && result.length > 0) {
let tmpResult = {};
for(let tmp of result) {
tmpResult[tmp[indexBy]] = tmp;
}
result = tmpResult;
}
return result;
};
/**
* 从excel中批量新增数据
*
* @param {Number} rationRepId
* @param {Array} data
* @return {bool}
*/
rationItemDAO.prototype.batchAddFromExcel = async function(rationRepId, data) {
if (data.length <= 0) {
return false;
}
// 获取定额库相关数据
const rationRepository = await rationRepositoryDao.getRepositoryById(rationRepId);
if (rationRepository.length !== 1 || rationRepository[0].gljLib === undefined) {
return false;
}
// 获取标准工料机库数据
const stdBillsLibListsModel = new STDGLJListModel();
const stdGLJData = await stdBillsLibListsModel.getGljItemsByRepId(rationRepository[0].gljLib);
// 整理标准工料机库数据
let stdGLJList = {};
let stdGLJListByID = {};
for (const tmp of stdGLJData) {
stdGLJList[tmp.code.toString()] = tmp.ID;
stdGLJListByID[tmp.ID] = tmp;
}
let lastData = {};
// 定额xx下提示的次数
let lastFailCount = 0;
const rationData = [];
// 编码列表,用于查找库中是否有对应数据
let rationCodeList = [];
let gljCodeList = [];
// 插入失败的工料机列表(用于提示)
let failGLJList = [];
for (const tmp of data) {
if (tmp.length <= 0) {
continue;
}
// 如果第一个字段为null则是工料机数据,放入上一个数据的工料机字段
if (tmp[0] === undefined && Object.keys(lastData).length > 0) {
// 如果不存在对应的工料机库数据则跳过
if (stdGLJList[tmp[1]] === undefined) {
if (lastFailCount === 0) {
failGLJList.push('定额' + lastData.code + '下的');
lastFailCount++;
}
//const failString = '定额' + lastData.code + '下的' + tmp[1];
failGLJList.push(tmp[1]);
continue;
}
const tmpRationGlj = {
gljId: stdGLJList[tmp[1]],
consumeAmt: tmp[4],
proportion: 0,
};
lastData.rationGljList.push(tmpRationGlj);
if (gljCodeList.indexOf(tmp[1]) < 0) {
gljCodeList.push(tmp[1]);
}
continue;
}
if (tmp[0] === '定额' && Object.keys(lastData).length > 0) {
rationData.push(lastData);
}
lastFailCount = 0;
// 组装数据
lastData = {
code: tmp[1],
name: tmp[2],
unit: tmp[3],
caption: tmp[2],
rationRepId: rationRepId,
sectionId: 0,
labourPrice: '0',
materialPrice: '0',
machinePrice: '0',
basePrice: '0',
rationGljList: []
};
// 防止重复加入
if (rationCodeList.indexOf(tmp[1]) < 0) {
rationCodeList.push(tmp[1]);
}
}
// 最后一个入数组
rationData.push(lastData);
// 查找数据库中是否已存在待插入数据
const condition = {
rationRepId: rationRepId,
code: { $in: rationCodeList }
};
const existCodeList = await this.getRationItemByCondition(condition, ['code'], 'code');
// 过滤插入数据
let insertData = [];
//已存在定额,则更新价格及rationGLjList字段
let updateData = [];
for (const ration of rationData) {
if (existCodeList[ration.code] !== undefined) {
updateData.push(ration);
continue;
}
insertData.push(ration);
}
//更新定额
let updateBulk = [];
for(let ration of updateData){
this.calcForRation(stdGLJListByID, ration);
updateBulk.push({
updateOne: {
filter: {rationRepId: rationRepId, code: ration.code},
update: {$set: {rationGljList: ration.rationGljList, labourPrice: ration.labourPrice, materialPrice: ration.materialPrice,
machinePrice: ration.machinePrice, basePrice: ration.basePrice}}
}
});
}
//更新数据库
if(updateBulk.length > 0){
await rationItemModel.bulkWrite(updateBulk);
}
// 如果都已经存在,直接返回
if (insertData.length <= 0) {
return failGLJList;
}
//计算价格
for(let ration of insertData){
this.calcForRation(stdGLJListByID, ration);
}
// 组织id
const counterInfo = await counter.counterDAO.getIDAfterCount(counter.moduleName.rations, insertData.length);
let maxId = counterInfo.sequence_value;
maxId = parseInt(maxId);
let count = 0;
for (const index in insertData) {
insertData[index].ID = maxId - (insertData.length - 1) + count;
count++;
}
// 插入数据库
await rationItemModel.create(insertData);
return failGLJList;
};
/**
* 导出到excel的数据
*
* @param {Number} rationRepId
* @return {Array}
*/
rationItemDAO.prototype.exportExcelData = async function(rationRepId) {
const condition = {
rationRepId: rationRepId
};
const rationDataList = await this.getRationItemByCondition(condition, ['name', 'code', 'ID', 'sectionId', 'feeType', 'caption', 'basePrice', 'jobContent', 'annotation']);
// 整理数据
let rationData = [];
for (const tmp of rationDataList) {
const sectionId = tmp.sectionId <= 0 || tmp.sectionId === undefined ? null : tmp.sectionId;
const feeType = tmp.feeType === '' || tmp.feeType === undefined ? null : tmp.feeType;
const ration = [sectionId, feeType, tmp.ID, tmp.code, tmp.name, tmp.caption, tmp.basePrice, tmp.jobContent, tmp.annotation];
rationData.push(ration);
}
const excelData = [['树ID', '取费专业', '定额ID', '定额编码', '定额名', '定额显示名称', '基价', '工作内容', '附注']];
excelData.push.apply(excelData, rationData);
return excelData;
//根据编号排序,优先级:number-number-..., number, Anumber....
/*let regConnector = /-/g,
regLetter = /[a-z,A-Z]/g,
regNum = /\d+/g;
rationData.sort(function (a, b) {
let aCode = a[3],
bCode = b[3],
rst = 0;
function compareConnector(arrA, arrB) {
let lessArr = arrA.length <= arrB ? arrA : arrB;
for (let i = 0; i < lessArr.length; i++) {
let result = compareUnit(arrA[i], arrB[i]);
if (result !== 0) {
return result;
} else {
}
}
function compareUnit(uA, uB) {
let uAV = parseFloat(uA),
uBV = parseFloat(uB);
if (uAV > uBV) {
return 1;
} else if (uAV < uBV) {
return -1;
}
return 0;
}
}
if (regConnector.test(a) && !regConnector.test(b)) {
rst = -1;
} else if (!regConnector.test(a) && regConnector.test(b)) {
rst = 1;
} else if (regConnector.test(a) && regConnector.test(b)) {
}
});
rationData.sort(function (a, b) {
let aCode = a[3],
bCode = b[3],
rst = 0,
splitA = aCode.split('-'),
splitB = bCode.split('-');
if(splitA[0] > splitB[0]){
rst = 1;
}
else if(splitA[0] < splitB[0]){
rst = -1;
}
else {
if(splitA[1] && splitB[1]){
let floatA = parseFloat(splitA[1]),
floatB = parseFloat(splitB[1]);
if(floatA > floatB){
rst = 1;
}
else if(floatA < floatB){
rst = -1;
}
}
}
return rst;
});*/
/*const excelData = [['树ID', '取费专业', '定额ID', '定额编码', '定额名', '定额显示名称', '基价']];
excelData.push.apply(excelData, rationData);
return excelData;*/
};
/**
* 批量更改章节id
*
* @param {Object} data
* @return {bool}
*/
rationItemDAO.prototype.batchUpdateSectionIdFromExcel = async function(data) {
if (data.length <= 0) {
return false;
}
// 批量执行update
let bulkOprs = [],
sectionIDs = [];
for (const tmp of data) {
let rationId = parseInt(tmp[2]);
rationId = isNaN(rationId) || rationId <= 0 ? 0 : rationId;
let sectionId = parseInt(tmp[0]);
sectionId = isNaN(sectionId) || sectionId <= 0 ? 0 : sectionId;
if (sectionId <= 0 || rationId <= 0) {
continue;
}
sectionIDs.push(sectionId);
// 取费专业
let feeType = tmp[1] ? parseInt(tmp[1]) : null;
feeType = isNaN(feeType) || feeType <= 0 ? null : feeType;
let name = tmp[4];
name = name ? name : '';
let caption = tmp[5];
caption = caption ? caption : '';
let jobContent = tmp[7] ? tmp[7] : '';
let annotation = tmp[8] ? tmp[8] : '';
bulkOprs.push({updateOne: {
filter: {ID: rationId},
update: {$set: {
sectionId,
feeType,
name,
caption,
jobContent,
annotation
}}}
});
}
if(bulkOprs.length <= 0){
throw '无有效数据(树ID、定额ID不为空、且为数值)';
}
await rationItemModel.bulkWrite(bulkOprs);
// 更新章节树工作内容、附注节点选项(全设置为ALL)
sectionIDs = Array.from(new Set(sectionIDs));
if (sectionIDs.length) {
await stdRationSectionModel.updateMany(
{ID: {$in: sectionIDs}},
{$set: {
jobContentSituation: 'ALL',
annotationSituation: 'ALL'
}}
)
}
};
module.exports = new rationItemDAO();