Browse Source

1. 报表内存表,期-计量单元
2. 报表内存表,期-计量单元-全参与人
3. 数据预处理,审批人选择,期-计量单元

MaiXinRong 5 years atrás
parent
commit
608c72d579

+ 5 - 3
app/lib/ledger.js

@@ -334,10 +334,12 @@ class pos {
     /**
      * 计算全部
      */
-    calculateAll() {
-        if (!this.setting.calc) { return; }
+    calculateAll(fun) {
+        const calcFun = fun ? fun : this.setting.calc;
+        if (!calcFun) return;
+
         for (const pos of this.datas) {
-            this.setting.calc(pos);
+            calcFun(pos);
         }
     }
 

+ 19 - 1
app/lib/rpt_data_analysis.js

@@ -834,7 +834,7 @@ const auditSelect = {
     name: '审批人选择',
     hint: '需搭配用户交互--审批人选择一起使用',
     defaultSetting: {
-        table: ['mem_stage_bills_compare'],
+        table: ['mem_stage_bills_compare', 'mem_stage_pos_compare'],
     },
     _stageBillsCompare(data, order) {
         const fields = [];
@@ -854,6 +854,21 @@ const auditSelect = {
             }
         }
     },
+    _stagePosCompare(data, order) {
+        const fields = [];
+        for (const [i, o] of order.entries()) {
+            const sPrefix = 'r' + o + '_';
+            const tPrefix = 'as' + i + '_';
+            fields.push({source: sPrefix + 'contract_qty', target: tPrefix + 'contract_qty'});
+            fields.push({source: sPrefix + 'qc_qty', target: tPrefix + 'qc_qty'});
+            fields.push({source: sPrefix + 'gather_qty', target: tPrefix + 'gather_qty'});
+        }
+        for (const d of data) {
+            for (const f of fields) {
+                d[f.target] = d[f.source];
+            }
+        }
+    },
     fun: function (ctx, data, fieldsKey, options, csRela) {
         if (!ctx.tender || !ctx.stage) return;
         if (!csRela.tplDefine) return;
@@ -878,6 +893,9 @@ const auditSelect = {
                 case 'mem_stage_bills_compare':
                     this._stageBillsCompare(data[t], order);
                     break;
+                case 'mem_stage_pos_compare':
+                    this._stagePosCompare(data[t], order);
+                    break;
             }
         }
     }

+ 2 - 1
app/reports/rpt_component/jpc_flow_tab.js

@@ -1152,7 +1152,8 @@ JpcFlowTabSrv.prototype.createNew = function() {
                             if (contentValuesIdx[rowIdx][2] >= 0) {
                                 const psv = JpcFieldHelper.getValue(page_sum_data_fields[di], contentValuesIdx[rowIdx][2]);
                                 if (psv) {
-                                    rowGrandTotal[di] = rowGrandTotal[di] + parseFloat(parseFloat(psv).toFixed(precisionAmt));
+                                    rowGrandTotal[di] = bc.add(rowGrandTotal[di] ? rowGrandTotal[di] : 0 , parseFloat(psv));
+                                    //rowGrandTotal[di] = rowGrandTotal[di] + parseFloat(parseFloat(psv).toFixed(precisionAmt));
                                 }
                             }
                         }

+ 127 - 18
app/service/report_memory.js

@@ -24,6 +24,31 @@ const stageImVersion = '1.0';
 
 const Ledger = require('../lib/ledger');
 
+const billsFields = (function () {
+    const cur = ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'gather_qty', 'gather_tp', 'postil'];
+    const pre = ['pre_contract_qty', 'pre_contract_tp', 'pre_qc_qty', 'pre_qc_tp', 'pre_gather_qty', 'pre_gather_tp'];
+    const end = ['end_contract_qty', 'end_contract_tp', 'end_qc_qty', 'end_qc_tp', 'end_gather_qty', 'end_gather_tp'];
+    const final = ['final_tp', 'final_ratio'];
+
+    const stage = cur.concat(pre, end, final);
+    const stageEnd = pre.concat(end, final);
+    const bgl = ['qc_bgl_code'];
+
+    return {cur, pre, end, final, stage, stageEnd, bgl};
+})();
+const posFields = (function () {
+    const cur = ['contract_qty', 'qc_qty', 'gather_qty', 'postil'];
+    const pre = ['pre_contract_qty', 'pre_qc_qty', 'pre_gather_qty'];
+    const end = ['end_contract_qty', 'end_qc_qty', 'end_gather_qty'];
+    const final = ['final_ratio'];
+
+    const stage = cur.concat(pre, end, final);
+    const stageEnd = pre.concat(end, final);
+    const bgl = ['qc_bgl_code'];
+
+    return {cur, pre, end, final, stage, stageEnd, bgl};
+})();
+
 const curFields = ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'gather_qty', 'gather_tp', 'postil'];
 const preFields = ['pre_contract_qty', 'pre_contract_tp', 'pre_qc_qty', 'pre_qc_tp', 'pre_gather_qty', 'pre_gather_tp'];
 const endFields = ['end_contract_qty', 'end_contract_tp', 'end_qc_qty', 'end_qc_tp', 'end_gather_qty', 'end_gather_tp'];
@@ -89,6 +114,7 @@ module.exports = app => {
             // 需要缓存的数据
             this.stageImData = null;
             this.changeData = null;
+            this.stageValidRole = [];
         }
 
         _checkFieldsExist(source, check) {
@@ -342,7 +368,7 @@ module.exports = app => {
             }
 
             const billsData = await this.ctx.service.ledger.getData(this.ctx.tender.id);
-            if (this._checkFieldsExist(fields, stageFields)) {
+            if (this._checkFieldsExist(fields, billsFields.stage)) {
                 if (this.ctx.stage.readOnly) {
                     const curStage = await this.ctx.service.stageBills.getAuditorStageData(this.ctx.tender.id,
                         this.ctx.stage.id, this.ctx.stage.curTimes, this.ctx.stage.curOrder);
@@ -356,7 +382,7 @@ module.exports = app => {
                     ]);
                 }
             }
-            if (this._checkFieldsExist(fields, preFields.concat(endFields, finalFields))) {
+            if (this._checkFieldsExist(fields, billsFields.stageEnd)) {
                 const preStage = this.ctx.stage.order > 1 ? await this.ctx.service.stageBillsFinal.getFinalData(this.ctx.tender, this.ctx.stage.order - 1) : [];
                 this.ctx.helper.assignRelaData(billsData, [
                     {data: preStage, fields: ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp'], prefix: 'pre_', relaId: 'lid'}
@@ -365,7 +391,7 @@ module.exports = app => {
             this.billsTree.loadDatas(billsData);
             this.billsTree.calculateAll();
 
-            if (this._checkFieldsExist(fields, bglFields)) {
+            if (this._checkFieldsExist(fields, billsFields.bgl)) {
                 await this._calcBillsBgl();
             }
 
@@ -385,35 +411,67 @@ module.exports = app => {
             ]);
         }
 
+        async _calcPosBgl() {
+            if (!this.ctx.stage) return;
+
+            const helper = this.ctx.helper;
+            const tender = this.ctx.tender;
+            const stage = this.ctx.stage;
+            const bglData = this.ctx.stage.readOnly
+                ? await this.ctx.service.stageChange.getAuditorAllStageData(tender.id, stage.id, stage.curTimes, stage.curOrder)
+                : await this.ctx.service.stageChange.getLastestAllStageData(tender.id, stage.id);
+
+            for (const p of this.pos.datas) {
+                p.qc_bgl_code = '';
+
+                const pBgl = helper._.filter(bglData, {lid: p.lid, pid: p.id});
+                if (pBgl.length === 0) continue;
+                helper._.pullAll(bglData, pBgl);
+                const validBgl = helper._.filter(pBgl, function (x) {
+                    return !helper.checkZero(x.qty);
+                });
+                p.qc_bgl_code = helper._.uniq(helper._.map(validBgl, 'c_code')).join(';');
+            }
+        }
+
         async getStagePosData(tid, sid, fields) {
             await this.ctx.service.tender.checkTender(tid);
             await this.ctx.service.stage.checkStage(sid);
 
             const posData = await this.ctx.service.pos.getAllDataByCondition({ where: {tid: this.ctx.tender.id }});
-            if (this.ctx.stage.readOnly) {
-                const curPosStage = await this.ctx.service.stagePos.getAuditorStageData2(this.ctx.tender.id,
-                    this.ctx.stage.id, this.ctx.stage.curTimes, this.ctx.stage.curOrder);
-                this.ctx.helper.assignRelaData(posData, [
-                    {data: curPosStage, fields: ['contract_qty', 'qc_qty'], prefix: '', relaId: 'pid'}
-                ]);
-            } else {
-                const curPosStage = await this.ctx.service.stagePos.getLastestStageData2(this.ctx.tender.id, this.ctx.stage.id);
+            if (this._checkFieldsExist(fields, posFields.stage)) {
+                if (this.ctx.stage.readOnly) {
+                    const curPosStage = await this.ctx.service.stagePos.getAuditorStageData2(this.ctx.tender.id,
+                        this.ctx.stage.id, this.ctx.stage.curTimes, this.ctx.stage.curOrder);
+                    this.ctx.helper.assignRelaData(posData, [
+                        {data: curPosStage, fields: ['contract_qty', 'qc_qty'], prefix: '', relaId: 'pid'}
+                    ]);
+                } else {
+                    const curPosStage = await this.ctx.service.stagePos.getLastestStageData2(this.ctx.tender.id, this.ctx.stage.id);
+                    this.ctx.helper.assignRelaData(posData, [
+                        {data: curPosStage, fields: ['contract_qty', 'qc_qty'], prefix: '', relaId: 'pid'}
+                    ]);
+                }
+            }
+            if (this._checkFieldsExist(fields, posFields.stageEnd)) {
+                const prePosStage = this.ctx.stage.order > 1 ? await this.ctx.service.stagePosFinal.getFinalData(this.ctx.tender, this.ctx.stage.order - 1) : [];
                 this.ctx.helper.assignRelaData(posData, [
-                    {data: curPosStage, fields: ['contract_qty', 'qc_qty'], prefix: '', relaId: 'pid'}
+                    {data: prePosStage, fields: ['contract_qty', 'qc_qty'], prefix: 'pre_', relaId: 'pid'}
                 ]);
             }
-            const prePosStage = this.ctx.stage.order > 1 ? await this.ctx.service.stagePosFinal.getFinalData(this.ctx.tender, this.ctx.stage.order - 1) : [];
-            this.ctx.helper.assignRelaData(posData, [
-                {data: prePosStage, fields: ['contract_qty', 'qc_qty'], prefix: 'pre_', relaId: 'pid'}
-            ]);
             this.pos.loadDatas(posData);
             this.pos.calculateAll();
 
+            if (this._checkFieldsExist(fields, posFields.bgl)) {
+                await this._calcPosBgl();
+            }
+
             return this.pos.getDatas();
         }
 
         _getStageValidRole () {
             if (!this.ctx.stage) throw '期数据错误,请重试';
+            if (this.stageValidRole && this.stageValidRole.length > 0) return;
 
             const result = [{dataOrder: 0, flowOrder: 0, uid: this.ctx.stage.user_id}];
             for (const auditor of this.ctx.stage.auditors) {
@@ -433,15 +491,16 @@ module.exports = app => {
                     }
                 }
             }
-            return result;
+            this.stageValidRole = result;
         };
 
         async getStageBillsCompareData(tid, sid, fields) {
             await this.ctx.service.tender.checkTender(tid);
             await this.ctx.service.stage.checkStage(sid);
+            await this._getStageValidRole();
 
             const stage = this.ctx.stage, helper = this.ctx.helper;
-            const validRole = this._getStageValidRole();
+            const validRole = this.stageValidRole;
             const billsData = await this.ctx.service.ledger.getData(this.ctx.tender.id);
             const allStageBills = await this.ctx.service.stageBills.getAllDataByCondition({where: {sid: sid}});
 
@@ -521,6 +580,56 @@ module.exports = app => {
             // ]);
         }
 
+        async getStagePosCompareData(tid, sid, fields) {
+            await this.ctx.service.tender.checkTender(tid);
+            await this.ctx.service.stage.checkStage(sid);
+            await this._getStageValidRole();
+
+            const stage = this.ctx.stage, helper = this.ctx.helper;
+            const validRole = this.stageValidRole;
+
+            const allStagePos = await this.ctx.service.stagePos.getAllDataByCondition({where: {sid: sid}});
+            const posData = await this.ctx.service.pos.getAllDataByCondition({ where: {tid: this.ctx.tender.id }});
+            const prePosStage = this.ctx.stage.order > 1 ? await this.ctx.service.stagePosFinal.getFinalData(this.ctx.tender, this.ctx.stage.order - 1) : [];
+            this.ctx.helper.assignRelaData(posData, [
+                {data: prePosStage, fields: ['contract_qty', 'qc_qty'], prefix: 'pre_', relaId: 'pid'}
+            ]);
+            const stagePosIndex = {}, timesLen = 100;
+            for (const role of validRole) {
+                const stagePos = this.ctx.helper._.filter(allStagePos, function (x) {
+                    return x.times < stage.curTimes || (x.times === stage.curTimes && x.order <= role.dataOrder);
+                });
+                this.ctx.helper._.pullAll(allStagePos, stagePos);
+                for (const sp of stagePos) {
+                    const key = 'sp-' + sp.pid;
+                    const spi = stagePosIndex[key];
+                    if (spi) {
+                        if ((spi.times * timesLen + spi.order) < (sp.times * timesLen + sp.order)) stagePosIndex[key] = sp;
+                    } else {
+                        stagePosIndex[key] = sp;
+                    }
+                }
+                const filterStagePos = [];
+                for (const prop in stagePosIndex) {
+                    filterStagePos.push(stagePosIndex[prop]);
+                }
+                this.ctx.helper.assignRelaData(posData, [
+                    {data: filterStagePos, fields: ['contract_qty', 'qc_qty'], prefix: 'r' + role.flowOrder + '_', relaId: 'pid'}
+                ]);
+            }
+            this.pos.loadDatas(posData);
+            this.pos.calculateAll(function (p) {
+                p.pre_gather_qty = helper.add(p.pre_contract_qty, p.pre_qc_qty);
+                for (const role of validRole) {
+                    const prefix = 'r' + role.flowOrder + '_';
+                    p[prefix + 'gather_qty'] = helper.add(p[prefix + 'contract_qty'], p[prefix + 'qc_qty']);
+                }
+
+            });
+
+            return this.pos.getDatas();
+        }
+
         async getStagePayData(tid, sid, fields) {
             await this.ctx.service.tender.checkTender(tid);
             await this.ctx.service.stage.checkStage(sid);

+ 90 - 2
builder_report_index_define.js

@@ -22,6 +22,7 @@ const tag = {
     tp: {type: 'tp'},
     up: {type: 'up'},
 };
+// 其他台账
 const stage_jgcl = {
     name: '期-甲供材料(mem_stage_jgcl)',
     remark: '',
@@ -101,6 +102,7 @@ const stage_other = {
         {name: '截止上期-金额', field: 'pre_tp', type: dataType.currency, tag: {type: 'tp'}},
     ]
 };
+// 变更令
 const change = {
     name: '变更令(mem_change)',
     remark: '',
@@ -184,6 +186,92 @@ const changeBills = {
 
     ]
 };
+// 期 - 计量单元
+const stage_pos = {
+    name: '期-部位明细(mem_stage_pos)',
+    remark: '',
+    id: 34,
+    key: 'stage_pos',
+    prefix: '期-部位明细',
+    cols: [
+        {name: 'id', field: 'id', type: dataType.str},
+        {name: '所属标段id', field: 'tid', type: dataType.int},
+        {name: '所属清单id', field: 'lid', type: dataType.str},
+        {name: '名称', field: 'name', type: dataType.str},
+        {name: '位置', field: 'position', type: dataType.str},
+        {name: '施工复核-数量', field: 'sgfh_qty', type: dataType.currency},
+        {name: '其他错漏-数量', field: 'qtcl_qty', type: dataType.currency},
+        {name: '设计错漏-数量', field: 'sjcl_qty', type: dataType.currency},
+        {name: '台账-数量', field: 'quantity', type: dataType.currency},
+        {name: '图号', field: 'drawing_code', type: dataType.str},
+        {name: '排序', field: 'p_order', type: dataType.str},
+        {name: '本期-合同计量-数量', field: 'contract_qty', type: dataType.currency},
+        {name: '本期-数量变更-数量', field: 'qc_qty', type: dataType.currency},
+        {name: '本期-数量变更-变更令', field: 'qc_bgl_code', type: dataType.str},
+        {name: '本期-完成计量-数量', field: 'gather_qty', type: dataType.currency},
+        {name: '本期批注', field: 'postil', type: dataType.str},
+        {name: '截止上期-合同计量-数量', field: 'pre_contract_qty', type: dataType.currency},
+        {name: '截止上期-数量变更-数量', field: 'pre_qc_qty', type: dataType.currency},
+        {name: '截止上期-完成计量-数量', field: 'pre_gather_qty', type: dataType.currency},
+        {name: '截止本期-合同计量-数量', field: 'end_contract_qty', type: dataType.currency},
+        {name: '截止本期-数量变更-数量', field: 'end_qc_qty', type: dataType.currency},
+        {name: '截止本期-完成计量-数量', field: 'end_gather_qty', type: dataType.currency},
+        {name: '截止本期-完成率', field: 'final_ratio', type: dataType.currency},
+    ],
+};
+const stage_pos_compare = {
+    name: '期-部位明细-全参与人(mem_stage_pos_compare)',
+    remark: '',
+    id: 35,
+    key: 'stage_pos_compare',
+    prefix: '期-部位明细-全参与人',
+    cols: [
+        {name: 'id', field: 'id', type: dataType.str},
+        {name: '所属标段id', field: 'tid', type: dataType.int},
+        {name: '所属清单id', field: 'lid', type: dataType.str},
+        {name: '名称', field: 'name', type: dataType.str},
+        {name: '位置', field: 'position', type: dataType.str},
+        {name: '施工复核-数量', field: 'sgfh_qty', type: dataType.currency},
+        {name: '其他错漏-数量', field: 'qtcl_qty', type: dataType.currency},
+        {name: '设计错漏-数量', field: 'sjcl_qty', type: dataType.currency},
+        {name: '台账-数量', field: 'quantity', type: dataType.currency},
+        {name: '图号', field: 'drawing_code', type: dataType.str},
+        {name: '排序', field: 'p_order', type: dataType.str},
+        {name: '截止上期-合同计量-数量', field: 'pre_contract_qty', type: dataType.currency},
+        {name: '截止上期-数量变更-数量', field: 'pre_qc_qty', type: dataType.currency},
+        {name: '截止上期-完成计量-数量', field: 'pre_gather_qty', type: dataType.currency},
+        {name: '本期-合同计量-数量_0', field: 'r0_contract_qty', type: dataType.currency},
+        {name: '本期-数量变更-数量_0', field: 'r0_qc_qty', type: dataType.currency},
+        {name: '本期-完成计量-数量_0', field: 'r0_gather_qty', type: dataType.currency},
+        {name: '本期-合同计量-数量_1', field: 'r1_contract_qty', type: dataType.currency},
+        {name: '本期-数量变更-数量_1', field: 'r1_qc_qty', type: dataType.currency},
+        {name: '本期-完成计量-数量_1', field: 'r1_gather_qty', type: dataType.currency},
+        {name: '本期-合同计量-数量_2', field: 'r2_contract_qty', type: dataType.currency},
+        {name: '本期-数量变更-数量_2', field: 'r2_qc_qty', type: dataType.currency},
+        {name: '本期-完成计量-数量_2', field: 'r2_gather_qty', type: dataType.currency},
+        {name: '本期-合同计量-数量_3', field: 'r3_contract_qty', type: dataType.currency},
+        {name: '本期-数量变更-数量_3', field: 'r3_qc_qty', type: dataType.currency},
+        {name: '本期-完成计量-数量_3', field: 'r3_gather_qty', type: dataType.currency},
+        {name: '本期-合同计量-数量_4', field: 'r4_contract_qty', type: dataType.currency},
+        {name: '本期-数量变更-数量_4', field: 'r4_qc_qty', type: dataType.currency},
+        {name: '本期-完成计量-数量_4', field: 'r4_gather_qty', type: dataType.currency},
+        {name: '本期-合同计量-数量_5', field: 'r5_contract_qty', type: dataType.currency},
+        {name: '本期-数量变更-数量_5', field: 'r5_qc_qty', type: dataType.currency},
+        {name: '本期-完成计量-数量_5', field: 'r5_gather_qty', type: dataType.currency},
+        {name: '本期-合同计量-数量_6', field: 'r6_contract_qty', type: dataType.currency},
+        {name: '本期-数量变更-数量_6', field: 'r6_qc_qty', type: dataType.currency},
+        {name: '本期-完成计量-数量_6', field: 'r6_gather_qty', type: dataType.currency},
+        {name: '本期-合同计量-数量_7', field: 'r7_contract_qty', type: dataType.currency},
+        {name: '本期-数量变更-数量_7', field: 'r7_qc_qty', type: dataType.currency},
+        {name: '本期-完成计量-数量_7', field: 'r7_gather_qty', type: dataType.currency},
+        {name: '本期-合同计量-数量_8', field: 'r8_contract_qty', type: dataType.currency},
+        {name: '本期-数量变更-数量_8', field: 'r8_qc_qty', type: dataType.currency},
+        {name: '本期-完成计量-数量_8', field: 'r8_gather_qty', type: dataType.currency},
+        {name: '本期-合同计量-数量_9', field: 'r9_contract_qty', type: dataType.currency},
+        {name: '本期-数量变更-数量_9', field: 'r9_qc_qty', type: dataType.currency},
+        {name: '本期-完成计量-数量_9', field: 'r9_gather_qty', type: dataType.currency},
+    ],
+};
 
 const recursiveMkdirSync = async function (pathName) {
     if (!fs.existsSync(pathName)) {
@@ -268,10 +356,10 @@ const exportTableDefine = async function (define) {
     for (const col of define.cols) {
         addFields(tableDefine, col.name, col.field, col.type, col.tag);
     }
-    await saveTableDefine(tableDefine, path.join(savePath, define.key + '.json'));
+    await saveTableDefine(tableDefine, path.join(savePath, define.key + '_define.json'));
 };
 
-const defines = [change, changeBills];
+const defines = [stage_pos, stage_pos_compare];
 for (const d of defines) {
     exportTableDefine(d);
 }

+ 10 - 11
test/app/service/report_memory_temp.test.js

@@ -19,25 +19,24 @@ describe('test/app/service/report_memory.test.js', () => {
         const ctx = app.mockContext();
         savePath = path.join(ctx.app.baseDir,'report_temp');
         const postData = {
-            account: 'zengpeiwen',
-            project: 'P1201',
-            project_password: '123456',
+            account: '734406061@qq.com',
+            project: 'T201711273363',
+            project_password: 'mai654321',
         };
         ctx.session = {};
         const loginResult = yield ctx.service.projectAccount.accountLogin(postData, 2);
         assert(loginResult);
         mockData.session = ctx.session;
     });
-    it('test mem_change_bills && mem_change ', function* () {
+    // 期部位明细数据
+    it('test getStagePos', function* () {
         const ctx = app.mockContext(mockData);
 
-        const change = yield ctx.service.reportMemory.getChangeData(2046);
-        if (change instanceof Array) {
-            yield ctx.helper.saveBufferFile(JSON.stringify(change, '', '\t'), path.join(savePath, 'mem_change.json'));
-        }
-        const data = yield ctx.service.reportMemory.getChangeBillsData(2046);
-        if (data instanceof Array) {
-            yield ctx.helper.saveBufferFile(JSON.stringify(data, '', '\t'), path.join(savePath, 'mem_change_bills.json'));
+        // test12 - 第6期
+        const stage = yield ctx.service.stage.getDataByCondition({tid: 12, order: 6});
+        const mainData = yield ctx.service.reportMemory.getStagePosCompareData(12, stage.id);
+        if (mainData instanceof Array) {
+            yield ctx.helper.saveBufferFile(JSON.stringify(mainData,"","\t"), path.join(savePath, 'mem_stage_pos_compare.json'));
         }
     });
 });