Browse Source

招标预算

MaiXinRong 1 year ago
parent
commit
6b280c8179

+ 4 - 1
app/controller/budget_controller.js

@@ -38,6 +38,7 @@ module.exports = app => {
                     bl.gu_tp = await ctx.service.budgetGu.getSumTp(bl.budget_id);
                     bl.gai_tp = await ctx.service.budgetGai.getSumTp(bl.budget_id);
                     bl.yu_tp = await ctx.service.budgetYu.getSumTp(bl.budget_id);
+                    bl.zb_tp = await ctx.service.budgetZb.getSumTp(bl.budget_id);
                 }
                 renderData.tenderList = await ctx.service.tender.getList4Select('stage');
                 renderData.categoryData = await this.ctx.service.category.getAllCategory(this.ctx.session.sessionProject.id);
@@ -106,6 +107,7 @@ module.exports = app => {
                     data.gu = await ctx.service.budgetGu.getData(ctx.budget.id);
                     data.gai = await ctx.service.budgetGai.getData(ctx.budget.id);
                     data.yu = await ctx.service.budgetYu.getData(ctx.budget.id);
+                    data.zb = await ctx.service.budgetZb.getData(ctx.budget.id);
                 }
                 ctx.body = { err: 0, msg: '', data };
             } catch (err) {
@@ -167,13 +169,14 @@ module.exports = app => {
                 case 'gu': return this.ctx.service.budgetGu;
                 case 'gai': return this.ctx.service.budgetGai;
                 case 'yu': return this.ctx.service.budgetYu;
+                case 'zb': return this.ctx.service.budgetZb;
                 default: return null;
             }
         }
         async _getNeedGcl() {
             if (!this.ctx.params.btype) throw '参数错误';
             const funRela = await this.ctx.service.project.getFunRela(this.ctx.session.sessionProject.id);
-            return this.ctx.params.btype === 'yu' && !!funRela.needGcl;
+            return ['yu', 'zb'].indexOf(this.ctx.params.btype) >= 0 && !!funRela.needGcl;
         }
 
         async detail(ctx) {

+ 20 - 0
app/lib/budget_final.js

@@ -133,6 +133,20 @@ class BudgetFinal {
         });
     }
 
+    async _loadZb(budget) {
+        const helper = this.ctx.helper;
+        const zb = await this.ctx.service.budgetYu.getData(budget.id);
+        const zbTree = new BillsTree(this.ctx, { id: 'tree_id', pid: 'tree_pid', order: 'order', level: 'level', rootId: -1, calcFields: ['total_price'] });
+        zbTree.loadDatas(zb);
+        zbTree.calculateAll();
+        this.finalTree.loadTree(zbTree, function (cur, source) {
+            cur.base = true;
+            cur.zb_dgn_qty1 = helper.add(cur.zb_dgn_qty1, source.dgn_qty1);
+            cur.zb_dgn_qty2 = helper.add(cur.zb_dgn_qty2, source.dgn_qty2);
+            cur.zb_tp = helper.add(cur.zb_tp, source.total_price);
+        });
+    }
+
     async _loadTender(id) {
         const helper = this.ctx.helper;
         const bills = await this.ctx.service.ledger.getFinalData(id, ['id', 'ledger_id', 'ledger_pid', 'level', 'order', 'full_path', 'is_leaf',
@@ -215,6 +229,10 @@ class BudgetFinal {
             node.yu_dgn_qty = node.yu_dgn_qty1
                 ? (node.yu_dgn_qty2 ? node.yu_dgn_qty1 + '/' + node.yu_dgn_qty2 : node.yu_dgn_qty1 + '')
                 : (node.yu_dgn_qty2 ? '/' + node.yu_dgn_qty2 : '');
+            node.zb_dgn_price = helper.div(node.zb_tp, node.zb_dgn_qty1, 2);
+            node.zb_dgn_qty = node.zb_dgn_qty1
+                ? (node.zb_dgn_qty2 ? node.zb_dgn_qty1 + '/' + node.zb_dgn_qty2 : node.zb_dgn_qty1 + '')
+                : (node.zb_dgn_qty2 ? '/' + node.zb_dgn_qty2 : '');
 
             node.final_dgn_price = helper.div(node.final_tp, node.final_dgn_qty1, 2);
             node.final_dgn_qty = node.final_dgn_qty1
@@ -246,6 +264,7 @@ class BudgetFinal {
                 gu_dgn_qty1: x.gu_dgn_qty1 || 0, gu_dgn_qty2: x.gu_dgn_qty2 || 0, gu_dgn_qty: x.gu_dgn_qty, gu_dgn_price: x.gu_dgn_price || 0, gu_tp: x.gu_tp || 0,
                 gai_dgn_qty1: x.gai_dgn_qty1 || 0, gai_dgn_qty2: x.gai_dgn_qty2 || 0, gai_dgn_qty: x.gai_dgn_qty, gai_dgn_price: x.gai_dgn_price || 0, gai_tp: x.gai_tp || 0,
                 yu_dgn_qty1: x.yu_dgn_qty1 || 0, yu_dgn_qty2: x.yu_dgn_qty2 || 0, yu_dgn_qty: x.yu_dgn_qty, yu_dgn_price: x.yu_dgn_price || 0, yu_tp: x.yu_tp || 0,
+                zb_dgn_qty1: x.zb_dgn_qty1 || 0, zb_dgn_qty2: x.zb_dgn_qty2 || 0, zb_dgn_qty: x.zb_dgn_qty, zb_dgn_price: x.zb_dgn_price || 0, zb_tp: x.zb_tp || 0,
 
                 dgn_qty1: x.dgn_qty1 || 0, dgn_qty2: x.dgn_qty2 || 0, total_price: x.total_price || 0,
                 final_dgn_qty1: x.final_dgn_qty1 || 0, final_dgn_qty2: x.final_dgn_qty2 || 0, final_tp: x.final_tp || 0,
@@ -266,6 +285,7 @@ class BudgetFinal {
         await this._loadGai(budget);
         await this._loadGu(budget);
         await this._loadYu(budget);
+        await this._loadZb(budget);
         for (const t of final.tender) {
             await this._loadTender(t);
         }

+ 16 - 0
app/public/js/budget_compare.js

@@ -33,6 +33,9 @@ $(document).ready(() => {
             {title: '施工图预算|数量1/数量2', colSpan: '3|1', rowSpan: '1|1', field: 'yu_dgn_qty', hAlign: 2, width: 80, bc_type: 'number'},
             {title: '|经济指标', colSpan: '|1', rowSpan: '|1', field: 'yu_dgn_price', hAlign: 2, width: 80, type: 'Number', bc_type: 'number'},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'yu_tp', hAlign: 2, width: 80, type: 'Number', bc_type: 'number'},
+            {title: '招标预算|数量1/数量2', colSpan: '3|1', rowSpan: '1|1', field: 'zb_dgn_qty', hAlign: 2, width: 80, bc_type: 'number'},
+            {title: '|经济指标', colSpan: '|1', rowSpan: '|1', field: 'zb_dgn_price', hAlign: 2, width: 80, type: 'Number', bc_type: 'number'},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'zb_tp', hAlign: 2, width: 80, type: 'Number', bc_type: 'number'},
             {title: '台账|数量1/数量2', colSpan: '3|1', rowSpan: '1|1', field: 'dgn_qty', hAlign: 2, width: 80, bc_type: 'number', visible: false},
             {title: '|经济指标', colSpan: '|1', rowSpan: '|1', field: 'dgn_price', hAlign: 2, width: 80, type: 'Number', bc_type: 'number', visible: false},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 80, type: 'Number', bc_type: 'number', visible: false},
@@ -163,6 +166,15 @@ $(document).ready(() => {
                 cur.yu_dgn_qty2 = ZhCalc.add(cur.yu_dgn_qty2, source.dgn_qty2);
                 cur.yu_tp = ZhCalc.add(cur.yu_tp, source.total_price);
             });
+            const zbTree = createNewPathTree('ledger', setting);
+            zbTree.loadDatas(result.zb);
+            treeCalc.calculateAll(zbTree);
+            compareTree.loadTree(zbTree, function (cur, source) {
+                cur.base = true;
+                cur.zb_dgn_qty1 = ZhCalc.add(cur.zb_dgn_qty1, source.dgn_qty1);
+                cur.zb_dgn_qty2 = ZhCalc.add(cur.zb_dgn_qty2, source.dgn_qty2);
+                cur.zb_tp = ZhCalc.add(cur.zb_tp, source.total_price);
+            });
             compareTree.afterLoad(node => {
                 node.gu_dgn_price = ZhCalc.div(node.gu_tp, node.gu_dgn_qty1, 2);
                 node.gu_dgn_qty = node.gu_dgn_qty1
@@ -176,6 +188,10 @@ $(document).ready(() => {
                 node.yu_dgn_qty = node.yu_dgn_qty1
                     ? (node.yu_dgn_qty2 ? node.yu_dgn_qty1 + '/' + node.yu_dgn_qty2 : node.yu_dgn_qty1)
                     : (node.yu_dgn_qty2 ? '/' + node.yu_dgn_qty2 : '');
+                node.zb_dgn_price = ZhCalc.div(node.zb_tp, node.zb_dgn_qty1, 2);
+                node.zb_dgn_qty = node.zb_dgn_qty1
+                    ? (node.zb_dgn_qty2 ? node.zb_dgn_qty1 + '/' + node.zb_dgn_qty2 : node.zb_dgn_qty1)
+                    : (node.zb_dgn_qty2 ? '/' + node.zb_dgn_qty2 : '');
             });
             compareTree.resortChildrenByCustom(function (x, y) {
                 const iCode = compareCode(x.code, y.code);

+ 30 - 0
app/service/budget.js

@@ -99,6 +99,7 @@ module.exports = app => {
             await this.ctx.service.budgetGu.initByTemplate(transaction, operate.insertId, budgetStd.gu_template_id);
             await this.ctx.service.budgetGai.initByTemplate(transaction, operate.insertId, budgetStd.gai_template_id);
             await this.ctx.service.budgetYu.initByTemplate(transaction, operate.insertId, budgetStd.yu_template_id);
+            await this.ctx.service.budgetZb.initByTemplate(transaction, operate.insertId, budgetStd.zb_template_id);
             return operate.insertId;
         }
 
@@ -139,6 +140,7 @@ module.exports = app => {
                 await transaction.delete(this.ctx.service.budgetGu.tableName, { bid: id });
                 await transaction.delete(this.ctx.service.budgetGai.tableName, { bid: id });
                 await transaction.delete(this.ctx.service.budgetYu.tableName, { bid: id });
+                await transaction.delete(this.ctx.service.budgetZb.tableName, { bid: id });
                 await transaction.commit();
                 return true;
             } catch (err) {
@@ -203,6 +205,31 @@ module.exports = app => {
             return result;
         }
 
+        async _getZbUpdateData(newDecimal, orgDecimal) {
+            if (newDecimal.qty >= orgDecimal.qty && newDecimal.up >= orgDecimal.up && newDecimal.tp === orgDecimal.tp) return [];
+            const datas = await this.ctx.service.budgetZb.getData(this.ctx.budget.id);
+            const result = [];
+            for (const d of datas) {
+                if (d.b_code) {
+                    if (!d.is_leaf) continue;
+                    const quantity = this.ctx.helper.round(d.quantity, newDecimal.qty);
+                    const unit_price = this.ctx.helper.round(d.unit_price, newDecimal.up);
+                    const total_price = this.ctx.helper.mul(unit_price, quantity, newDecimal.tp);
+                    if (quantity !== d.quantity || unit_price !== d.unit_price || total_price !== d.total_price) {
+                        result.push({ id: d.id, tree_id: d.tree_id, quantity, unit_price, total_price });
+                    }
+                } else {
+                    const dgn_qty1 = this.ctx.helper.round(d.dgn_qty1, newDecimal.qty);
+                    const dgn_qty2 = this.ctx.helper.round(d.dgn_qty2, newDecimal.qty);
+                    const total_price = d.is_leaf ? this.ctx.helper.round(d.total_price, newDecimal.tp) : 0;
+                    if (dgn_qty1 !== d.dgn_qty1 || dgn_qty2 !== d.dgn_qty2 || total_price !== d.total_price) {
+                        result.push({ id: d.id, tree_id: d.tree_id, dgn_qty1, dgn_qty2, total_price });
+                    }
+                }
+            }
+            return result;
+        }
+
         async saveDecimal(decimal, page) {
             const newDecimal = JSON.parse(JSON.stringify(this.ctx.budget.decimal));
             if (decimal.qty >= 0 && decimal.qty <= 6) newDecimal.qty = decimal.qty;
@@ -212,17 +239,20 @@ module.exports = app => {
             const guDatas = await this._getGuUpdateData(newDecimal, this.ctx.budget.decimal);
             const gaiDatas = await this._getGaiUpdateData(newDecimal, this.ctx.budget.decimal);
             const yuDatas = await this._getYuUpdateData(newDecimal, this.ctx.budget.decimal);
+            const zbDatas = await this._getZbUpdateData(newDecimal, this.ctx.budget.decimal);
             const conn = await this.db.beginTransaction();
             try {
                 const result = await conn.update(this.tableName, { id: this.ctx.budget.id, decimal: JSON.stringify(newDecimal) });
                 if (guDatas.length > 0) await conn.updateRows(this.ctx.service.budgetGu.tableName, guDatas);
                 if (gaiDatas.length > 0) await conn.updateRows(this.ctx.service.budgetGai.tableName, gaiDatas);
                 if (yuDatas.length > 0) await conn.updateRows(this.ctx.service.budgetYu.tableName, yuDatas);
+                if (zbDatas.length > 0) await conn.updateRows(this.ctx.service.budgetZb.tableName, zbDatas);
                 await conn.commit();
                 switch (page) {
                     case 'gu': return { update: guDatas };
                     case 'gai': return { update: gaiDatas };
                     case 'yu': return { update: yuDatas };
+                    case 'zb': return { update: zbDatas };
                 }
             } catch (err) {
                 await conn.rollback();

+ 28 - 0
app/service/budget_zb.js

@@ -0,0 +1,28 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Mai
+ * @date
+ * @version
+ */
+
+module.exports = app => {
+    class BudgetZb extends app.BaseBudgetService {
+
+        /**
+         * 构造函数
+         *
+         * @param {Object} ctx - egg全局变量
+         * @param {String} tableName - 表名
+         * @return {void}
+         */
+        constructor(ctx) {
+            super(ctx, { keyPre: 'budget_zb_maxLid:' });
+            this.tableName = 'budget_zb';
+        }
+    }
+
+    return BudgetZb;
+};

+ 1 - 0
app/view/budget/sub_menu_list.ejs

@@ -4,6 +4,7 @@
 <nav-menu title="投资估算" url="/budget/<%= ctx.budget.id %>/gu" ml="3" active="<%= ctx.url.indexOf('/gu') %>"></nav-menu>
 <nav-menu title="设计概算" url="/budget/<%= ctx.budget.id %>/gai%>" ml="3" active="<%= ctx.url.indexOf('/gai') %>"></nav-menu>
 <nav-menu title="施工图预算" url="/budget/<%= ctx.budget.id %>/yu" ml="3" active="<%= ctx.url.indexOf('/yu') %>"></nav-menu>
+<nav-menu title="招标预算" url="/budget/<%= ctx.budget.id %>/zb" ml="3" active="<%= ctx.url.indexOf('/zb') %>"></nav-menu>
 <% if (!ctx.budget.readOnly && ctx.url.indexOf('/compare') === -1 && ctx.url !== '/budget/' + ctx.budget.id) { %>
 <div class="contarl-box"><button class="btn btn-primary btn-sm btn-block" data-toggle="modal" data-target="#budget-set">设置</button></div>
 <% } %>