Explorar o código

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

Tony Kang hai 1 ano
pai
achega
2e984f24f4

+ 8 - 8
app/const/spread.js

@@ -527,7 +527,7 @@ const BaseSpreadColSetting = {
                 {title: '台账小计|数量', colSpan: '2|1', rowSpan: '1|1', field: 'quantity', hAlign: 2, width: 60, type: 'Number', readOnly: true},
                 {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 60, type: 'Number', readOnly: true},
             ],
-            drawing_code: [{title: '图(册)号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@'}],
+            drawing_code: [{title: '图(册)号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@', textIndent: 1}],
             node_type: [{title: '费用类别', colSpan: '1', rowSpan: '2', field: 'node_type', hAlign: 0, width: 100, cellType: 'customizeCombo'}],
             memo: [{title: '备注', colSpan: '1', rowSpan: '2', field: 'memo', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}],
             ex_memo1: [{title: 'ex_memo1', colSpan: '1', rowSpan: '2', field: 'ex_memo1', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}, ],
@@ -543,7 +543,7 @@ const BaseSpreadColSetting = {
                 {title: '|其他错漏增减', colSpan: '|1', rowSpan: '|1', field: 'qtcl_qty', hAlign: 2, width: 100, type: 'Number'},
                 {title: '|小计', colSpan: '|1', rowSpan: '|1', field: 'quantity', hAlign: 2, width: 60, type: 'Number', readOnly: true},
             ],
-            drawing_code: [{title: '图(册)号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@'}],
+            drawing_code: [{title: '图(册)号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@', textIndent: 1}],
             node_type: [{title: '费用类别', colSpan: '1', rowSpan: '2', field: 'node_type', hAlign: 0, width: 100, cellType: 'customizeCombo'}],
             ex_memo1: [{title: 'ex_memo1', colSpan: '1', rowSpan: '2', field: 'ex_memo1', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}],
             ex_memo2: [{title: 'ex_memo2', colSpan: '1', rowSpan: '2', field: 'ex_memo2', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}],
@@ -597,7 +597,7 @@ const BaseSpreadColSetting = {
             is_tp: [{title: '总额计量', colSpan: '1', rowSpan: '2', field: 'is_tp', hAlign: 1, width: 60, cellType: 'checkbox'}],
             gxby: [{title: '工序报验', colSpan: '1', rowSpan: '2', field: 'gxby', hAlign: 1, width: 80, formatter: '@', readOnly: true}],
             dagl: [{title: '档案管理', colSpan: '1', rowSpan: '2', field: 'dagl', hAlign: 1, width: 80, formatter: '@', readOnly: true}],
-            drawing_code: [{title: '图(册)号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@'}],
+            drawing_code: [{title: '图(册)号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@', textIndent: 1}],
             memo: [{title: '备注', colSpan: '1', rowSpan: '2', field: 'memo', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}],
             postil: [{title: '本期批注', colSpan: '1', rowSpan: '2', field: 'postil', hAlign: 0, width: 100, formatter: '@', cellType: 'autoTip'},],
             ex_memo1: [{title: 'ex_memo1', colSpan: '1', rowSpan: '2', field: 'ex_memo1', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}],
@@ -622,7 +622,7 @@ const BaseSpreadColSetting = {
                 {title: '|完成', colSpan: '|1', rowSpan: '|1', field: 'end_gather_qty', hAlign: 2, width: 60, type: 'Number', readOnly: true},
             ],
             postil: [{title: '本期批注', colSpan: '1', rowSpan: '2', field: 'postil', hAlign: 0, width: 80, formatter: '@', cellType: 'autoTip'},],
-            drawing_code: [{title: '图(册)号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@'}],
+            drawing_code: [{title: '图(册)号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@', textIndent: 1}],
             ex_memo1: [{title: 'ex_memo1', colSpan: '1', rowSpan: '2', field: 'ex_memo1', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}],
             ex_memo2: [{title: 'ex_memo2', colSpan: '1', rowSpan: '2', field: 'ex_memo2', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}],
             ex_memo3: [{title: 'ex_memo3', colSpan: '1', rowSpan: '2', field: 'ex_memo3', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}],
@@ -657,7 +657,7 @@ const BaseSpreadColSetting = {
                 {title: '台账小计|数量', colSpan: '2|1', rowSpan: '1|1', field: 'quantity', hAlign: 2, width: 60, type: 'Number', readOnly: true},
                 {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 60, type: 'Number', readOnly: true},
             ],
-            drawing_code: [{title: '图(册)号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@'}],
+            drawing_code: [{title: '图(册)号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@', textIndent: 1}],
             node_type: [{title: '费用类别', colSpan: '1', rowSpan: '2', field: 'node_type', hAlign: 0, width: 100, cellType: 'customizeCombo'}],
             memo: [{title: '备注', colSpan: '1', rowSpan: '2', field: 'memo', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}],
             ex_memo1: [{title: 'ex_memo1', colSpan: '1', rowSpan: '2', field: 'ex_memo1', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}, ],
@@ -673,7 +673,7 @@ const BaseSpreadColSetting = {
                 {title: '|其他错漏增减', colSpan: '|1', rowSpan: '|1', field: 'qtcl_qty', hAlign: 2, width: 100, type: 'Number'},
                 {title: '|小计', colSpan: '|1', rowSpan: '|1', field: 'quantity', hAlign: 2, width: 60, type: 'Number', readOnly: true},
             ],
-            drawing_code: [{title: '图(册)号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@'}],
+            drawing_code: [{title: '图(册)号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@', textIndent: 1}],
             node_type: [{title: '费用类别', colSpan: '1', rowSpan: '2', field: 'node_type', hAlign: 0, width: 100, cellType: 'customizeCombo'}],
             ex_memo1: [{title: 'ex_memo1', colSpan: '1', rowSpan: '2', field: 'ex_memo1', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}],
             ex_memo2: [{title: 'ex_memo2', colSpan: '1', rowSpan: '2', field: 'ex_memo2', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}],
@@ -727,7 +727,7 @@ const BaseSpreadColSetting = {
             is_tp: [{title: '总额计量', colSpan: '1', rowSpan: '2', field: 'is_tp', hAlign: 1, width: 60, cellType: 'checkbox'}],
             gxby: [{title: '工序报验', colSpan: '1', rowSpan: '2', field: 'gxby', hAlign: 1, width: 80, formatter: '@', readOnly: true}],
             dagl: [{title: '档案管理', colSpan: '1', rowSpan: '2', field: 'dagl', hAlign: 1, width: 80, formatter: '@', readOnly: true}],
-            drawing_code: [{title: '图(册)号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@'}],
+            drawing_code: [{title: '图(册)号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@', textIndent: 1}],
             memo: [{title: '备注', colSpan: '1', rowSpan: '2', field: 'memo', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}],
             postil: [{title: '本期批注', colSpan: '1', rowSpan: '2', field: 'postil', hAlign: 0, width: 100, formatter: '@', cellType: 'autoTip'},],
             ex_memo1: [{title: 'ex_memo1', colSpan: '1', rowSpan: '2', field: 'ex_memo1', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}],
@@ -751,7 +751,7 @@ const BaseSpreadColSetting = {
                 {title: '|完成', colSpan: '|1', rowSpan: '|1', field: 'end_gather_qty', hAlign: 2, width: 60, type: 'Number', readOnly: true},
             ],
             postil: [{title: '本期批注', colSpan: '1', rowSpan: '2', field: 'postil', hAlign: 0, width: 80, formatter: '@', cellType: 'autoTip'},],
-            drawing_code: [{title: '图(册)号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@'}],
+            drawing_code: [{title: '图(册)号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@', textIndent: 1}],
             ex_memo1: [{title: 'ex_memo1', colSpan: '1', rowSpan: '2', field: 'ex_memo1', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}],
             ex_memo2: [{title: 'ex_memo2', colSpan: '1', rowSpan: '2', field: 'ex_memo2', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}],
             ex_memo3: [{title: 'ex_memo3', colSpan: '1', rowSpan: '2', field: 'ex_memo3', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}],

+ 6 - 4
app/lib/rm/material.js

@@ -131,7 +131,7 @@ class ReportMemoryMaterial {
         return result;
     }
 
-    _completeMaterialGl(materialGl) {
+    _completeMaterialGl(materialGl, decimal) {
         const tTypeStr = [], mTypeStr = [];
         for (const t of materialConst.t_type) {
             tTypeStr[t.value] = t.text;
@@ -140,7 +140,7 @@ class ReportMemoryMaterial {
             mTypeStr[m.value] = m.text;
         }
         for (const gl of materialGl) {
-            gl.tp = this.ctx.helper.mul(gl.quantity, gl.m_spread, 2);
+            gl.tp = this.ctx.helper.mul(gl.quantity, gl.m_spread, decimal.tp);
             gl.t_type_str = tTypeStr[gl.t_type];
             gl.m_type_str = mTypeStr[gl.m_type];
             gl.end_tp = this.ctx.helper.add(gl.tp, gl.pre_tp);
@@ -171,9 +171,10 @@ class ReportMemoryMaterial {
         });
         if (materials.length === 0) return [];
 
-        let result, material;
+        let result, material, decimal;
         if (materials[0].order === material_order) {
             material = materials[0];
+            decimal = material.decimal ? JSON.parse(material.decimal) : { qty: 3, up: 3, tp: 2 };
             if (material.is_stage_self) {
                 const sql = 'SELECT msb.id, msb.tid, msb.mid, msb.ms_id, ms.sid, ms.`order` as s_order, mb.order, mb.t_type, mb.code, mb.name, mb.unit, mb.spec, mb.m_type,' +
                     '    msb.quantity, mb.expr,' +
@@ -195,6 +196,7 @@ class ReportMemoryMaterial {
             material = this.ctx.helper._.find(materials, {order: material_order});
             if (!material) return [];
 
+            decimal = material.decimal ? JSON.parse(material.decimal) : { tp: 2 };
             if (material.is_stage_self) {
                 const sql = 'SELECT msb.id, msb.tid, msb.mid, msb.ms_id, ms.sid, ms.`order` as s_order, mb.order, mb.t_type, mb.code, mb.name, mb.unit, mb.spec, mb.m_type,' +
                     '    msb.quantity, mbh.expr,' +
@@ -221,7 +223,7 @@ class ReportMemoryMaterial {
                 result = await this.ctx.app.mysql.query(sql, [tender_id, material.id]);
             }
         }
-        this._completeMaterialGl(result);
+        this._completeMaterialGl(result, decimal);
 
         if (this._checkFieldsExist(fields, ['month_msg_tp', 'month'])) await this._loadMaterialMonth(material, result);
         return result;

+ 4 - 3
app/public/js/change_information_set.js

@@ -2110,7 +2110,7 @@ function tableDataRemake(changeListData) {
                     let pushbwmx = '0*;*0';
                     if (listinfo.leafXmjs !== undefined) {
                         const leafInfo = listinfo.leafXmjs.find(function (item) {
-                            const flag = (item.bwmx === undefined || item.bwmx === clinfo.bwmx || item.jldy === clinfo.bwmx) && item.gcl_id === clinfo.gcl_id && (item.quantity !== null ? item.quantity === parseFloat(clinfo.oamount) : 0 === parseFloat(clinfo.oamount));
+                            const flag = (item.bwmx === undefined || item.bwmx === clinfo.bwmx || item.jldy === clinfo.bwmx) && item.gcl_id === clinfo.gcl_id && (!clinfo.mx_id || (item.mx_id && clinfo.mx_id && item.mx_id === clinfo.mx_id)) && (item.quantity !== null ? item.quantity === parseFloat(clinfo.oamount) : 0 === parseFloat(clinfo.oamount));
                             if (flag && item.code === clinfo.xmj_code) {
                                 return flag && item.code === clinfo.xmj_code;
                             }
@@ -2150,13 +2150,14 @@ function tableDataRemake(changeListData) {
                     let pushbwmx = '0*;*0';
                     if (listinfo.leafXmjs !== undefined) {
                         const leafInfo = listinfo.leafXmjs.find(function (item) {
-                            const flag = (item.bwmx === undefined || item.bwmx === clinfo.bwmx || item.jldy === clinfo.bwmx) && item.gcl_id === clinfo.gcl_id && (item.quantity !== null ? item.quantity === parseFloat(clinfo.oamount) : 0 === parseFloat(clinfo.oamount));
+                            const flag = (item.bwmx === undefined || item.bwmx === clinfo.bwmx || item.jldy === clinfo.bwmx) && item.gcl_id === clinfo.gcl_id && (!clinfo.mx_id || (item.mx_id && clinfo.mx_id && item.mx_id === clinfo.mx_id)) && (item.quantity !== null ? item.quantity === parseFloat(clinfo.oamount) : 0 === parseFloat(clinfo.oamount));
                             if (flag && item.code === clinfo.xmj_code) {
                                 return flag && item.code === clinfo.xmj_code;
                             }
                             return flag;
                         });
                         if (leafInfo) {
+                            console.log(leafInfo, clinfo);
                             info = leafInfo;
                             pushbwmx = leafInfo.code + '!_!' + (leafInfo.jldy !== undefined ? leafInfo.jldy : '') + '!_!' +
                                 (leafInfo.dwgc ? leafInfo.dwgc : '') + '!_!' +
@@ -2345,7 +2346,7 @@ function remakeChangeSpread(cOrder = changeOrder) {
             };
             const radionInfo = changeList.find(function (info) {
                 //return info.code === code && (info.lid == lid || parseInt(info.lid) === parseInt(lindex)) && gcl_id == info.gcl_id && (info.bwmx === bwmx || (info.bwmx === xmj_jldy && info.mx_id && info.mx_id === mx_id)) && parseInt(info.oamount) === parseInt(oamount);
-                return (info.lid == lid || parseInt(info.lid) === parseInt(lindex)) && gcl_id == info.gcl_id && (info.bwmx === bwmx || (info.bwmx === xmj_jldy && info.mx_id && info.mx_id === mx_id));
+                return (info.lid == lid || parseInt(info.lid) === parseInt(lindex)) && gcl_id == info.gcl_id && (!mx_id || (mx_id && info.mx_id && info.mx_id === mx_id)) && (info.bwmx === bwmx || info.bwmx === xmj_jldy);
             });
             if (radionInfo) {
                 trlist.camount = radionInfo.camount;

+ 16 - 2
app/public/js/file_detail.js

@@ -230,10 +230,12 @@ $(document).ready(function() {
                 callback(result);
             });
         }
-        uploadFiles(files, callback) {
+        uploadFiles(files, filterFiles, callback) {
             const formData = new FormData();
             formData.append('filing_id', filingObj.curFiling.id);
+            let count = 0;
             for (const file of files) {
+                if (filterFiles.indexOf(file.name) >= 0) continue;
                 if (file === undefined) {
                     toastr.error('未选择上传文件。');
                     return false;
@@ -249,6 +251,11 @@ $(document).ready(function() {
                 }
                 formData.append('size', file.size);
                 formData.append('file[]', file);
+                count++;
+            }
+            if (count === 0) {
+                toastr.warning('没有可上传的文件');
+                return false;
             }
             postDataWithFile('file/upload', formData, function (data) {
                 filingObj.updateFilingFileCount(filingObj.curFiling, data.filing.file_count);
@@ -574,6 +581,8 @@ $(document).ready(function() {
         });
     });
     $('#add-file').on('show.bs.modal', function() {
+        $('#filter-same')[0].checked = false;
+        $('#filter-same').parent().hide();
         $('#upload-file-hint').hide();
         $('#upload-file')[0].value = '';
         if ($('#add-file-ok').hasClass('btn-warning')) $('#add-file-ok').removeClass('btn-warning').addClass('btn-primary');
@@ -585,16 +594,21 @@ $(document).ready(function() {
             if (result.length === 0) {
                 $('#upload-file-hint').hide();
                 $('#add-file-ok').removeClass('btn-warning').addClass('btn-primary').attr('disabled', false);
+                $('#filter-same').parent().hide();
             } else {
                 const msg = result[0] + (result.length > 1 ? `(等${result.length}个文件)`: '') + '</br>存在同名文件,请确认是否上传重复';
                 $('#upload-file-hint').html(msg).show();
                 $('#add-file-ok').removeClass('btn-primary').addClass('btn-warning').attr('disabled', false);
+                $('#filter-same').parent().show();
+                $('#filter-same').attr('filterFiles', result.join('$;$'));
             }
         });
     });
     $('#add-file-ok').click(() => {
         const input = $('#upload-file');
-        filingObj.uploadFiles(input[0].files, function() {
+        const filter = $('#filter-same')[0].checked;
+        const filterFiles = filter ? $('#filter-same').attr('filterFiles').split('$;$') : [];
+        filingObj.uploadFiles(input[0].files, filterFiles, function() {
             $(input).val('');
             $('#add-file').modal('hide');
         });

+ 2 - 0
app/public/js/spreadjs_rela/spreadjs_zh.js

@@ -430,6 +430,7 @@ const SpreadJsObj = {
         } else if (col.field !== '' && data[col.field]) {
             cell.value(data[col.field]);
         }
+        if (col.textIndent) cell.textIndent(col.textIndent);
 
         let font = sheet.getDefaultStyle().font;
         if (col.font) {
@@ -536,6 +537,7 @@ const SpreadJsObj = {
                 font = sheet.zh_setting.tree.getFont(sheet, data, row, col, font);
             }
             cell.font(font);
+            if (col.textIndent) cell.textIndent(col.textIndent);
 
             if (col.foreColor) {
                 if (Object.prototype.toString.apply(col.foreColor) === "[object Function]") {

+ 17 - 9
app/public/js/stage.js

@@ -920,6 +920,11 @@ $(document).ready(() => {
                 if (nodePos && nodePos.length > 0) {
                     $('#bills-expr').val('').attr('readOnly', true);
                 } else {
+                    if ((!data.is_tp && col.field.indexOf('tp') >= 0) || (data.is_tp && col.field.indexOf('tp') < 0)) {
+                        $('#bills-expr').val('').attr('readOnly', true);
+                        $('#bills-expr').removeAttr('data-row');
+                        return;
+                    }
                     const exprInfo = getExprInfo(col.field);
                     const value = exprInfo && data[exprInfo.expr] ? data[exprInfo.expr] : data[col.field];
                     $('#bills-expr').val(value).attr('field', col.field).attr('org', data[col.field]);
@@ -1296,12 +1301,6 @@ $(document).ready(() => {
             if (!info.sheet.zh_setting || !info.sheet.zh_tree) return;
             const col = info.sheet.zh_setting.cols[info.col];
             const node = info.sheet.zh_tree.nodes[info.row];
-            const exprInfo = getExprInfo(col.field);
-            if (exprInfo) {
-                if (node[exprInfo.expr] && node[exprInfo.expr] !== '') {
-                    info.sheet.getCell(info.row, info.col).text(node[exprInfo.expr]);
-                }
-            }
             switch (col.field) {
                 case 'contract_qty':
                 case 'qc_qty':
@@ -1315,6 +1314,15 @@ $(document).ready(() => {
                     info.cancel = true;
                     break;
             }
+
+            if (!info.cancel) {
+                const exprInfo = getExprInfo(col.field);
+                if (exprInfo) {
+                    if (node[exprInfo.expr] && node[exprInfo.expr] !== '') {
+                        info.sheet.getCell(info.row, info.col).text(node[exprInfo.expr]);
+                    }
+                }
+            }
         },
         buttonClicked: function (e, info) {
             if (info.sheet.zh_setting) {
@@ -1673,7 +1681,7 @@ $(document).ready(() => {
                     return !node || !!node.b_code;
                 }
             },
-            'remainByExprAll4': {
+            'remainByExprAll': {
                 name: '计算本期合同计量',
                 icon: 'fa-forward',
                 callback: function(key, opt) {
@@ -1711,7 +1719,7 @@ $(document).ready(() => {
                     });
                 },
                 visible: function(key, opt) {
-                    return !readOnly;
+                    return !readOnly && contractExpr;
                 },
             },
             zjjlSpr: '----',
@@ -4320,7 +4328,7 @@ $(document).ready(() => {
 
                 posData = stagePos.getLedgerPos(node.id) || [];
                 const changePos = posData.find(x => { return x.name === changeBills.bwmx; });
-                if (changePos.settle_status) return null;
+                if (changePos && changePos.settle_status) return null;
 
                 let defaultPos;
                 if (posData.length > 0) {

+ 1 - 1
app/service/file.js

@@ -45,7 +45,7 @@ module.exports = app => {
         }
 
         async checkFiles(filing_id, files) {
-            const existFiles = await this.getAllDataByCondition({ columns: ['filename', 'fileext'], where: { filing_id } });
+            const existFiles = await this.getAllDataByCondition({ columns: ['filename', 'fileext'], where: { filing_id, is_deleted: 0 } });
             const existFilesName = existFiles.map(x => { return x.filename + x.fileext });
             return files.filter(x => { return existFilesName.indexOf(x) >= 0; });
         }

+ 49 - 42
app/service/stage_change.js

@@ -55,7 +55,7 @@ class autoUseChange {
 
             const posData = this.pos.getLedgerPos(node.id) || [];
             const changePos = posData.find(x => { return x.name === changeBills.bwmx; });
-            if (changePos.settle_status) return null;
+            if (changePos && changePos.settle_status) return null;
 
             let defaultPos;
             if (posData.length > 0) {
@@ -100,10 +100,36 @@ class autoUseChange {
         }
     }
 
+    _calculateQty(detail, minus, bills) {
+        if (bills.is_valuation) {
+            detail.qty = this.helper.add(detail.qty, bills.valid_qty);
+            if (minus) {
+                detail.negative_qc_qty = this.helper.add(detail.negative_qc_qty, bills.valid_qty);
+            } else {
+                detail.positive_qc_qty = this.helper.add(detail.positive_qc_qty, bills.valid_qty);
+            }
+        } else {
+            detail.qc_minus_qty = this.helper.add(detail.qc_minus_qty, bills.valid_qty);
+        }
+    }
+    _calculateUsedQty(detail, bills) {
+        if (!bills.no_value) {
+            detail.qty = this.helper.add(detail.qty, bills.qty);
+            if (detail.minus) {
+                detail.negative_qc_qty = this.helper.add(detail.negative_qc_qty, bills.qty);
+            } else {
+                detail.positive_qc_qty = this.helper.add(detail.positive_qc_qty, bills.qty);
+            }
+        } else {
+            detail.qc_minus_qty = this.helper.add(detail.qc_minus_qty, bills.valid_qty);
+        }
+    }
     useBills(bills) {
         if (bills.billsPos) bills.billsPos.bills = this.ledgerTree.datas.find(x => {return x.id === bills.billsPos.lid; });
         const billsPos = bills.billsPos || this.findBillsPos(bills);
         if (!billsPos) return;
+        if (!this.minusNoValue && !bills.is_valuation) return;
+
         const bamount = parseFloat(bills.samount);
         const minus = bamount < 0;
         this.changeDetail.push({
@@ -112,31 +138,20 @@ class autoUseChange {
             qty: bills.valid_qty, stimes: 1, sorder: 0, unit_price: bills.unit_price, minus, no_value: !bills.is_valuation,
         });
 
-        if (!bills.is_valuation) return;
         if (billsPos.pid !== '-1') {
             let cp = this.changePos[billsPos.pid];
             if (!cp) {
-                cp = { lid: billsPos.lid, pid: billsPos.pid, qty: 0, bills: billsPos.bills };
-                this.changePos[billsPos.pid] = cp
-            }
-            cp.qty = this.helper.add(cp.qty, bills.valid_qty);
-            if (minus) {
-                cp.negative_qc_qty = cp.qty;
-            } else {
-                cp.positive_qc_qty = cp.qty;
+                cp = { lid: billsPos.lid, pid: billsPos.pid, qty: 0, negative_qc_qty: 0, positive_qc_qty: 0, qc_minus_qty: 0, bills: billsPos.bills };
+                this.changePos[billsPos.pid] = cp;
             }
+            this._calculateQty(cp, minus, bills);
         } else {
             let cb = this.changeBills[billsPos.lid];
             if (!cb) {
                 cb = { lid: billsPos.lid, qty: 0, bills: billsPos.bills };
                 this.changeBills[billsPos.lid] = cb;
             }
-            cb.qty = this.helper.add(cb.qty, bills.valid_qty);
-            if (minus) {
-                cb.negative_qc_qty = this.helper.add(cb.negative_qc_qty, bills.valid_qty);
-            } else {
-                cb.positive_qc_qty = this.helper.add(cb.positive_qc_qty, bills.valid_qty);
-            }
+            this._calculateQty(cb, minus, bills);
         }
     }
 
@@ -154,16 +169,8 @@ class autoUseChange {
             }
         }
         for (const sc of this.stageChange) {
-            if (sc.no_value) continue;
             const cp = this.changePos[sc.pid];
-            if (cp) {
-                cp.qty = this.helper.add(cp.qty, sc.qty);
-                if (sc.minus) {
-                    cp.negative_qc_qty = this.helper.add(cp.negative_qc_qty, sc.qty);
-                } else {
-                    cp.positive_qc_qty = this.helper.add(cp.positive_qc_qty, sc.qty);
-                }
-            }
+            if (cp) this._calculateUsedQty(cp, sc);
         }
         for (const pid in this.changePos) {
             const cp = this.changePos[pid];
@@ -173,37 +180,31 @@ class autoUseChange {
             const qc_qty = this.helper.round(cp.qty, precision.value);
             const positive_qc_qty = this.helper.round(cp.positive_qc_qty || 0, precision.value);
             const negative_qc_qty = this.helper.round(cp.negative_qc_qty || 0, precision.value);
+            const qc_minus_qty = this.helper.round(cp.qc_minus_qty || 0, precision.value);
             const sp = this.stagePos.find(x => {return x.pid === pid});
             if (sp) {
-                this.updatePos.push({ id: sp.id, qc_qty, positive_qc_qty, negative_qc_qty });
+                this.updatePos.push({ id: sp.id, qc_qty, positive_qc_qty, negative_qc_qty, qc_minus_qty });
             } else {
                 this.insertPos.push({
                     tid: this.default.tid, sid: this.default.sid, said: this.default.said,
-                    lid: cp.lid, pid, qc_qty, positive_qc_qty, negative_qc_qty, times: 1, order: 0
+                    lid: cp.lid, pid, qc_qty, positive_qc_qty, negative_qc_qty, qc_minus_qty, times: 1, order: 0
                 });
             }
             const cb = this.changeBills[cp.lid];
             if (!cb) {
-                this.changeBills[cp.lid] = { lid: cp.lid, qty: qc_qty, positive_qc_qty, negative_qc_qty, bills: cp.bills };
+                this.changeBills[cp.lid] = { lid: cp.lid, qty: qc_qty, positive_qc_qty, negative_qc_qty, qc_minus_qty, bills: cp.bills };
             } else {
                 cb.qty = this.helper.add(cb.qty, qc_qty);
                 cb.positive_qc_qty = this.helper.add(cb.positive_qc_qty, positive_qc_qty);
                 cb.negative_qc_qty = this.helper.add(cb.negative_qc_qty, negative_qc_qty);
+                cb.qc_minus_qty = this.helper.add(cb.qc_minus_qty, qc_minus_qty);
             }
         }
         for (const sc of this.stageChange) {
-            if (sc.no_value) continue;
             const cp = this.changePos[sc.pid];
             if (cp) continue;
             const cb = this.changeBills[sc.lid];
-            if (cb) {
-                cb.qty = this.helper.add(cb.qty, sc.qty);
-                if (sc.minus) {
-                    cb.negative_qc_qty = this.helper.add(cb.negative_qc_qty, sc.qty);
-                } else {
-                    cb.positive_qc_qty = this.helper.add(cb.positive_qc_qty, sc.qty);
-                }
-            }
+            if (cb) this._calculateUsedQty(cb, sc);
         }
         for (const lid in this.changeBills) {
             const cb = this.changeBills[lid];
@@ -215,20 +216,22 @@ class autoUseChange {
             const positive_qc_tp = this.helper.mul(positive_qc_qty, cb.bills.unit_price, this.decimal.tp);
             const negative_qc_qty = this.helper.round(cb.negative_qc_qty || 0, precision.value);
             const negative_qc_tp = this.helper.mul(negative_qc_qty, cb.bills.unit_price, this.decimal.tp);
+            const qc_minus_qty = this.helper.round(cb.qc_minus_qty || 0, precision.value);
             const sb = this.stageBills.find(x => {return x.lid === lid});
             if (sb) {
-                this.updateBills.push({ id: sb.id, qc_qty, qc_tp, positive_qc_qty, positive_qc_tp, negative_qc_qty, negative_qc_tp });
+                this.updateBills.push({ id: sb.id, qc_qty, qc_tp, positive_qc_qty, positive_qc_tp, negative_qc_qty, negative_qc_tp, qc_minus_qty });
             } else {
                 this.insertBills.push({
                     tid: this.default.tid, sid: this.default.sid, said: this.default.said,
-                    lid, qc_qty, qc_tp, positive_qc_qty, positive_qc_tp, negative_qc_qty, negative_qc_tp, times: 1, order: 0
+                    lid, qc_qty, qc_tp, positive_qc_qty, positive_qc_tp, negative_qc_qty, negative_qc_tp, qc_minus_qty, times: 1, order: 0
                 });
             }
         }
     }
 
-    use(source, validChangeBills) {
+    use(source, validChangeBills, minusNoValue) {
         this.init(source);
+        this.minusNoValue = minusNoValue;
 
         for (const bills of validChangeBills) {
             this.useBills(bills);
@@ -806,7 +809,9 @@ module.exports = app => {
             const stageChange = await this.ctx.service.stageChange.getAllDataByCondition({ where: { sid: stage.id, lid }});
 
             const useModal = new autoUseChange(this.ctx.helper, tender.info);
-            useModal.use({ledgerData, posData, stageBills, stagePos, stageChange, default: { tid: stage.tid, sid: stage.id, said: this.ctx.session.sessionUser.accountId } }, validChangeBills);
+            const projectFunInfo = await this.ctx.service.project.getFunRela(this.ctx.session.sessionProject.id);
+            const minusNoValue = projectFunInfo.minusNoValue && tender.info.fun_rela.stage_change.minusNoValue;
+            useModal.use({ledgerData, posData, stageBills, stagePos, stageChange, default: { tid: stage.tid, sid: stage.id, said: this.ctx.session.sessionUser.accountId } }, validChangeBills, minusNoValue);
 
             const conn = await this.db.beginTransaction();
             try {
@@ -853,7 +858,9 @@ module.exports = app => {
             const stageBills = await this.ctx.service.stageBills.getAllDataByCondition({ where: { sid: stage.id } });
             const stagePos = await this.ctx.service.stagePos.getAllDataByCondition({ where: { sid: stage.id } });
             const useModal = new autoUseChange(this.ctx.helper, tender.info, this.ctx.service.settle.settleStatus);
-            useModal.use({ledgerData, posData, stageBills, stagePos, default: { tid: stage.tid, sid: stage.id, said: this.ctx.session.sessionUser.accountId } }, validChangeBills);
+            const projectFunInfo = await this.ctx.service.project.getFunRela(this.ctx.session.sessionProject.id);
+            const minusNoValue = projectFunInfo.minusNoValue && tender.info.fun_rela.stage_change.minusNoValue;
+            useModal.use({ledgerData, posData, stageBills, stagePos, default: { tid: stage.tid, sid: stage.id, said: this.ctx.session.sessionUser.accountId } }, validChangeBills, minusNoValue);
 
             // if (useModal.insertChange.length === 0) return '无可调用的清单或计量单元';
 

+ 2 - 2
app/service/stage_change_final.js

@@ -105,7 +105,7 @@ module.exports = app => {
             return changeBills.filter(cb => {
                 cb.qty = parseFloat(cb.samount);
                 const qtyDecimal = self.ctx.helper.findDecimal(changeBills.unit);
-                cb.limitQty = self.ctx.helper.mul(qty, self.ctx.helper.div(changeBills.delimit, 100, 2), qtyDecimal);
+                cb.limitQty = self.ctx.helper.mul(cb.qty, self.ctx.helper.div(changeBills.delimit, 100, 2), qtyDecimal);
                 cb.valid_qty = self.ctx.helper.sub(cb.limitQty, cb.used_qty);
                 return cb.valid_qty;
             });
@@ -125,7 +125,7 @@ module.exports = app => {
             return changeBills.filter(cb => {
                 cb.qty = parseFloat(cb.samount);
                 const qtyDecimal = self.ctx.helper.findDecimal(changeBills.unit);
-                cb.limitQty = self.ctx.helper.mul(qty, self.ctx.helper.div(changeBills.delimit, 100, 2), qtyDecimal);
+                cb.limitQty = self.ctx.helper.mul(cb.qty, self.ctx.helper.div(changeBills.delimit, 100, 2), qtyDecimal);
                 cb.valid_qty = self.ctx.helper.sub(cb.limitQty, cb.used_qty);
                 return cb.valid_qty;
             });

+ 4 - 0
app/view/file/file_modal.ejs

@@ -78,6 +78,10 @@
                 </div>
             </div>
             <div class="modal-footer">
+                <div class="custom-control custom-checkbox">
+                    <input type="checkbox" class="custom-control-input" id="filter-same">
+                    <label class="custom-control-label text-primary" for="filter-same">过滤同名附件</label>
+                </div>
                 <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
                 <button type="button" class="btn btn-primary btn-sm" id="add-file-ok">确认</button>
             </div>

+ 1 - 1
app/view/ledger/explode.ejs

@@ -330,7 +330,7 @@
 <script src="/public/js/moment/moment.min.js"></script>
 <script type="text/javascript">
     const readOnly = <%- ctx.tender.ledgerReadOnly %>;
-    const contractExpr = <%- ctx.session.sessionProject.page_show.openContractExpr && tender.ledger_status === auditConst.status.checked %>;
+    const contractExpr = <%- !!ctx.session.sessionProject.page_show.openContractExpr && tender.ledger_status === auditConst.status.checked %>;
     const tender = JSON.parse('<%- JSON.stringify(tender) %>');
     const tenderInfo = JSON.parse(unescape('<%- escape(JSON.stringify(tenderInfo)) %>'));
     const thousandth = <%- ctx.tender.info.display.thousandth %>;

+ 2 - 2
app/view/material/info.ejs

@@ -176,7 +176,7 @@
                             </div>
                             <div class="tab-content">
                                 <div class="tab-pane active" id="fysum">
-                                    <div class="sp-wrap">
+                                    <div class="sp-wrap" style="overflow: auto;">
                                         <% if (!material.material_tax && !old_had_tax) { %>
                                             <table class="table table-sm table-bordered">
                                                 <tr><th rowspan="2"></th><th colspan="2" class="text-center">信息价</th><th colspan="2" class="text-center">价格指数</th></tr>
@@ -228,7 +228,7 @@
                                 </div>
                                 <% if (material.is_stage_self) { %>
                                     <div class="tab-pane" id="qidetail">
-                                        <div class="sp-wrap">
+                                        <div class="sp-wrap" style="overflow: auto;">
                                             <table class="table table-bordered">
                                                 <thead>
                                                 <tr class="text-center"><th colspan="<% if (material.material_tax) { %>3<% } else { %>2<% } %>">期明细</th></tr>

+ 1 - 0
app/view/stage/index.ejs

@@ -556,6 +556,7 @@
     const hintMinusCb = <%- hintMinusCb %>;
     let currPageFileData = [];
     const settleStatus = JSON.parse('<%- JSON.stringify(settleStatus) %>');
+    const contractExpr = <%- !!ctx.session.sessionProject.page_show.openContractExpr %>;
 </script>
 <style>