|
|
@@ -17,7 +17,7 @@ const costFields = {
|
|
|
hisFields: ['calc_his'],
|
|
|
taxFields: ['tax'],
|
|
|
treeFields: ['tree_id', 'tree_pid', 'tree_level', 'tree_order', 'tree_full_path', 'tree_is_leaf'],
|
|
|
- baseFields: ['id', 'cost_id', 'tender_id', 'stage_id', 'node_type', 'calc_type'],
|
|
|
+ baseFields: ['id', 'cost_id', 'tender_id', 'stage_id', 'node_type', 'calc_type', 'has_detail', 'import_cost_id'],
|
|
|
};
|
|
|
costFields.sumFields = [...costFields.calcFields, ...costFields.selfCalcFields];
|
|
|
costFields.preCopyFields = [...costFields.treeFields, ...costFields.textFields, ...costFields.selfTextFields, ...costFields.calcFields, ...costFields.selfCalcFields, ...costFields.taxFields];
|
|
|
@@ -140,14 +140,13 @@ module.exports = app => {
|
|
|
async init(stage, transaction) {
|
|
|
if (!this.ctx.subProject.cost_analysis_template) throw '未设置成本分析模板,请联系管理员设置';
|
|
|
if (!stage || !transaction) throw '成本分析数据错误';
|
|
|
- const userId = this.ctx.session.sessionUser.accountId;
|
|
|
|
|
|
const templateData = await this.ctx.service.tenderNodeTemplate.getData(this.ctx.subProject.cost_analysis_template);
|
|
|
if (templateData.length === 0) throw '台账模板无数据,连请联系管理员修改';
|
|
|
const calcTemplate = await this.ctx.service.calcTmpl.getTemplate(stage.calc_template);
|
|
|
if (!calcTemplate) throw '计算模板未定义,请联系管理员设置';
|
|
|
|
|
|
- const insertTemplateData = [], insertLedgerData = [], insertDetailData = [];
|
|
|
+ const insertTemplateData = [];
|
|
|
let maxId = 0;
|
|
|
for (const b of templateData) {
|
|
|
const bills = {
|
|
|
@@ -160,68 +159,12 @@ module.exports = app => {
|
|
|
this._getDefaultData(bills, stage);
|
|
|
insertTemplateData.push(bills);
|
|
|
}
|
|
|
- const relaStage = await this.service.costStage.getStage(JSON.parse(stage.rela_stage).sid);
|
|
|
- const costStageLedger = await this.getCostStageData(relaStage);
|
|
|
- const costNode = insertTemplateData.find(x => { return x.node_type === 2 && x.tree_level === 1; });
|
|
|
- if (costStageLedger.nodes.length > 0) costNode.tree_is_leaf = 0;
|
|
|
- for (const [i, node] of costStageLedger.nodes.entries()) {
|
|
|
- const parent = costStageLedger.getParent(node);
|
|
|
- const newParent = parent ? insertLedgerData.find(x => { return x.tree_id === parent.new_tree_id; }) : costNode;
|
|
|
- const ln = { calc_type: 2 };
|
|
|
- this._getDefaultData(ln, stage);
|
|
|
- ln.node_type = 0;
|
|
|
- ln.cost_id = node.cost_id;
|
|
|
- ln.tree_id = maxId + i + 1;
|
|
|
- node.new_tree_id = ln.tree_id;
|
|
|
- ln.tree_pid = newParent.tree_id;
|
|
|
- ln.tree_order = node.tree_order;
|
|
|
- ln.tree_level = newParent.tree_level + 1;
|
|
|
- ln.tree_full_path = newParent.tree_full_path + '-' + ln.tree_id;
|
|
|
- ln.tree_is_leaf = node.tree_is_leaf;
|
|
|
- ln.code = node.code;
|
|
|
- ln.name = node.name;
|
|
|
- ln.unit = node.unit;
|
|
|
- ln.tax = 0;
|
|
|
- for (const prop of costFields.sumFields) {
|
|
|
- ln[prop] = 0;
|
|
|
- }
|
|
|
- insertLedgerData.push(ln);
|
|
|
- if (node.detail && node.detail.length > 0) {
|
|
|
- for (const [i, d] of node.detail.entries()) {
|
|
|
- const idd = {
|
|
|
- id: this.uuid.v4(), tender_id: stage.tid, stage_id: stage.id,
|
|
|
- add_user_id: userId, update_user_id: userId,
|
|
|
- ledger_id: ln.id, cost_id: ln.cost_id, source_id: d.source_cid,
|
|
|
- d_order: i+1,
|
|
|
- code: d.code, name: d.name, party_b: d.party_b || '', tax: d.tax || 0,
|
|
|
- yf_excl_tax_tp: d.yf_excl_tax_tp || 0, in_excl_tax_tp: d.in_excl_tax_tp || 0, sf_excl_tax_tp: d.sf_excl_tax_tp || 0,
|
|
|
- is_deal: d.is_deal,
|
|
|
- };
|
|
|
- this.ctx.service.calcTmpl.calcByTemplate(idd, idd, idd, calcTemplate.calc_expr);
|
|
|
- idd.sf_percent = idd.yf_excl_tax_tp ? this.ctx.helper.mul(this.ctx.helper.div(idd.sf_excl_tax_tp, idd.yf_excl_tax_tp), 100, 2) : 0;
|
|
|
- insertDetailData.push(idd);
|
|
|
- for (const prop of costFields.sumFields) {
|
|
|
- ln[prop] = this.ctx.helper.add(ln[prop], idd[prop]);
|
|
|
- }
|
|
|
- }
|
|
|
- } else {
|
|
|
- ln.tax = node.tax;
|
|
|
- ln.yf_excl_tax_tp = node.end_yf_excl_tax_tp || 0;
|
|
|
- ln.in_excl_tax_tp = node.end_in_excl_tax_tp || 0;
|
|
|
- ln.sf_excl_tax_tp = node.end_sf_excl_tax_tp || 0;
|
|
|
- this.ctx.service.calcTmpl.calcByTemplate(ln, ln, ln, calcTemplate.calc_expr);
|
|
|
- }
|
|
|
- ln.sf_percent = ln.yf_excl_tax_tp ? this.ctx.helper.mul(this.ctx.helper.div(ln.sf_excl_tax_tp, ln.yf_excl_tax_tp), 100, 2) : 0;
|
|
|
- }
|
|
|
|
|
|
await transaction.insert(this.tableName, insertTemplateData);
|
|
|
- await transaction.insert(this.tableName, insertLedgerData);
|
|
|
- if (insertDetailData.length > 0) await transaction.insert(this.ctx.service.costStageAnalysisDetail.tableName, insertDetailData);
|
|
|
}
|
|
|
async initByPre(stage, preStage, transaction) {
|
|
|
if (!stage || !preStage || !transaction) throw '成本分析数据错误';
|
|
|
- const userId = this.ctx.session.sessionUser.accountId;
|
|
|
- const insertData = [], insertDetailData = [];
|
|
|
+ const insertData = [];
|
|
|
let maxId = 0;
|
|
|
if (!stage.calcTemplate) stage.calcTemplate = await this.service.calcTmpl.getTemplate(stage.calc_template);
|
|
|
|
|
|
@@ -235,93 +178,23 @@ module.exports = app => {
|
|
|
const preDetails = await this.ctx.service.costStageAnalysisDetail.getReadData(preStage);
|
|
|
for (const pl of preLedger.nodes) {
|
|
|
if (pl.tree_is_leaf) pl.detail = preDetails.filter(x => { return x.ledger_id === pl.id; });
|
|
|
- if (pl.tree_level > 1) {
|
|
|
- const parent = preLedger.getTopParent(pl);
|
|
|
- if (parent.node_type === 2) continue;
|
|
|
- }
|
|
|
const idata = {};
|
|
|
this._getDefaultData(idata, stage);
|
|
|
idata.cost_id = pl.cost_id;
|
|
|
idata.node_type = pl.node_type;
|
|
|
idata.calc_type = pl.calc_type;
|
|
|
- for (const prop of costFields.preCopyFields) {
|
|
|
- idata[prop] = pl[prop];
|
|
|
+ idata.has_detail = pl.has_detail && pl.detail.length > 0;
|
|
|
+ idata.import_cost_id = pl.import_cost_id;
|
|
|
+ if (!idata.has_detail) {
|
|
|
+ for (const prop of costFields.preCopyFields) {
|
|
|
+ idata[prop] = pl[prop];
|
|
|
+ }
|
|
|
}
|
|
|
maxId = Math.max(maxId, idata.tree_id);
|
|
|
insertData.push(idata);
|
|
|
}
|
|
|
|
|
|
- const relaStage = await this.service.costStage.getStage(JSON.parse(stage.rela_stage).sid);
|
|
|
- const costStageLedger = await this.getCostStageData(relaStage);
|
|
|
- const costNode = insertData.find(x => { return x.node_type === 2 && x.tree_level === 1; });
|
|
|
- if (costStageLedger.nodes.length > 0) costNode.tree_is_leaf = 0;
|
|
|
- for (const [i, node] of costStageLedger.nodes.entries()) {
|
|
|
- const parent = costStageLedger.getParent(node);
|
|
|
- const newParent = parent ? insertData.find(x => { return x.tree_id === parent.new_tree_id; }) : costNode;
|
|
|
- const ln = { calc_type: 2 };
|
|
|
- this._getDefaultData(ln, stage);
|
|
|
- ln.node_type = 0;
|
|
|
- ln.cost_id = node.cost_id;
|
|
|
- ln.tree_id = maxId + i + 1;
|
|
|
- node.new_tree_id = ln.tree_id;
|
|
|
- ln.tree_pid = newParent.tree_id;
|
|
|
- ln.tree_order = node.tree_order;
|
|
|
- ln.tree_level = newParent.tree_level + 1;
|
|
|
- ln.tree_full_path = newParent.tree_full_path + '-' + ln.tree_id;
|
|
|
- ln.tree_is_leaf = node.tree_is_leaf;
|
|
|
- ln.code = node.code;
|
|
|
- ln.name = node.name;
|
|
|
- ln.unit = node.unit;
|
|
|
- ln.tax = node.tax;
|
|
|
- ln.yf_excl_tax_tp = node.end_yf_excl_tax_tp || 0;
|
|
|
- ln.in_excl_tax_tp = node.end_in_excl_tax_tp || 0;
|
|
|
- ln.sf_excl_tax_tp = node.end_sf_excl_tax_tp || 0;
|
|
|
- ln.postil = '';
|
|
|
- ln.sf_percent = 0;
|
|
|
- insertData.push(ln);
|
|
|
- const preSource = preLedger.nodes.find(x => { return x.cost_id === node.cost_id; });
|
|
|
- for (const prop of costFields.selfTextFields) {
|
|
|
- ln[prop] = preSource ? preSource[prop] : '';
|
|
|
- }
|
|
|
- if (!node.detail || node.detail.length === 0) {
|
|
|
- for (const prop of costFields.selfCalcFields) {
|
|
|
- ln[prop] = preSource ? preSource[prop] : 0;
|
|
|
- }
|
|
|
- } else {
|
|
|
- for (const prop of costFields.sumFields) {
|
|
|
- ln[prop] = 0;
|
|
|
- }
|
|
|
- for (const [i, d] of node.detail.entries()) {
|
|
|
- const ld = {
|
|
|
- id: this.uuid.v4(), tender_id: stage.tid, stage_id: stage.id,
|
|
|
- add_user_id: userId, update_user_id: userId,
|
|
|
- ledger_id: ln.id, cost_id: ln.cost_id, source_id: d.source_cid,
|
|
|
- d_order: i+1,
|
|
|
- code: d.code, name: d.name, party_b: d.party_b || '', tax: ln.tax || 0,
|
|
|
- yf_excl_tax_tp: d.yf_excl_tax_tp || 0, in_excl_tax_tp: d.in_excl_tax_tp || 0, sf_excl_tax_tp: d.sf_excl_tax_tp || 0,
|
|
|
- is_deal: d.is_deal,
|
|
|
- };
|
|
|
- const preDetailSource = preSource ? preSource.detail.find(x => { return x.source_id === d.source_cid; }) : undefined;
|
|
|
- for (const prop of costFields.selfTextFields) {
|
|
|
- ld[prop] = preDetailSource ? preDetailSource[prop] : '';
|
|
|
- }
|
|
|
- for (const prop of costFields.selfCalcFields) {
|
|
|
- ld[prop] = preDetailSource ? preDetailSource[prop] || 0 : 0;
|
|
|
- }
|
|
|
- this.ctx.service.calcTmpl.calcByTemplate(ld, ld, ld, stage.calcTemplate.calc_expr);
|
|
|
- ld.sf_percent = ld.yf_excl_tax_tp ? this.ctx.helper.mul(this.ctx.helper.div(ld.sf_excl_tax_tp, ld.yf_excl_tax_tp), 100, 2) : 0;
|
|
|
- for (const prop of costFields.sumFields) {
|
|
|
- ln[prop] = this.ctx.helper.add(ln[prop], ld[prop]);
|
|
|
- }
|
|
|
- insertDetailData.push(ld);
|
|
|
- }
|
|
|
- }
|
|
|
- this.ctx.service.calcTmpl.calcByTemplate(ln, ln, ln, stage.calcTemplate.calc_expr);
|
|
|
- ln.sf_percent = ln.yf_excl_tax_tp ? this.ctx.helper.mul(this.ctx.helper.div(ln.sf_excl_tax_tp, ln.yf_excl_tax_tp), 100, 2) : 0;
|
|
|
- }
|
|
|
-
|
|
|
await transaction.insert(this.tableName, insertData);
|
|
|
- if (insertDetailData.length > 0) await transaction.insert(this.ctx.service.costStageAnalysisDetail.tableName, insertDetailData);
|
|
|
}
|
|
|
async initStageData(transaction, stage, preStage) {
|
|
|
try {
|
|
|
@@ -440,7 +313,7 @@ module.exports = app => {
|
|
|
const ids = id instanceof Array ? id : [id];
|
|
|
if (ids.length === 0) return [];
|
|
|
|
|
|
- const data = await this.db.getAllDataByCondition({ where: { id: ids } });
|
|
|
+ const data = await this.getAllDataByCondition({ where: { id: ids } });
|
|
|
return data;
|
|
|
}
|
|
|
|
|
|
@@ -489,7 +362,7 @@ module.exports = app => {
|
|
|
? select[this.setting.fullPath].replace('-' + select[this.setting.kid], '-' + newData[this.setting.kid])
|
|
|
: newData[this.setting.kid] + '';
|
|
|
newData[this.setting.isLeaf] = true;
|
|
|
- newData.calc_type = calcType.in;
|
|
|
+ newData.calc_type = select ? select.calc_type : calcType.in;
|
|
|
this._getDefaultData(newData, stage);
|
|
|
newDatas.push(newData);
|
|
|
}
|
|
|
@@ -515,6 +388,54 @@ module.exports = app => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ async addAnalysisChild(stage, targetId, count) {
|
|
|
+ if (!stage) return null;
|
|
|
+
|
|
|
+ const select = targetId ? await this.getDataByKid(stage.id, targetId) : null;
|
|
|
+ if (targetId && !select) throw '新增节点数据错误';
|
|
|
+ const children = await this.getChildrenByParentId(stage.id, select[this.setting.kid]);
|
|
|
+ const lastChild = children.length > 0 ? children[children.length - 1] : null;
|
|
|
+
|
|
|
+ this.transaction = await this.db.beginTransaction();
|
|
|
+ const newDatas = [];
|
|
|
+ try {
|
|
|
+ const maxId = await this._getMaxLid(stage.id);
|
|
|
+ for (let i = 1; i < count + 1; i++) {
|
|
|
+ const newData = {};
|
|
|
+ newData[this.setting.kid] = maxId + i;
|
|
|
+ newData[this.setting.pid] = select[this.setting.kid];
|
|
|
+ newData[this.setting.mid] = stage.id;
|
|
|
+ newData[this.setting.level] = select[this.setting.level] + 1;
|
|
|
+ newData[this.setting.order] = lastChild ? lastChild[this.setting.order] + i : i;
|
|
|
+ newData[this.setting.fullPath] = select[this.setting.fullPath] + '-' + newData[this.setting.kid];
|
|
|
+ newData[this.setting.isLeaf] = true;
|
|
|
+ newData.calc_type = select.calc_type;
|
|
|
+ this._getDefaultData(newData, stage);
|
|
|
+ newDatas.push(newData);
|
|
|
+ }
|
|
|
+ const insertResult = await this.transaction.insert(this.tableName, newDatas);
|
|
|
+ this._cacheMaxLid(stage.id, maxId + count);
|
|
|
+
|
|
|
+ if (insertResult.affectedRows !== count) throw '新增节点数据错误';
|
|
|
+ if (!lastChild) {
|
|
|
+ const updateParent = { id: select.id };
|
|
|
+ updateParent[this.setting.isLeaf] = false;
|
|
|
+ this.clearParentingData(updateParent);
|
|
|
+ await this.transaction.update(this.tableName, updateParent);
|
|
|
+ }
|
|
|
+ await this.transaction.commit();
|
|
|
+ this.transaction = null;
|
|
|
+ } catch (err) {
|
|
|
+ await this.transaction.rollback();
|
|
|
+ this.transaction = null;
|
|
|
+ throw err;
|
|
|
+ }
|
|
|
+
|
|
|
+ const createData = await this.getDataByIds(newDatas.map(x => { return x.id; }));
|
|
|
+ const updateData = lastChild ? await this.getDataById(select.id) : [];
|
|
|
+ return {create: createData, update: updateData};
|
|
|
+ }
|
|
|
+
|
|
|
async getProfitUpdateData(updateData) {
|
|
|
const leafNode = await this.getAllDataByCondition({ where: { stage_id: this.ctx.costStage.id, tree_is_leaf: 1 } });
|
|
|
const profit = leafNode.find(x => { return x.node_type === 3; });
|
|
|
@@ -623,6 +544,80 @@ module.exports = app => {
|
|
|
}
|
|
|
return { update: [payUpdate, ...profitUpdate] };
|
|
|
}
|
|
|
+ async importCost(stage, select_id, cost_id) {
|
|
|
+ const userId = this.ctx.session.sessionUser.accountId;
|
|
|
+ const select = await this.getDataById(select_id);
|
|
|
+ if (!select) throw '选择的节点不存在,请刷新后重试';
|
|
|
+
|
|
|
+ const costStageLedger = await this.getCostStageData(stage.relaStage);
|
|
|
+ const nodes = costStageLedger.nodes.filter(x => { return cost_id.indexOf(x.cost_id) >= 0; });
|
|
|
+ if(nodes.length === 0 || nodes.length !== cost_id.length) throw '选择的成本数据不存在,请刷新后重试';
|
|
|
+
|
|
|
+ const orgDetailDatas = await this.ctx.service.costStageAnalysisDetail.getAllDataByCondition({ where: { ledger_id: select.id, stage_id: stage.id } });
|
|
|
+ const updateData = {
|
|
|
+ id: select.id, tree_id: select.tree_id, update_user_id: userId,
|
|
|
+ import_cost_id: cost_id.join(',')
|
|
|
+ };
|
|
|
+ const insertDetails = [];
|
|
|
+ if (nodes[0].detail.length > 0) {
|
|
|
+ const preStage = stage.stage_order > 1 ? await this.ctx.service.costStage.getStageByOrder(stage.tid, stage.stage_type, stage.stage_order -1) : null;
|
|
|
+ const preDetail = preStage ? await this.ctx.service.costStageAnalysisDetail.getAllDataByCondition({ where: { stage_id: preStage.id, cost_id: select.cost_id } }) : [];
|
|
|
+ for (const node of nodes) {
|
|
|
+ for (const d of node.detail) {
|
|
|
+ let id = insertDetails.find(x => { return x.source_id === d.source_cid && x.is_deal === d.is_deal; });
|
|
|
+ if (!id) {
|
|
|
+ id = {
|
|
|
+ id: this.uuid.v4(), tender_id: stage.tid, stage_id: stage.id,
|
|
|
+ add_user_id: userId, update_user_id: userId,
|
|
|
+ ledger_id: select.id, cost_id: select.cost_id, source_id: d.source_cid, is_deal: d.is_deal,
|
|
|
+ d_order: insertDetails.length + 1,
|
|
|
+ code: d.code, name: d.name, party_b: d.party_b || '', tax: d.tax || 0,
|
|
|
+ };
|
|
|
+ insertDetails.push(id);
|
|
|
+ }
|
|
|
+ id.yf_excl_tax_tp = this.ctx.helper.add(id.yf_excl_tax_tp, d.yf_excl_tax_tp || 0);
|
|
|
+ id.sf_excl_tax_tp = this.ctx.helper.add(id.sf_excl_tax_tp, d.sf_excl_tax_tp || 0);
|
|
|
+ id.in_excl_tax_tp = this.ctx.helper.add(id.in_excl_tax_tp, d.in_excl_tax_tp || 0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for (const id of insertDetails) {
|
|
|
+ let sourceDetail = orgDetailDatas.find(x => { return x.source_id === id.source_id && x.is_deal === id.is_deal; });
|
|
|
+ if (!sourceDetail) sourceDetail = preDetail.find(x => { return x.source_id === id.source_id && x.is_deal === id.is_deal; });
|
|
|
+ for (const prop of costFields.selfCalcFields) {
|
|
|
+ id[prop] = sourceDetail ? sourceDetail[prop] || 0 : 0;
|
|
|
+ }
|
|
|
+ this.ctx.service.calcTmpl.calcByTemplate(id, id, id, stage.calcTemplate.calc_expr);
|
|
|
+ for (const prop of costFields.sumFields) {
|
|
|
+ updateData[prop] = this.ctx.helper.add(updateData[prop], id[prop]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ for (const node of nodes) {
|
|
|
+ updateData.yf_excl_tax_tp = this.ctx.helper.add(updateData.yf_excl_tax_tp, node.end_yf_excl_tax_tp || 0);
|
|
|
+ updateData.sf_excl_tax_tp = this.ctx.helper.add(updateData.sf_excl_tax_tp, node.end_sf_excl_tax_tp || 0);
|
|
|
+ updateData.in_excl_tax_tp = this.ctx.helper.add(updateData.in_excl_tax_tp, node.end_in_excl_tax_tp || 0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.ctx.service.calcTmpl.calcByTemplate(updateData, updateData, select, stage.calcTemplate.calc_expr);
|
|
|
+ const profitUpdate = await this.getProfitUpdateData([updateData]);
|
|
|
+
|
|
|
+ const conn = await this.db.beginTransaction();
|
|
|
+ try {
|
|
|
+ await conn.update(this.tableName, updateData);
|
|
|
+ await conn.updateRows(this.tableName, profitUpdate);
|
|
|
+ await conn.delete(this.ctx.service.costStageAnalysisDetail.tableName, { stage_id: stage.id, ledger_id: select.id });
|
|
|
+ if (insertDetails.length > 0) await conn.insert(this.ctx.service.costStageAnalysisDetail.tableName, insertDetails);
|
|
|
+ await conn.commit();
|
|
|
+ } catch(err) {
|
|
|
+ this.ctx.log(err);
|
|
|
+ await conn.rollback();
|
|
|
+ throw '导入成本数据错误';
|
|
|
+ }
|
|
|
+ return {
|
|
|
+ update: [updateData, ...profitUpdate],
|
|
|
+ detail: { add: insertDetails, del: orgDetailDatas.map(x => { return x.id; }) }
|
|
|
+ };
|
|
|
+ }
|
|
|
async reCalcProfit(stageId) {
|
|
|
if (!this.ctx.costStage) {
|
|
|
const costStage = await this.service.costStage.getStage(stageId);
|