Просмотр исходного кода

Merge branch 'dev' of http://192.168.1.41:3000/maixinrong/Calculation into dev

Tony Kang 2 дней назад
Родитель
Сommit
c3a8321ff6

+ 6 - 0
app/lib/rm/tender.js

@@ -140,6 +140,12 @@ class rptMemPaymentSafe extends RptMemBase {
                 return materialSource.getMaterialPos(params.tender_id, params.material_order, fields);
             case 'mem_material_stage':
                 return materialSource.getMaterialStage(params.tender_id, params.material_order, fields);
+            case 'mem_material_exponent':
+                return materialSource.getMaterialExponent(params.tender_id, params.material_order, fields);
+            case 'mem_material_exponent_node':
+                return materialSource.getMaterialExponentNode(params.tender_id, params.material_order, fields);
+            case 'mem_material_exponent_shard':
+                return materialSource.getMaterialExponentShard(params.tender_id, params.material_order, fields);
             case 'mem_stage_sum_bills':
                 return service.rptStageSumMemory.getStageSumBills(params.tender_id, fields,
                     customDefine.stage_select, customSelect ? customSelect.stage_select : null);

+ 37 - 0
app/lib/rm/tender_material.js

@@ -446,6 +446,43 @@ class ReportMemoryMaterial {
             }];
         }
     }
+
+    async getMaterialExponent(tender_id, material_order, fields) {
+        const material = await this.ctx.service.material.getDataByCondition({tid: tender_id, order: material_order});
+        if (!material) return [];
+
+        const materials = await this.ctx.service.material.getAllDataByCondition({
+            where: {tid: this.ctx.material.tid},
+            orders: [['order', 'desc']],
+        });
+        if (materials.length === 0) return [];
+
+        let result;
+        if (materials[0].order === material.order) {
+            result = await this.ctx.service.materialExponent.getAllDataByCondition({
+                where: { tid: material.tid }
+            });
+        } else {
+            const sql = 'SELECT me.id, me.tid, me.mid, me.type, me.symbol, me.symbol_desc, me.code, me.remark, me.in_time,' +
+                '    meh.type, meh.weight_num, meh.basic_price, meh.basic_times, meh.m_price, meh.calc_num, meh.is_summary' +
+                '  FROM ' + this.ctx.service.materialExponentHistory.tableName + ' meh ' +
+                '  LEFT JOIN ' + this.ctx.service.materialExponent.tableName + ' me ON meh.me_id = me.id ' +
+                '  WHERE meh.tid = ? And meh.mid = ?'+
+                '  ORDER By me.id';
+            result = await this.ctx.app.mysql.query(sql, [material.tid, material.id]);
+        }
+        return result;
+    }
+    async getMaterialExponentNode(tender_id, material_order, fields) {
+        const material = await this.ctx.service.material.getDataByCondition({tid: tender_id, order: material_order});
+        if (!material) return [];
+        return this.ctx.service.materialExponentNode.getAllDataByCondition({ where: { mid: material.id } });
+    }
+    async getMaterialExponentShard(tender_id, material_order, fields) {
+        const material = await this.ctx.service.material.getDataByCondition({tid: tender_id, order: material_order});
+        if (!material) return [];
+        return this.ctx.service.materialExponentNode.getAllDataByCondition({ where: { mid: material.id } });
+    }
 }
 
 module.exports = ReportMemoryMaterial;

+ 16 - 3
app/public/js/cost_stage_analysis.js

@@ -26,10 +26,11 @@ $(document).ready(function() {
                 keys: ['id', 'stage_id', 'tree_id'],
                 calcFun: function(node) {
                     node.sf_percent = node.yf_excl_tax_tp ? ZhCalc.mul(ZhCalc.div(node.sf_excl_tax_tp, node.yf_excl_tax_tp), 100 , 2) : 0;
-                }
+                },
             };
             this.tree = createNewPathTree('ledger', this.treeSetting);
             this.spreadSetting = bllsSpreadSetting;
+            this.spreadSetting.readOnly = readOnly;
             sjsSettingObj.setFxTreeStyle(this.spreadSetting, sjsSettingObj.FxTreeStyle.phasePay);
 
             this.ckBillsSpread = window.location.pathname + '-billsSelect';
@@ -319,10 +320,20 @@ $(document).ready(function() {
             switch (col.field) {
                 case 'code':
                 case 'name':
-                case 'yf_excl_tax_tp':
+                    info.cancel = node.tree_level === 1 || node.node_type > 0 || node.calc_type === 2;
+                    break;
                 case 'in_excl_tax_tp':
+                    info.cancel = node.children && node.children.length > 0;
+                    if (!info.cancel) {
+                        info.cancel = node.tree_level === 1 || node.node_type > 1  || topParent.node_type === 2;
+                    }
+                    break;
+                case 'yf_excl_tax_tp':
                 case 'sf_excl_tax_tp':
-                    info.cancel = node.tree_level === 1 || node.node_type > 0  || [2,3,4].indexOf(topParent.node_type) >= 0;
+                    info.cancel = node.children && node.children.length > 0;
+                    if (!info.cancel) {
+                        info.cancel = node.tree_level === 1 || node.node_type > 0  || topParent.node_type === 2;
+                    }
                     break;
                 case 'num_a':
                 case 'num_b':
@@ -469,7 +480,9 @@ $(document).ready(function() {
             this.sheet = this.spread.getActiveSheet();
             this.data = createAncillaryGcl({ id: 'id', masterId: 'ledger_id', sort: [['d_order', 'asc']] });
             this.dealSpreadSetting = dealSpreadSetting;
+            this.dealSpreadSetting.readOnly = readOnly;
             this.commonSpreadSetting = commonSpreadSetting;
+            this.commonSpreadSetting.readOnly = readOnly;
 
             this.initSpread();
         }

+ 3 - 1
app/public/js/cost_tmpl.js

@@ -128,6 +128,8 @@ $(document).ready(() => {
                 const typeInfo = validColInfo.find(x => { return x.key === data.type; });
                 return typeInfo.name || '';
             };
+            const numCol = validColInfo.find(x => { return x.key === 'num'; });
+            const validCalcCode = numCol.fields.map(x => { return x.replace('num_', '').toUpperCase(); });
             this.spreadSetting = {
                 cols: [
                     { title: '类型', colSpan: '1', rowSpan: '1', field: 'type', hAlign: 1, width: 80, formatter: '@', readOnly: true, getValue: getTypeValue },
@@ -136,7 +138,7 @@ $(document).ready(() => {
                     // { title: '单位', colSpan: '1', rowSpan: '1', field: 'unit', hAlign: 1, width: 60, cellType: 'unit' },
                     {
                         title: '计算代号', colSpan: '1', rowSpan: '1', field: 'calc_code', hAlign: 1, width: 80, cellType: 'customizeCombo',
-                        comboItems: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P'],
+                        comboItems: validCalcCode,
                     },
                     { title: '小数位数', colSpan: '1', rowSpan: '1', field: 'decimal', hAlign: 1, width: 60, type: 'Number' },
                     { title: '期数据', colSpan: '1', rowSpan: '1', field: 'sum', hAlign: 1, width: 60, readOnly: true, cellType: 'signalCheckbox', show: function(data) {

+ 2 - 2
app/public/js/ledger.js

@@ -2927,8 +2927,8 @@ $(document).ready(function() {
                         if (colSetting.type === 'Number') {
                             const exprInfo = getExprInfo(colSetting.field);
                             const num = _.toNumber(posData[colSetting.field]);
-                            if (num) {
-                                posData[colSetting.field] = num;
+                            if (_.isNumber(num)) {
+                                posData[colSetting.field] = _.isFinite(num) ? num : 0;
                                 if (exprInfo) posData[exprInfo.expr] = '';
                                 bPaste = true;
                             } else {

+ 1 - 2
app/public/js/ledger_check.js

@@ -171,8 +171,7 @@ const ledgerCheckUtil = {
             }
         };
         for (const topLevel of ledgerTree.children) {
-            if ([1, 2, 3, 4].indexOf(topLevel.node_type) < 0) continue;
-
+            // if ([1, 2, 3, 4].indexOf(topLevel.node_type) < 0) continue;
             addXmjCheck(topLevel);
         }
         const xmjPart = {}, xmjIndex = [];

+ 4 - 2
app/public/js/pos_calc_tmpl.js

@@ -540,16 +540,18 @@ $(document).ready(() => {
                 const typeInfo = validColInfo.find(x => { return x.key === data.type; });
                 return typeInfo.name || '';
             };
+            const numCol = validColInfo.find(x => { return x.key === 'num'; });
+            const validCalcCode = numCol.fields.map(x => { return x.replace('num_', '').toUpperCase(); });
             this.spreadSetting = {
                 cols: [
                     { title: '类型', colSpan: '1', rowSpan: '1', field: 'type', hAlign: 1, width: 80, formatter: '@', readOnly: true, getValue: getTypeValue },
                     { title: '列名', colSpan: '1', rowSpan: '1', field: 'title', hAlign: 0, width: 130, formatter: '@' },
                     { title: '列宽', colSpan: '1', rowSpan: '1', field: 'width', hAlign: 1, width: 70, type: 'Number' },
                     { title: '单位', colSpan: '1', rowSpan: '1', field: 'unit', hAlign: 1, width: 60, cellType: 'unit' },
-                    { title: '计算代号', colSpan: '1', rowSpan: '1', field: 'calc_code', hAlign: 1, width: 80, cellType: 'customizeCombo', comboItems: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'], },
+                    { title: '计算代号', colSpan: '1', rowSpan: '1', field: 'calc_code', hAlign: 1, width: 80, cellType: 'customizeCombo', comboItems: validCalcCode, },
                     { title: '小数位数', colSpan: '1', rowSpan: '1', field: 'decimal', hAlign: 1, width: 60, type: 'Number' },
                     { title: '规格类型', colSpan: '1', rowSpan: '1', field: 'spec_set', hAlign: 1, width: 80, cellType: 'customizeCombo', cellTypeKey: 'spec', comboItems: specList, },
-                    { title: '关联列代号', colSpan: '1', rowSpan: '1', field: 'rela_col', hAlign: 1, width: 80, cellType: 'customizeCombo', comboItems: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'], },
+                    { title: '关联列代号', colSpan: '1', rowSpan: '1', field: 'rela_col', hAlign: 1, width: 80, cellType: 'customizeCombo', comboItems: validCalcCode, },
                     { title: '计算公式', colSpan: '1', rowSpan: '1', field: 'expr', hAlign: 0, width: 250 },
                 ],
                 emptyRows: 0,

+ 1 - 1
app/service/calc_tmpl.js

@@ -520,7 +520,7 @@ module.exports = app => {
             if (!org || org.pid !== this.ctx.session.sessionProject.id) throw '复制的模板不存在,请刷新后重试';
 
             await this.getProjectCalcTmplSet();
-            const count = await this.count({pid: this.ctx.session.sessionProject.id, type});
+            const count = await this.count({pid: this.ctx.session.sessionProject.id, type: org.type});
             if (count >= this.projectSet[org.type].validCount) throw '已达模板使用上限';
 
             const insertData = {

+ 4 - 2
app/service/pos_calc_detail.js

@@ -73,8 +73,10 @@ module.exports = app => {
             if (updateData.spec !== undefined) {
                 calc = true;
                 data.spec = updateData.spec;
-                const sv = template.specValue.find(x => { return x.spec === data.spec; });
-                data[template.spec_rela] = sv ? sv.value : 0;
+                if (template.spec_rela) {
+                    const sv = template.specValue.find(x => { return x.spec === data.spec; });
+                    data[template.spec_rela] = sv ? sv.value : 0;
+                }
             }
             if (updateData[template.spec_rela] !== undefined) delete updateData[template.spec_rela];
             this.ctx.service.calcTmpl.calcByTemplate(data, updateData, orgData, template.calc_expr, { qty: 'expr' });

+ 12 - 0
app/service/report.js

@@ -293,6 +293,18 @@ module.exports = app => {
                             runnableRst.push(materialSource.getMaterialStage(params.tender_id, params.material_order, memFieldKeys[filter]));
                             runnableKey.push(filter);
                             break;
+                        case 'mem_material_exponent':
+                            runnableRst.push(materialSource.getMaterialExponent(params.tender_id, params.material_order, memFieldKeys[filter]));
+                            runnableKey.push(filter);
+                            break;
+                        case 'mem_material_exponent_node':
+                            runnableRst.push(materialSource.getMaterialExponentNode(params.tender_id, params.material_order, memFieldKeys[filter]));
+                            runnableKey.push(filter);
+                            break;
+                        case 'mem_material_exponent_shard':
+                            runnableRst.push(materialSource.getMaterialExponentShard(params.tender_id, params.material_order, memFieldKeys[filter]));
+                            runnableKey.push(filter);
+                            break;
                         case 'mem_stage_sum_bills':
                             runnableRst.push(service.rptStageSumMemory.getStageSumBills(params.tender_id, memFieldKeys[filter],
                                 customDefine.stage_select, customSelect ? customSelect.stage_select : null));

+ 16 - 1
app/service/stage_audit.js

@@ -1555,13 +1555,28 @@ module.exports = app => {
         async _auditCheckCancelAnd(stage) {
             const accountId = this.ctx.session.sessionUser.accountId;
             const selfAuditor = stage.flowAuditors.find(x => { return x.aid === accountId; });
-            if (!selfAuditor || selfAuditor.status !== auditConst.status.checked) throw '不可撤回';
+            const nextChecked = selfAuditor && selfAuditor.audit_group_order ? stage.flowAuditors.find(x => { return x.audit_group_order > selfAuditor.audit_group_order && x.status === auditConst.status.checked; }) : null;
+            if (!selfAuditor || selfAuditor.status !== auditConst.status.checked || nextChecked) throw '不可撤回';
+            const skipUpdateData = [];
+            if (selfAuditor.audit_group_order) {
+                const preChecked = stage.flowAuditors.filter(x => { return x.audit_group_order < selfAuditor.audit_group_order && x.status === auditConst.status.checked; }).sort((a, b) => { return a.audit_group_order - b.audit_group_order});
+                const minCancelOrder = preChecked.length > 0 ? preChecked[preChecked.length - 1].audit_group_order + 1 : 0;
+                for (const a of stage.flowAuditors) {
+                    if (a.status !== auditConst.status.checkSkip) continue;
+                    if (a.aid === accountId) continue;
+                    if (a.audit_group_order > selfAuditor.audit_group_order || a.audit_group_order < minCancelOrder) continue;
+                    skipUpdateData.push({ id: a.id, status: auditConst.status.checking, opinion: '', end_time: null });
+                }
+            }
 
             const transaction = await this.db.beginTransaction();
             try {
                 await transaction.update(this.tableName, {
                     id: selfAuditor.id, status: auditConst.status.checking, opinion: '', end_time: null,
                 });
+                if (skipUpdateData.length > 0) await transaction.updateRows(this.tableName, skipUpdateData);
+                // 2026-02-09,需求要求仅该撤回情况触发inner_flow
+                await this.ctx.service.specMsg.addStageMsg(transaction, this.ctx.session.sessionProject.id, stage, pushOperate.stage.inner_flow);
                 await transaction.commit();
             } catch(err) {
                 await transaction.rollback();