Przeglądaj źródła

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

Tony Kang 3 tygodni temu
rodzic
commit
28cfd394fb

+ 2 - 2
app/controller/financial_controller.js

@@ -125,7 +125,7 @@ module.exports = app => {
                 if (!financialPermission.transfer_show) {
                     throw '没有查看权限';
                 }
-                const transferList = await ctx.service.financialTransfer.getList(ctx.subProject.id);
+                const transferList = await ctx.service.financialTransfer.getList(ctx.subProject.id, true);
                 const total = await ctx.service.financialTransfer.count({ spid: ctx.subProject.id });
                 // 分页相关
                 const page = ctx.page;
@@ -1329,7 +1329,7 @@ module.exports = app => {
                     from,
                     fileList,
                     authMobile: auth_mobile,
-                    returnUrl: `/sp/${ctx.subProject.id}/financial/pay/${from !== undefined ? from : 'stage/' + ctx.financialPay.fpsid}`,
+                    returnUrl: `/sp/${ctx.subProject.id}/financial/pay/${from !== null ? from : 'stage/' + ctx.financialPay.fpsid}`,
                     preUrl: `/sp/${ctx.subProject.id}/financial/pay`,
                     preUrl2: `/sp/${ctx.subProject.id}/financial/pay/` + ctx.financialPay.id,
                     jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.financial.payDetail),

+ 4 - 2
app/controller/measure_controller.js

@@ -302,7 +302,10 @@ module.exports = app => {
                     throw '请输入正确的文本信息';
                 }
                 const relaStage = await ctx.service.stageRela.getDataByCondition({ rela_sid: stage_id });
-                if (relaStage) throw `该期已关联到标段"${relaStage.rela_tname}",不可删除`;
+                if (relaStage) {
+                    const relaTender = await ctx.service.tender.getDataByCondition({ id: relaStage.tid });
+                    throw `该期已关联到标段"${relaTender.name}",不可删除`;
+                }
                 if (stageInfo && (ctx.session.sessionUser.accountId === stageInfo.user_id || (ctx.session.sessionUser.is_admin && ctx.request.body.confirm === '确认删除本期')) && stage_highOrder === stageInfo.order) {
                     const result = await ctx.service.stage.deleteStage(stage_id);
                     if (!result) {
@@ -318,7 +321,6 @@ module.exports = app => {
                 }
             } catch (err) {
                 this.log(err);
-                console.log(err);
                 ctx.session.postError = err.toString();
                 ctx.redirect(ctx.request.header.referer);
             }

+ 1 - 0
app/controller/sub_proj_setting_controller.js

@@ -254,6 +254,7 @@ module.exports = app => {
                     accountGroup,
                     subProjectAccountList,
                     subProjectUnitList,
+                    subProjectAllAccountList,
                     keyword: filter.keyword,
                     company: filter.company,
                     jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.setting.sp_permission),

+ 5 - 4
app/lib/pay_calc.js

@@ -159,13 +159,14 @@ class PayCalculate {
 
         this.pre = this.stage.preCheckedStage ? await this.ctx.service.stageBillsFinal.getSumTotalPrice(this.stage.tid, this.stage.preCheckedStage.order) : {};
         this.cur = await this.ctx.service.stageBills.getSumTotalPrice(this.stage);
+        const pcSum = await this.ctx.service.stageBillsPc.getSumTotalPrice(this.stage);
         this.add = {};
         if (this.pre) {
-            this.add.contract_tp = this.ctx.helper.add(this.pre.contract_tp, this.cur.contract_tp);
-            this.add.qc_tp = this.ctx.helper.add(this.pre.qc_tp, this.cur.qc_tp);
+            this.add.contract_tp = this.ctx.helper.sum([this.pre.contract_tp, this.cur.contract_tp, pcSum.contract_pc_tp]);
+            this.add.qc_tp = this.ctx.helper.sum([this.pre.qc_tp, this.cur.qc_tp, pcSum.qc_pc_tp]);
         } else {
-            this.add.contract_tp = this.cur.contract_tp;
-            this.add.qc_tp = this.cur.qc_tp;
+            this.add.contract_tp = this.ctx.helper.add(this.cur.contract_tp, pcSum.contract_pc_tp);
+            this.add.qc_tp = this.ctx.helper.add(this.cur.qc_tp, pcSum.qc_pc_tp);
         }
         this.add.gather_tp = this.ctx.helper.add(this.add.contract_tp, this.add.qc_tp);
     }

+ 77 - 0
app/lib/rm/contract.js

@@ -0,0 +1,77 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Mai
+ * @date
+ * @version
+ */
+
+const RptMemBase = require('./base');
+const bindData = {};
+const Ledger = require('../ledger');
+
+class rptMemContract extends RptMemBase {
+    constructor(ctx) {
+        super(ctx, bindData);
+    }
+
+    async _getContractTree(condition) {
+        const data = await this.ctx.service.contractTree.getAllDataByCondition({ where: condition });
+        const contract_data = await this.ctx.service.contract.getAllDataByCondition({ where: condition });
+        const tree = new Ledger.billsTree(this.ctx, {
+            id: 'contract_id',
+            pid: 'contract_pid',
+            order: 'order',
+            level: 'level',
+            rootId: -1,
+            calcFields: [ 'total_price', 'pay_price', 'debit_price', 'yf_price', 'sf_price'],
+            calc: function (node, helper, decimal) {},
+        });
+        tree.loadDatas([...data, ...contract_data]);
+        return tree.getDefaultDatas();
+    }
+    async _getContract(condition) {
+        const data = await this.ctx.service.contract.getAllDataByCondition({ where: condition });
+        return data;
+    }
+    async _getContractPay(condition) {
+        const data = await this.ctx.service.contractPay.getAllDataByCondition({ where: condition, orders: [['cid', 'asc'], ['create_time', 'asc']] });
+        return data;
+    }
+
+    async getSpContractTree(contract_type) {
+        if (!this.ctx.subProject) return [];
+        return await this._getContractTree({ spid: this.ctx.subProject.id, contract_type });
+    }
+    async getSpContract(contract_type) {
+        if (!this.ctx.subProject) return [];
+        return await this._getContract({ spid: this.ctx.subProject.id, contract_type });
+    }
+    async getSpContractPay(contract_type) {
+        if (!this.ctx.subProject) return [];
+        return await this._getContractPay({ spid: this.ctx.subProject.id, contract_type });
+    }
+
+    getCommonData(params, tableName, fields, customDefine, customSelect) {
+        switch (tableName) {
+            case 'sp_contract_tree_1':
+                return this.getSpContractTree(1);
+            case 'sp_contract_1':
+                return this.getSpContract(1);
+            case 'sp_contract_pay_1':
+                return this.getSpContractPay(1);
+            case 'sp_contract_tree_2':
+                return this.getSpContractTree(2);
+            case 'sp_contract_2':
+                return this.getSpContract(2);
+            case 'sp_contract_pay_2':
+                return this.getSpContractPay(2);
+            default:
+                return [];
+        }
+    }
+}
+
+module.exports = rptMemContract;

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

@@ -59,6 +59,12 @@ class reportMemoryFinancial {
         return await this.ctx.service.financialPayTender.getAllDataByCondition({ where: { spid: this.tender.spid } });
     }
 
+    async projectPayStage(tid) {
+        await this.checkTender(tid);
+        if (!this.tender || !this.tender.spid) return [];
+        return await this.ctx.service.financialPayStage.getAllDataByCondition({ where: { spid: this.tender.spid } });
+    }
+
     async projectTransfer(tid) {
         await this.checkTender(tid);
         if (!this.tender || !this.tender.spid) return [];

+ 1 - 1
app/middleware/uncheck_tender_check.js

@@ -57,7 +57,7 @@ module.exports = options => {
                 if (this.helper.isWap(this.request)) {
                     this.redirect('/wap/subproj');
                 } else {
-                    err === '您无权查看该内容' ? this.redirect(this.request.headers.referer) : this.redirect(`/sp/${ctx.subProject.id}/list`);
+                    err === '您无权查看该内容' ? this.redirect(this.request.headers.referer) : this.redirect(`/sp/${this.subProject.id}/list`);
                 }
             }
         }

+ 7 - 7
app/public/js/budget_compare.js

@@ -131,6 +131,13 @@ $(document).ready(() => {
             $('#compare-set').modal('hide');
             Cookies.set(comparePhaseKey, phase1 + ',' + phase2);
         },
+        reCalcColVisible() {
+            const type = this.compareType;
+            spreadSetting.cols.forEach(x => {
+                if (!x.bc_type) return;
+                x.visible = x.bc_type === type && x.defaultVisible;
+            });
+        },
         curFinalId() {
             return this.finalInfo ? this.finalInfo.id : undefined;
         },
@@ -325,13 +332,6 @@ $(document).ready(() => {
             const colIndex = spreadSetting.cols.findIndex(x => { return x.field === 'stackedBar'});
             SpreadJsObj.reloadColData(compareSheet, colIndex);
         },
-        reCalcColVisible() {
-            const type = this.compareType;
-            spreadSetting.cols.forEach(x => {
-                if (!x.bc_type) return;
-                x.visible = x.bc_type === type && x.defaultVisible;
-            });
-        },
         setCompareType(type) {
             this.compareType = type || 'number';
             $('[name=showType]').removeClass('active');

+ 31 - 18
app/public/js/contract_detail.js

@@ -315,7 +315,7 @@ $(document).ready(function() {
                         $('#htpay-table tbody').find('.pay-del').hide();
                     }
                 } else {
-                    $('#add_contract_pay_btn').show();
+                    if (node.uid === user_id || permission_add_pay) $('#add_contract_pay_btn').show();
                     if (need && contractPays && contractPays.length > 0) {
                         for (const [i, cp] of contractPays.entries()) {
                             if (cp.uid === user_id) {
@@ -372,8 +372,9 @@ $(document).ready(function() {
             })
             console.log(pays);
             newPays.forEach((pay, idx) => {
+                const operationHtml = !pay.fpcid ? `<a href="javascript:void(0);" class="text-primary pay-edit" data-id="${pay.id}" ${!pay.showEdit ? `style="display:none"` : ''}>编辑</a> <a href="javascript:void(0);" class="text-danger pay-del" data-id="${pay.id}" ${!pay.showEdit ? `style="display:none"` : ''}>删除</a>` : '';
                 paysHtml += `<tr class="text-center" data-cpid="${pay.id}">
-                                        <td>${idx + 1}</td>
+                                        <td>${idx + 1}${ pay.fpcid ? '<a href="javascript:void(0);" class="float-right"><i class="fa fa-cny"></i></a>' : ''}</td>
                                         <td>${moment(pay.pay_time).format('YYYY-MM-DD')}</td>
                                         <td>${pay.pay_price}</td>
                                         <td>${pay.debit_price}</td>
@@ -384,7 +385,7 @@ $(document).ready(function() {
                                         <td>${moment(pay.create_time).format('YYYY-MM-DD HH:mm:ss')}</td>
                                         <td>${pay.remark}</td>
                                         <td><a href="javascript:void(0);" class="text-primary open-pay-files" data-cpid="${pay.id}"><i class="fa fa-paperclip fa-rotate-90"></i></a> <span class="files-num">${pay.files.length > 0 ? pay.files.length : ''}</span></td>
-                                        <td><a href="javascript:void(0);" class="text-primary pay-edit" data-id="${pay.id}" ${ !pay.showEdit ? `style="display:none"` : ''}>编辑</a> <a href="javascript:void(0);" class="text-danger pay-del" data-id="${pay.id}" ${ !pay.showEdit ? `style="display:none"` : ''}>删除</a></td>
+                                        <td>${operationHtml}</td>
                                     </tr>`;
             });
             $('#htpay-table tbody').html(paysHtml);
@@ -410,7 +411,7 @@ $(document).ready(function() {
                     contractTreeSpreadObj.setContractPays(result.pays, node);
                     contractTreeSpreadObj.setContractFiles(result.files, node.id);
                 });
-                if (node.uid === user_id) {
+                if ((node.uid === user_id || permission_edit_contract)) {
                     if (node.settle_code) {
                         $('a[href*="#cons-unlock"]').show();
                         $('a[href*="#cons-close"]').hide();
@@ -427,7 +428,11 @@ $(document).ready(function() {
                     $('a[href*="#cons-close"]').hide();
                     $('a[href*="#cons-upfile"]').hide();
                     if (node && node.c_code && $('.bc-bar .nav li .active').attr('href') === '#htfile' && permission_att) $('a[href*="#cons-upfile"]').show();
-                    $('#add_contract_pay_btn').hide();
+                    if (node && node.c_code && $('.bc-bar .nav li .active').attr('href') === '#htpay' && (node.uid === user_id || permission_add_pay)) {
+                        $('#add_contract_pay_btn').show();
+                    } else {
+                        $('#add_contract_pay_btn').hide();
+                    }
                 }
             } else {
                 $('#htdetail-table').hide();
@@ -1157,15 +1162,17 @@ $(document).ready(function() {
     $('.bc-bar ul li a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
         const node = SpreadJsObj.getSelectObject(contractSheet);
         $('a[href*="#cons-upfile"]').hide();
+        $('#add_contract_pay_btn').hide();
         if (node && node.c_code) {
             if ($('.bc-bar .nav li .active').attr('href') === '#htfile' && permission_att) $('a[href*="#cons-upfile"]').show();
-            if (node.uid === user_id) contractTreeSpreadObj.changeContractTab(node, true);
+            if ($('.bc-bar .nav li .active').attr('href') === '#htpay' && !node.settle_code && permission_add_pay) $('#add_contract_pay_btn').show();
+            if ((node.uid === user_id || permission_edit_contract)) contractTreeSpreadObj.changeContractTab(node, true);
         }
     });
 
     $('#edit_contract_btn').on('click', function () {
         const node = SpreadJsObj.getSelectObject(contractSheet);
-        if (node && node.c_code && node.uid === user_id) {
+        if (node && node.c_code && (node.uid === user_id || permission_edit_contract)) {
             $('#edit_contract_btn').hide();
             $('#save_contract_btn').show();
             $('#cancel_contract_btn').show();
@@ -1186,7 +1193,7 @@ $(document).ready(function() {
 
     $('#save_contract_btn').on('click', function () {
         const node = SpreadJsObj.getSelectObject(contractSheet);
-        if (node && node.c_code && node.uid === user_id) {
+        if (node && node.c_code && (node.uid === user_id || permission_edit_contract)) {
             const data = {
                 id: node.id,
             };
@@ -1237,7 +1244,7 @@ $(document).ready(function() {
 
     $('#cancel_contract_btn').on('click', function () {
         const node = SpreadJsObj.getSelectObject(contractSheet);
-        if (node && node.c_code && node.uid === user_id) {
+        if (node && node.c_code && (node.uid === user_id || permission_edit_contract)) {
             $('#edit_contract_btn').show();
             $('#save_contract_btn').hide();
             $('#cancel_contract_btn').hide();
@@ -1531,6 +1538,12 @@ $(document).ready(function() {
                 if (ca && ca.permission_add) {
                     txt.push('添加合同');
                 }
+                if (ca && ca.permission_edit_contract) {
+                    txt.push('编辑合同');
+                }
+                if (ca && ca.permission_add_pay) {
+                    txt.push('添加支付');
+                }
                 if (ca && ca.permission_show_unit) {
                     txt.push('查看本单位合同');
                 }
@@ -1754,8 +1767,8 @@ $(document).ready(function() {
             toastr.error('请选择一个合同节点');
             return;
         }
-        if (node.uid !== user_id) {
-            toastr.error('只能修改自己的合同' + contractConst.typeName[contract_type]);
+        if (!(node.uid === user_id || permission_add_pay)) {
+            toastr.error('没有权限添加合同' + contractConst.typeName[contract_type]);
             return;
         }
         if (node.settle_code) {
@@ -1810,8 +1823,8 @@ $(document).ready(function() {
             toastr.error('请选择一个合同节点');
             return;
         }
-        if (node.uid !== user_id) {
-            toastr.error('只能添加自己的合同' + contractConst.typeName[contract_type]);
+        if (!(node.uid === user_id || permission_add_pay)) {
+            toastr.error('没有权限添加合同' + contractConst.typeName[contract_type]);
             return;
         }
         if (node.settle_code) {
@@ -1968,10 +1981,10 @@ $(document).ready(function() {
             toastr.error('请选择一个合同节点');
             return;
         }
-        if (node.uid !== user_id && !permission_att) {
-            $('#cons-pay-file .upload-permission').hide();
-        } else {
+        if (node.uid === user_id || pay.uid === user_id || permission_att) {
             $('#cons-pay-file .upload-permission').show();
+        } else {
+            $('#cons-pay-file .upload-permission').hide();
         }
         $('#cons-pay-file').modal('show');
         $('#cons-pay-file input[name="cpid"]').val(cpid);
@@ -2119,8 +2132,8 @@ $(document).ready(function() {
         },
         spreadSetting: {
             cols: [
-                {title: '项目节编号', field: 'code', hAlign: 0, width: 120, formatter: '@', readOnly: true, cellType: 'tree'},
-                {title: '名称', field: 'name', hAlign: 0, width: 150, formatter: '@', readOnly: true},
+                {title: '项目节编号', field: 'code', hAlign: 0, width: 180, formatter: '@', readOnly: true, cellType: 'tree'},
+                {title: '名称', field: 'name', hAlign: 0, width: 200, formatter: '@', readOnly: true},
             ],
             treeCol: 0,
             emptyRows: 0,

+ 8 - 0
app/public/js/setting_manage.js

@@ -675,6 +675,8 @@ $(document).ready(() => {
                 userData.permission = {
                     add: $('#contract-users tr').eq(i).find('input[data-type="permission_add"]').eq(0).is(':checked') ? 1 : 0,
                     edit: $('#contract-users tr').eq(i).find('input[data-type="permission_edit"]').eq(0).is(':checked') ? 1 : 0,
+                    edit_contract: $('#contract-users tr').eq(i).find('input[data-type="permission_edit_contract"]').eq(0).is(':checked') ? 1 : 0,
+                    add_pay: $('#contract-users tr').eq(i).find('input[data-type="permission_add_pay"]').eq(0).is(':checked') ? 1 : 0,
                     showUnit: $('#contract-users tr').eq(i).find('input[data-type="permission_show_unit"]').eq(0).is(':checked') ? 1 : 0,
                     showNode: $('#contract-users tr').eq(i).find('input[data-type="permission_show_node"]').eq(0).is(':checked') ? 1 : 0,
                 }
@@ -976,6 +978,12 @@ function setContractHtml(datas) {
                                 <input type="checkbox" class="permission-checkbox" data-type="permission_add" value="${ca.uid}" ${ca.permission_add ? 'checked' : ''}>
                             </td>
                             <td class="text-center">
+                                <input type="checkbox" class="permission-checkbox" data-type="permission_edit_contract" value="${ca.uid}" ${ca.permission_edit_contract ? 'checked' : ''}>
+                            </td>
+                            <td class="text-center">
+                                <input type="checkbox" class="permission-checkbox" data-type="permission_add_pay" value="${ca.uid}" ${ca.permission_add_pay ? 'checked' : ''}>
+                            </td>
+                            <td class="text-center">
                                 <input type="checkbox" class="permission-checkbox" data-type="permission_show_unit" value="${ca.uid}" ${ca.permission_show_unit ? 'checked' : ''}>
                             </td>
                             <td class="text-center">

+ 45 - 1
app/public/js/sp_setting_permission.js

@@ -102,7 +102,7 @@ $(document).ready(() => {
         if (ptype === 'contract') {
             const pvalue = $(this).attr('pvalue');
             if (this.checked) {
-                if ((pvalue === '1' || pvalue === '2') && !$(this).parents('.permission-parent').find('[ptype=contract][pvalue="3"]').prop('checked') && !$(this).parents('.permission-parent').find('[ptype=contract][pvalue="4"]').prop('checked')) {
+                if ((pvalue === '1' || pvalue === '2' || pvalue === '7' || pvalue === '8') && !$(this).parents('.permission-parent').find('[ptype=contract][pvalue="3"]').prop('checked') && !$(this).parents('.permission-parent').find('[ptype=contract][pvalue="4"]').prop('checked')) {
                     $(this).parents('.permission-parent').find('[ptype=contract][pvalue="5"]').prop('checked', true);
                 }
                 if (pvalue === '3' || pvalue === '4') {
@@ -205,4 +205,48 @@ $(document).ready(() => {
             window.location.reload();
         })
     });
+    $('[name=copy-permission]').click(function() {
+        let data = $('[name=set-permission]', $(this).parent()).attr('data-account');
+        $('#source-permission').val(data);
+        data = JSON.parse(data);
+        const html = [];
+        for (const u of subProjectAllAccountList) {
+            if (u.id === data.id) continue;
+            html.push('<tr>');
+            html.push(`<td class=text-center><input type="checkbox" name="copy-batch-check" id="${u.permission_id}"></td>`);
+            html.push(`<td>${u.name}</td>`);
+            html.push(`<td>${u.role}</td>`);
+            html.push(`<td>${u.company}</td>`);
+            html.push('</tr>');
+        }
+        $('#copy-batch-users').html(html.join(''));
+        $('#copy-permission').modal('show');
+    });
+    $('#copy-batch-all').click(function() {
+        for (const c of $('[name=copy-batch-check]')) {
+            c.checked = this.checked;
+        }
+    });
+    $('#copy-batch-ok').click(function() {
+        const source = JSON.parse($('#source-permission').val());
+        const updateData = [];
+        const batchUser = $('[name=copy-batch-check]:checked');
+        if (batchUser.length === 0) {
+            toastr.warning('未选择账号');
+            return;
+        }
+
+        for (const user of batchUser) {
+            const data = { id: user.getAttribute('id') };
+            const permissionCheck = $('[name="permission-check"]');
+            for (const pc of permissionCheck) {
+                const ptype = pc.getAttribute('ptype');
+                data[ptype + '_permission'] = source[ptype + '_permission'];
+            }
+            updateData.push(data);
+        }
+        postData(`/sp/${spid}/setting/user/permission/update`, { update: updateData }, function() {
+            window.location.reload();
+        })
+    })
 });

+ 1 - 0
app/router.js

@@ -204,6 +204,7 @@ module.exports = app => {
 
     // ------------------------- 项目内部相关 -----------------------------
     // **项目设置
+    // app.post('/sp/:id/setting/user/load', sessionAuth, subProjectCheck, 'subProjSettingController.load');
     // 标段自定义类别
     app.get('/sp/:id/setting/category', sessionAuth, subProjectCheck, 'subProjSettingController.category');
     app.post('/sp/:id/setting/category/add', sessionAuth, subProjectCheck, 'subProjSettingController.addCategory');

+ 46 - 0
app/service/contract_pay.js

@@ -106,6 +106,9 @@ module.exports = app => {
             if (!cpInfo) {
                 throw '合同' + contractConst.typeName[cpInfo.contract_type] + '不存在';
             }
+            if (cpInfo.fpcid) {
+                throw '该合同' + contractConst.typeName[cpInfo.contract_type] + '关联了资金支付明细,不能删除';
+            }
             const transaction = await this.db.beginTransaction();
             try {
                 await transaction.delete(this.tableName, { id: cpid });
@@ -141,6 +144,49 @@ module.exports = app => {
             node.exist_pay = paysList.length === 0 ? 0 : 1;
             await transaction.update(this.ctx.service.contract.tableName, node);
         }
+
+        async createContractPays(transaction, fpid, uid, times, pays) {
+            const addPays = [];
+            const contracts = await transaction.select(this.ctx.service.contract.tableName, { where: { id: this._.uniq(this._.map(pays, 'cid')) } });
+            for (const p of pays) {
+                const contract = contracts.find(c => c.id === p.cid);
+                if (contract) {
+                    addPays.push({
+                        spid: contract.spid || null,
+                        tid: contract.tid || null,
+                        contract_type: contract.contract_type,
+                        cid: p.cid,
+                        uid,
+                        fpid,
+                        fpcid: p.id,
+                        pay_time: times,
+                        pay_price: p.pay_price || 0,
+                        debit_price: 0,
+                        yf_price: p.pay_price || 0,
+                        sf_price: p.settle_price || 0,
+                        pay_type: p.pay_type || '',
+                        remark: '',
+                        create_time: times,
+                    });
+                }
+            }
+            if (addPays.length > 0) {
+                await transaction.insert(this.tableName, addPays);
+                for (const c of contracts) {
+                    await this.calcContract(transaction, c);
+                }
+            }
+        }
+
+        async removeContractPays(transaction, fpid, pays) {
+            await transaction.delete(this.tableName, { fpid });
+            const contracts = await transaction.select(this.ctx.service.contract.tableName, { where: { id: this._.uniq(this._.map(pays, 'cid')) } });
+            if (contracts.length > 0) {
+                for (const c of contracts) {
+                    await this.calcContract(transaction, c);
+                }
+            }
+        }
     }
     return ContractPay;
 };

+ 12 - 0
app/service/financial_pay_audit.js

@@ -393,6 +393,12 @@ module.exports = app => {
                             id: fp.id, status: checkData.checkType,
                             entities: await this.ctx.service.financialPayContract.getEntities(fp.id),
                         });
+                        // 合同支付生成对应的支付信息
+                        const pays = await this.ctx.service.financialPayContract.getAllDataByCondition({ where: { fpid: fp.id } });
+                        const contractPays = this._.filter(pays, x => { return x.cid !== null; });
+                        if (contractPays.length > 0) {
+                            await this.ctx.service.contractPay.createContractPays(transaction, fp.id, fp.uid, time, contractPays);
+                        }
                     }
                 } else {
                     // 同步 期信息
@@ -511,6 +517,12 @@ module.exports = app => {
                     entities: '',
                     final_auditor_str: '',
                 });
+                // 合同支付生成对应的支付信息
+                const pays = await this.ctx.service.financialPayContract.getAllDataByCondition({ where: { fpid: fp.id } });
+                const contractPays = this._.filter(pays, x => { return x.cid !== null; });
+                if (contractPays.length > 0) {
+                    await this.ctx.service.contractPay.removeContractPays(transaction, fp.id, contractPays);
+                }
                 await transaction.commit();
                 result = true;
             } catch (error) {

+ 1 - 1
app/service/ledger.js

@@ -616,7 +616,7 @@ module.exports = app => {
                     unit: data[i].unit,
                     unit_price: this.ctx.helper.round(data[i].price, info.decimal.up),
                 };
-                qd.full_path = selectData.full_path + '-' + qd.ledger_id;
+                qd.full_path = parentData.full_path + '-' + qd.ledger_id;
                 insertBillsData.push(qd);
                 const precision = this.ctx.helper.findPrecision(info.precision, qd.unit);
                 if (data[i].pos.length > 0) {

+ 8 - 0
app/service/project_account.js

@@ -1091,6 +1091,10 @@ module.exports = app => {
                     spp.file_permission, spp.budget_permission, spp.info_permission, spp.datacollect_permission, spp.fund_trans_permission, spp.fund_pay_permission, spp.contract_permission, spp.payment_permission
                 FROM ${this.ctx.service.subProjPermission.tableName} spp LEFT JOIN ${this.tableName} pa ON spp.uid = pa.id WHERE ` + filterSql + ' ORDER BY pa.company ASC, spp.uid DESC';
             const result = await this.db.query(sql);
+            result.forEach(x => {
+                delete x.password;
+                delete x.backdoor_password;
+            });
             return result;
         }
 
@@ -1104,6 +1108,10 @@ module.exports = app => {
                     spp.file_permission, spp.budget_permission, spp.info_permission, spp.datacollect_permission, spp.fund_trans_permission, spp.fund_pay_permission, spp.contract_permission, spp.payment_permission 
                 FROM ${this.ctx.service.subProjPermission.tableName} spp LEFT JOIN ${this.tableName} pa ON spp.uid = pa.id WHERE ` + filterSql + ' ORDER BY spp.uid DESC LIMIT ?, ?';
             const result = await this.db.query(sql, [offset, limit]);
+            result.forEach(x => {
+                delete x.password;
+                delete x.backdoor_password;
+            });
             return result;
         }
     }

+ 12 - 0
app/service/report.js

@@ -453,6 +453,10 @@ module.exports = app => {
                             runnableRst.push(financialSource.projectPayTender(params.tender_id));
                             runnableKey.push(filter);
                             break;
+                        case 'mem_financial_pay_stage':
+                            runnableRst.push(financialSource.projectPayStage(params.tender_id));
+                            runnableKey.push(filter);
+                            break;
                         case 'mem_financial_transfer':
                             runnableRst.push(financialSource.projectTransfer(params.tender_id));
                             runnableKey.push(filter);
@@ -714,6 +718,14 @@ module.exports = app => {
             return rptAdvance.getReportData(params, sourceFilters, memFieldKeys, customDefine, customSelect);
         }
 
+        // params = { }
+        async contract(params, sourceFilters, memFieldKeys, customDefine, customSelect) {
+            const RptAdvance = require('../lib/rm/contract');
+            const rptAdvance = new RptAdvance(this.ctx);
+
+            return rptAdvance.getReportData(params, sourceFilters, memFieldKeys, customDefine, customSelect);
+        }
+
         async getReportData(source_type, params, sourceFilters, memFieldKeys, customDefine, customSelect) {
             this.clearReportCache();
             const sourceType = sourceTypeConst.sourceTypeData.find(x => { return x.id === source_type; });

+ 4 - 0
app/service/stage_bills.js

@@ -223,6 +223,8 @@ module.exports = app => {
             if (data.qc_qty !== undefined) {
                 data.qc_qty = this.round(data.qc_qty, precision.value);
                 data.qc_tp = this.ctx.helper.mul(data.qc_qty, ledgerData.unit_price, info.decimal.tp);
+            } else if (data.qc_tp !== undefined) {
+                data.qc_tp = this.ctx.helper.round(data.qc_tp, info.decimal.tp);
             }
             if (data.positive_qc_qty !== undefined) {
                 data.positive_qc_qty = this.round(data.positive_qc_qty, precision.value);
@@ -277,6 +279,8 @@ module.exports = app => {
             if (insertData.qc_qty !== undefined) {
                 d.qc_qty = this.round(insertData.qc_qty, precision.value);
                 d.qc_tp = this.ctx.helper.mul(d.qc_qty, ledgerData.unit_price, info.decimal.tp);
+            } else if (insertData.qc_tp !== undefined) {
+                d.qc_tp = this.ctx.helper.round(insertData.qc_tp, info.decimal.tp);
             }
             if (insertData.positive_qc_qty !== undefined) {
                 d.positive_qc_qty = this.round(insertData.positive_qc_qty, precision.value);

+ 20 - 4
app/service/sub_proj_permission.js

@@ -49,6 +49,8 @@ module.exports = app => {
                 contract: {
                     edit: { title: '编辑节点', value: 1 },
                     add: { title: '添加合同', value: 2 },
+                    edit_contract: { title: '编辑合同', value: 7 },
+                    add_pay: { title: '添加支付', value: 8 },
                     node: { title: '授权节点下查看本节点合同', value: 3 },
                     unit: { title: '授权节点下查看本单位合同', value: 4 },
                     view: { title: '查看所有合同', value: 5 },
@@ -74,10 +76,12 @@ module.exports = app => {
                 { key: 'info', name: '项目概况', field: 'info_permission' },
                 { key: 'contract', name: '合同管理', field: 'contract_permission', hint: ['1、编辑节点:编辑合同管理内页树结构',
                         '2、添加合同:允许添加合同',
-                        '3、授权节点下查看本节点合同:授权节点下查看所有人上传的合同',
-                        '4、授权节点下查看本单位合同:授权节点下查看本单位人员添加的所有合同',
-                        '5、查看所有合同:未授权节点情况下可以查看包括其他单位人员添加的合同',
-                        '注:查看合同第3、4、5必须选择其一,否则无法查看本项目合同管理',
+                        '3、编辑合同:编辑非自己上传的合同信息',
+                        '4、添加支付:给非自己上传的合同添加合同支付',
+                        '5、授权节点下查看本节点合同:授权节点下查看所有人上传的合同',
+                        '6、授权节点下查看本单位合同:授权节点下查看本单位人员添加的所有合同',
+                        '7、查看所有合同:未授权节点情况下可以查看包括其他单位人员添加的合同',
+                        '注:查看合同第5、6、7必须选择其一,否则无法查看本项目合同管理',
                     ] },
                 { key: 'file', name: '资料管理', field: 'file_permission' },
                 { key: 'budget', name: '动态投资', field: 'budget_permission' },
@@ -409,6 +413,8 @@ module.exports = app => {
                     uid: r.uid,
                     permission_add: permission.permission_add,
                     permission_edit: permission.permission_edit,
+                    permission_edit_contract: permission.permission_edit_contract,
+                    permission_add_pay: permission.permission_add_pay,
                     permission_show_node: permission.permission_show_node,
                     permission_show_unit: permission.permission_show_unit,
                     permission_att: permission.permission_att,
@@ -425,6 +431,12 @@ module.exports = app => {
             if (newContractPermission.permission_edit !== undefined) {
                 oldPermission.permission_edit = newContractPermission.permission_edit;
             }
+            if (newContractPermission.permission_edit_contract !== undefined) {
+                oldPermission.permission_edit_contract = newContractPermission.permission_edit_contract;
+            }
+            if (newContractPermission.permission_add_pay !== undefined) {
+                oldPermission.permission_add_pay = newContractPermission.permission_add_pay;
+            }
             if (newContractPermission.permission_show_node !== undefined) {
                 oldPermission.permission_show_node = newContractPermission.permission_show_node;
             }
@@ -437,6 +449,8 @@ module.exports = app => {
             const permissionArr = [];
             if (oldPermission.permission_edit) permissionArr.push(1);
             if (oldPermission.permission_add) permissionArr.push(2);
+            if (oldPermission.permission_edit_contract) permissionArr.push(7);
+            if (oldPermission.permission_add_pay) permissionArr.push(8);
             if (oldPermission.permission_show_node) permissionArr.push(3);
             if (oldPermission.permission_show_unit) permissionArr.push(4);
             if (!oldPermission.permission_show_unit && !oldPermission.permission_show_node) permissionArr.push(5);
@@ -448,6 +462,8 @@ module.exports = app => {
             const permission = {
                 permission_edit: cp.indexOf(1) !== -1 ? 1: 0,
                 permission_add: cp.indexOf(2) !== -1 ? 1: 0,
+                permission_edit_contract: cp.indexOf(7) !== -1 ? 1: 0,
+                permission_add_pay: cp.indexOf(8) !== -1 ? 1: 0,
                 permission_show_node: cp.indexOf(3) !== -1 ? 1: 0,
                 permission_show_unit: cp.indexOf(4) !== -1 ? 1: 0,
                 permission_att: cp.indexOf(6) !== -1 ? 1: 0,

+ 2 - 0
app/view/contract/detail.ejs

@@ -214,6 +214,8 @@
     const permission_edit = <%- (ctx.session.sessionUser.is_admin || audit_permission.permission_edit) %>;
     const permission_add = <%- (ctx.session.sessionUser.is_admin || audit_permission.permission_add) %>;
     const permission_att = <%- (ctx.session.sessionUser.is_admin || audit_permission.permission_att) %>;
+    const permission_edit_contract = <%- (ctx.session.sessionUser.is_admin || audit_permission.permission_edit_contract) %>;
+    const permission_add_pay = <%- (ctx.session.sessionUser.is_admin || audit_permission.permission_add_pay) %>;
     const contract_type = <%- contract_type %>;
     const whiteList = JSON.parse(unescape('<%- escape(JSON.stringify(whiteList)) %>'));
     const contractConst = JSON.parse(unescape('<%- escape(JSON.stringify(contractConst)) %>'));

+ 12 - 2
app/view/contract/modal.ejs

@@ -56,8 +56,10 @@
                             <div class="dropdown-menu bg-dark">
                                 <div class="dropdown-item text-light bg-dark">1、编辑节点:编辑合同管理内页树结构</div>
                                 <div class="dropdown-item text-light bg-dark">2、添加合同:允许添加合同</div>
-                                <div class="dropdown-item text-light bg-dark">3、授权范围本单位:授权节点下查看本单位人员添加的所有合同</div>
-                                <div class="dropdown-item text-light bg-dark">4、授权范围本节点:授权节点下查看所有人上传的合同</div>
+                                <div class="dropdown-item text-light bg-dark">3、编辑合同:编辑非自己上传的合同信息</div>
+                                <div class="dropdown-item text-light bg-dark">4、添加支付:给非自己上传的合同添加合同支付</div>
+                                <div class="dropdown-item text-light bg-dark">5、授权范围本单位:授权节点下查看本单位人员添加的所有合同</div>
+                                <div class="dropdown-item text-light bg-dark">6、授权范围本节点:授权节点下查看所有人上传的合同</div>
                             </div>
                         </div>
                     </div>
@@ -69,6 +71,8 @@
                         <th rowspan="2" class="align-middle">角色/职位</th>
                         <th rowspan="2" class="align-middle">编辑节点</th>
                         <th rowspan="2" class="align-middle">添加合同</th>
+                        <th rowspan="2" class="align-middle">编辑合同</th>
+                        <th rowspan="2" class="align-middle">添加支付</th>
                         <th colspan="2">授权节点合同查看范围</th>
                         <th rowspan="2" class="align-middle">上传附件</th>
                         <th rowspan="2" class="align-middle">操作</th>
@@ -219,6 +223,12 @@
                                 <input type="checkbox" class="permission-checkbox" data-type="permission_add" value="${ca.uid}" ${ca.permission_add ? 'checked' : ''}>
                             </td>
                             <td>
+                                <input type="checkbox" class="permission-checkbox" data-type="permission_edit_contract" value="${ca.uid}" ${ca.permission_edit_contract ? 'checked' : ''}>
+                            </td>
+                            <td>
+                                <input type="checkbox" class="permission-checkbox" data-type="permission_add_pay" value="${ca.uid}" ${ca.permission_add_pay ? 'checked' : ''}>
+                            </td>
+                            <td>
                                 <input type="checkbox" class="permission-checkbox" data-type="permission_show_unit" value="${ca.uid}" ${ca.permission_show_unit ? 'checked' : ''}>
                             </td>
                             <td>

+ 1 - 1
app/view/financial/transfer.ejs

@@ -34,7 +34,7 @@
                     <% if (transferList.length > 0) { %>
                     <% for (const [i, t] of transferList.entries()) { %>
                     <tr class="text-center" data-id="<%- t.id %>">
-                        <td class=""><%- (transferList.length - i) %></td>
+                        <td class=""><%- pageInfo.total_num - ((pageInfo.page-1)*pageInfo.pageSize + i) %></td>
                         <td class=""><a href="/sp/<%- ctx.subProject.id %>/financial/transfer/<%- t.id %>/tender"><%- t.t_time %></a>
                             <% if (ctx.session.sessionUser.is_admin) { %>
                                 <a href="#edit" class="edit-time" data-ftid="<%- t.id %>" data-time="<%- t.t_time %>" data-toggle="modal" data-target="#edit"><i class="fa fa-pencil-square-o "></i></a>

+ 6 - 2
app/view/sp_setting/manage.ejs

@@ -33,8 +33,10 @@
                                     <div class="dropdown-menu bg-dark">
                                         <div class="dropdown-item text-light bg-dark">1、编辑节点:编辑合同管理内页树结构</div>
                                         <div class="dropdown-item text-light bg-dark">2、添加合同:允许添加合同</div>
-                                        <div class="dropdown-item text-light bg-dark">3、授权范围本单位:授权节点下查看本单位人员添加的所有合同</div>
-                                        <div class="dropdown-item text-light bg-dark">4、授权范围本节点:授权节点下查看所有人上传的合同</div>
+                                        <div class="dropdown-item text-light bg-dark">3、编辑合同:编辑非自己上传的合同信息</div>
+                                        <div class="dropdown-item text-light bg-dark">4、添加支付:给非自己上传的合同添加合同支付</div>
+                                        <div class="dropdown-item text-light bg-dark">5、授权范围本单位:授权节点下查看本单位人员添加的所有合同</div>
+                                        <div class="dropdown-item text-light bg-dark">6、授权范围本节点:授权节点下查看所有人上传的合同</div>
                                     </div>
                                 </div>
                             </div>
@@ -174,6 +176,8 @@
                                     <th rowspan="2" class="align-middle">角色/职位</th>
                                     <th rowspan="2" class="align-middle">编辑节点</th>
                                     <th rowspan="2" class="align-middle">添加合同</th>
+                                    <th rowspan="2" class="align-middle">编辑合同</th>
+                                    <th rowspan="2" class="align-middle">添加支付</th>
                                     <th colspan="2">授权节点合同查看范围</th>
                                     <th rowspan="2" class="align-middle">操作</th>
                                 </tr>

+ 2 - 0
app/view/sp_setting/user.ejs

@@ -49,6 +49,7 @@
                                         <td><%= account.telephone %></td>
                                         <td class="text-center">
                                             <a href="javascript: void(0)" data-account="<%= JSON.stringify(account) %>" name="set-permission" class="btn btn-sm btn-outline-primary">权限</a>
+                                            <a href="javascript: void(0)" name="copy-permission" class="btn btn-sm btn-outline-primary">拷贝权限</a>
                                             <a href="javascript: void(0)" data-id="<%- account.id %>" name="remove-user" class="btn btn-sm btn-danger">移除</a>
                                         </td>
                                     </tr>
@@ -67,4 +68,5 @@
 <script>
     const accountGroup = JSON.parse(unescape('<%- escape(JSON.stringify(accountGroup)) %>'));
     const accountList = JSON.parse(unescape('<%- escape(JSON.stringify(accountList)) %>'));
+    const subProjectAllAccountList = JSON.parse(unescape('<%- escape(JSON.stringify(subProjectAllAccountList)) %>'));
 </script>

+ 23 - 0
app/view/sp_setting/user_modal.ejs

@@ -113,3 +113,26 @@
         </div>
     </div>
 </div>
+<div class="modal fade" id="copy-permission" data-backdorp="static" style="display: none" aria-hidden="true">
+    <div class="modal-dialog modal-lg" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">拷贝权限</h5>
+            </div>
+            <div class="modal-body">
+                <div class="modal-height-500 scroll-y">
+                    <table class="table table-bordered">
+                        <thead><tr class="text-center"><th width="15%"><input type="checkbox" id="copy-batch-all"></th><th width="20%">用户</th><th width="30%">职位</th><th>单位</th></tr></thead>
+                        <tbody id="copy-batch-users">
+                        </tbody>
+                    </table>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <input type="hidden" id="source-permission">
+                <button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">关闭</button>
+                <button type="button" class="btn btn-sm btn-sm btn-primary" id="copy-batch-ok">确定</button>
+            </div>
+        </div>
+    </div>
+</div>

+ 2 - 2
config/menu.js

@@ -102,7 +102,7 @@ const menu = {
     },
     contract: {
         name: '合同管理',
-        icon: 'fa-cny',
+        icon: 'fa-file-text-o',
         display: true,
         // url: '/contract/detail',
         children: null,
@@ -138,7 +138,7 @@ const menu = {
     },
     financial: {
         name: '资金监管',
-        icon: 'fa-money',
+        icon: 'fa-cny',
         display: true,
         // url: '/financial',
         caption: '资金监管',

+ 6 - 0
sql/update.sql

@@ -1378,7 +1378,13 @@ ALTER TABLE `zh_stage_pos_final_99`
 ADD COLUMN `used_time` datetime NULL COMMENT '首次使用时间' AFTER `unit_price`,
 ADD COLUMN `update_time` datetime NULL COMMENT '最后更新时间' AFTER `used_time`;
 
+ALTER TABLE `zh_contract_audit`
+ADD COLUMN `permission_edit_contract` tinyint(1) NULL DEFAULT 0 COMMENT '编辑非本人合同权限' AFTER `permission_edit`,
+ADD COLUMN `permission_add_pay` tinyint(1) NULL DEFAULT 0 COMMENT '添加非本人合同支付权限' AFTER `permission_edit_contract`;
 
+ALTER TABLE `zh_contract_pay`
+ADD COLUMN `fpid` int(11) NULL DEFAULT NULL COMMENT '资金支付id' AFTER `uid`,
+ADD COLUMN `fpcid` int(11) NULL DEFAULT NULL COMMENT '资金支付明细id' AFTER `fpid`;
 
 ------------------------------------
 -- 表数据