Explorar el Código

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

MaiXinRong hace 1 mes
padre
commit
e5dbb1d9cc

+ 189 - 2
app/controller/financial_controller.js

@@ -244,6 +244,15 @@ module.exports = app => {
                     case 'save-transfer':
                         responseData.data = await ctx.service.financialTransfer.saveTransfer(data.postData);
                         break;
+                    case 'edit-transfer-time':
+                        if (!ctx.session.sessionUser.is_admin) throw '没有权限修改划拨年月';
+                        if (!data.postData.id || !data.postData.t_time) throw '数据错误';
+                        const node = await ctx.service.financialTransfer.getDataById(data.postData.id);
+                        if (!node) {
+                            throw '该资金划拨不存在';
+                        }
+                        await ctx.service.financialTransfer.defaultUpdate(data.postData);
+                        break;
                     default:
                         throw '未知操作';
                 }
@@ -899,7 +908,7 @@ module.exports = app => {
                 unitList,
                 moment,
                 auditType: auditConst.auditType,
-                preUrl: '/sp/' + ctx.subProject.id + '/financial/pay' + (from ? '/list' : '/stage'),
+                preUrl: '/sp/' + ctx.subProject.id + '/financial/pay' + (from !== null ? '/' + from : '/stage'),
                 jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.financial.pay),
                 pageInfo,
             };
@@ -1110,6 +1119,184 @@ module.exports = app => {
         }
 
         /**
+         * 变更管理 页面 (Get)
+         *
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        async payTender(ctx) {
+            try {
+                await this._filterPayTender(ctx);
+            } catch (err) {
+                this.log(err);
+                ctx.redirect(`/sp/${ctx.subProject.id}/dashboard`);
+            }
+        }
+
+        async _filterPayTender(ctx) {
+            const financialPermission = await ctx.service.subProjPermission.getFinancailPermission(ctx.subProject.permission.fund_trans_permission, ctx.subProject.permission.fund_pay_permission);
+            if (!financialPermission.pay_show) {
+                throw '没有查看权限';
+            }
+            const fptAudits = await ctx.service.financialPayTenderAudit.getAllDataByCondition({ where: { spid: ctx.subProject.id, uid: ctx.session.sessionUser.accountId } });
+            const fptAuditTids = ctx.helper._.map(fptAudits, 'tid');
+            const fptReportTids = ctx.helper._.map(ctx.helper._.filter(fptAudits, { is_report: 1 }), 'tid');
+            const unitList = await ctx.service.constructionUnit.getAllDataByCondition({ where: { pid: ctx.session.sessionProject.id } });
+            const filterTids = ctx.session.sessionUser.is_admin ? null : fptAuditTids;
+            const tenderCondition = { spid: ctx.subProject.id, filter_fund: 0 };
+            let hadTender = false;
+            if (ctx.session.sessionUser.is_admin) {
+                hadTender = true;
+            } else if (fptAuditTids.length !== 0) {
+                hadTender = true;
+                tenderCondition.id = fptAuditTids;
+            } else {
+                hadTender = false;
+                tenderCondition.id = -1;
+            }
+            const categoryData = await this.ctx.service.category.getAllCategory(ctx.subProject);
+            const tenders = hadTender ? await ctx.service.tender.getAllDataByCondition({ where: tenderCondition, columns: ['id', 'name', 'category'] }) : [];
+            const allPays = await ctx.service.financialPay.getListByStatus(ctx.subProject.id, null, 0, filterTids);
+            const transfersCondition = { spid: ctx.subProject.id };
+            if (filterTids) {
+                transfersCondition.tid = filterTids;
+            }
+            const allTransfers = await ctx.service.financialTransferTender.getAllDataByCondition({ where: transfersCondition });
+            const accountList = await ctx.service.projectAccount.getAllSubProjectAccount(ctx.subProject, ['id', 'account', 'name', 'company', 'company_id', 'role', 'enable', 'is_admin', 'account_group', 'mobile']);
+            const user = accountList.find(item => item.id === ctx.session.sessionUser.accountId) || null;
+            const userCompany = user ? ctx.helper._.find(unitList, { name: user.company }) : null;
+            if (!userCompany) {
+                throw '请联系管理员添加用户所在单位信息';
+            }
+            const allPayStages = await ctx.service.financialPayStage.getListByStatus(ctx.subProject.id, null, userCompany ? userCompany.id : 0, null, 0);
+            for (const t of tenders) {
+                t.category = t.category && t.category !== '' ? JSON.parse(t.category) : null;
+                const tenderPays = ctx.helper._.filter(allPays, { tid: t.id });
+                let payAmount = 0;
+                for (const p of tenderPays) {
+                    payAmount = ctx.helper.add(payAmount, p.total_price);
+                    p.stage = ctx.helper._.find(allPayStages, { id: p.fpsid }) || null;
+                    p.tenderName = t ? t.name : '';
+                    p.order = p.stage ? p.stage.order : 0;
+                    const userInfo = ctx.helper._.find(accountList, { id: p.uid });
+                    p.username = userInfo ? userInfo.name : '';
+                    if (p.status !== auditConst.financial.status.checked || !p.final_auditor_str) {
+                        p.curAuditors = await ctx.service.financialPayAudit.getAuditorsByStatus(p.id, p.status, p.times);
+                        if (p.status === auditConst.financial.status.checked && p.curAuditors.length > 0) {
+                            const final_auditor_str = p.curAuditors[0].audit_type === auditConst.auditType.key.common
+                                ? p.curAuditors[0].name + (p.curAuditors[0].role ? '-' + p.curAuditors[0].role : '')
+                                : ctx.helper.transFormToChinese(p.curAuditors[0].audit_order) + '审';
+                            await ctx.service.financialPay.defaultUpdate({ final_auditor_str }, { where: { id: p.id } });
+                        }
+                    }
+                    if (p.status !== auditConst.financial.status.checked) {
+                        p.entities = await ctx.service.financialPayContract.getEntities(p.id);
+                    }
+                }
+                t.pay_amount = payAmount;
+                t.pay_num = tenderPays.length;
+                const tenderTransfers = ctx.helper._.filter(allTransfers, { tid: t.id });
+                let transferAmount = 0;
+                for (const tr of tenderTransfers) {
+                    transferAmount = ctx.helper.add(transferAmount, tr.hb_tp);
+                }
+                t.transfer_amount = transferAmount;
+            }
+            // const accountList = await ctx.service.projectAccount.getAllSubProjectAccount(ctx.subProject, ['id', 'account', 'name', 'company', 'company_id', 'role', 'enable', 'is_admin', 'account_group', 'mobile']);
+            // const user = accountList.find(item => item.id === ctx.session.sessionUser.accountId) || null;
+            // const userCompany = user ? ctx.helper._.find(unitList, { name: user.company }) : null;
+            // if (!userCompany) {
+            //     throw '请联系管理员添加用户所在单位信息';
+            // }
+            // const userOrderList = await ctx.service.financialPayStage.getUserOrderList(ctx.subProject.id, userCompany ? userCompany.id : 0);
+            // const userCompanyList = await ctx.service.financialPayStage.getUserCompanyList(ctx.subProject.id, userCompany ? userCompany.id : 0, unitList);
+            // // const payList = await ctx.service.financialPayStage.getListByStatus(ctx.subProject.id, companyInfo ? companyInfo.id : null, userCompany ? userCompany.id : 0, qi);
+            const filter = JSON.parse(JSON.stringify(auditConst.financial.filter));
+            // filter.count = [];
+            // filter.count[filter.status.pending] = await ctx.service.financialPay.getCountByStatus(ctx.subProject.id, fpsidList.length > 0 ? fpsidList : null, filter.status.pending, filterTids, used);
+            // filter.count[filter.status.uncheck] = await ctx.service.financialPay.getCountByStatus(ctx.subProject.id, fpsidList.length > 0 ? fpsidList : null, filter.status.uncheck, filterTids, used);
+            // filter.count[filter.status.checking] = await ctx.service.financialPay.getCountByStatus(ctx.subProject.id, fpsidList.length > 0 ? fpsidList : null, filter.status.checking, filterTids, used);
+            // filter.count[filter.status.checked] = await ctx.service.financialPay.getCountByStatus(ctx.subProject.id, fpsidList.length > 0 ? fpsidList : null, filter.status.checked, filterTids, used);
+            // const payList = await ctx.service.financialPay.getListByStatus(ctx.subProject.id, fpsidList.length > 0 ? fpsidList : null, status, filterTids, used, 1);
+            // const total = await ctx.service.financialPay.getCountByStatus(ctx.subProject.id, fpsidList.length > 0 ? fpsidList : null, status, filterTids, used);
+            // // 分页相关
+            // const page = ctx.page;
+            // const pageSize = ctx.pageSize;
+            // const pageInfo = {
+            //     page,
+            //     pageSizeSelect: 1,
+            //     pageSize,
+            //     total_num: total,
+            //     total: Math.ceil(total / pageSize),
+            //     queryData: JSON.stringify(ctx.urlInfo.query),
+            // };
+            // for (const pay of payList) {
+            //     const t = ctx.helper._.find(tenders, { id: pay.tid });
+            //     pay.tenderName = t ? t.name : '';
+            //     const userInfo = ctx.helper._.find(accountList, { id: pay.uid });
+            //     pay.username = userInfo ? userInfo.name : '';
+            //     if (pay.status !== auditConst.financial.status.checked || !pay.final_auditor_str) {
+            //         pay.curAuditors = await ctx.service.financialPayAudit.getAuditorsByStatus(pay.id, pay.status, pay.times);
+            //         if (pay.status === auditConst.financial.status.checked && pay.curAuditors.length > 0) {
+            //             const final_auditor_str = pay.curAuditors[0].audit_type === auditConst.auditType.key.common
+            //                 ? pay.curAuditors[0].name + (pay.curAuditors[0].role ? '-' + pay.curAuditors[0].role : '')
+            //                 : ctx.helper.transFormToChinese(pay.curAuditors[0].audit_order) + '审';
+            //             await ctx.service.financialPay.defaultUpdate({ final_auditor_str }, { where: { id: pay.id } });
+            //         }
+            //     }
+            //     if (pay.status !== auditConst.financial.status.checked) {
+            //         pay.entities = await ctx.service.financialPayContract.getEntities(pay.id);
+            //     }
+            //     pay.stage = pay.fpsid ? await ctx.service.financialPayStage.getOnePayStage(pay.fpsid) : null;
+            // }
+            const renderData = {
+                categoryData,
+                tenders,
+                financialPermission,
+                usedList: financialConst.used,
+                auditConst: auditConst.financial,
+                filter,
+                allPays,
+                fptAuditTids,
+                fptReportTids,
+                unitList,
+                moment,
+                auditType: auditConst.auditType,
+                // preUrl: '/sp/' + ctx.subProject.id + '/financial/pay' + (from === 'list' ? '/list/?from=' + from : '/stage'),
+                jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.financial.payTender),
+                // pageInfo,
+            };
+            await this.layout('financial/pay_tender.ejs', renderData);
+        }
+
+        async payTenderSave(ctx) {
+            try {
+                const responseData = {
+                    err: 0, msg: '', data: {},
+                };
+                const data = JSON.parse(ctx.request.body.data);
+                if (!data.type) {
+                    throw '提交数据错误';
+                }
+                const payStage = await ctx.service.financialPayStage.getDataById(ctx.params.fpsid);
+                if (!payStage) {
+                    throw '资金支付单位期不存在';
+                }
+                switch (data.type) {
+                    case 'tender':
+                        if (!data.tid) throw '未选择标段';
+                        responseData.data = await ctx.service.financialPay.addPay(ctx.subProject.id, payStage, data.updateData);
+                        break;
+                    default: throw '参数有误';
+                }
+                ctx.body = responseData;
+            } catch (err) {
+                this.log(err);
+                ctx.body = { err: 1, msg: err.toString(), data: {} };
+            }
+        }
+
+        /**
          * 获取审批界面所需的 原报、审批人数据等
          * @param ctx
          * @return {Promise<void>}
@@ -1142,7 +1329,7 @@ module.exports = app => {
                     from,
                     fileList,
                     authMobile: auth_mobile,
-                    returnUrl: `/sp/${ctx.subProject.id}/financial/pay/${from === 'list' ? 'list' : 'stage/' + ctx.financialPay.fpsid}`,
+                    returnUrl: `/sp/${ctx.subProject.id}/financial/pay/${from !== undefined ? 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),

+ 297 - 0
app/public/js/financial_pay_tender.js

@@ -0,0 +1,297 @@
+'use strict';
+
+const tenderListSpec = (function(){
+    function getTenderNodeHtml(node, arr, pid) {
+        const html = [];
+        html.push('<tr pid="' + pid + '" data-tid="'+ (!node.cid ? node.id : -1) +'"' + (!node.cid ? 'class="tender-info" data-id="'+ node.id +'" style="cursor: pointer;"' : '') + '>');
+        // 名称
+        html.push('<td style="min-width: 150px;" class="in-' + node.level + '">');
+        if (node.cid) {
+            html.push('<span onselectstart="return false" style="{-moz-user-select:none}" class="fold-switch mr-1" title="收起" cid="'+ node.sort_id +'"><i class="fa fa-minus-square-o"></i></span> <i class="fa fa-folder-o"></i> ');
+            html.push((node.level === 1 ? '<b>' : ''), node.name, (node.level === 1 ? '</b>' : ''));
+        } else {
+            html.push('<span class="text-muted mr-2">');
+            html.push(arr.indexOf(node) === arr.length - 1 ? '└' : '├');
+            html.push('</span>');
+            html.push(node.name);
+        }
+        html.push('</td>');
+        // 累计划拨
+        html.push('<td class="text-right" style="width: 15%">');
+        if (!node.cid) {
+            html.push(node.transfer_amount ? node.transfer_amount : '');
+        }
+        html.push('</td>');
+        // 累计支付
+        html.push('<td class="text-right" style="width: 15%">');
+        if (!node.cid) {
+            html.push(node.pay_amount ? node.pay_amount : '');
+        }
+        html.push('</td>');
+        // 支付次数
+        html.push('<td class="text-center" style="width: 15%">');
+        if (!node.cid) {
+            html.push(node.pay_num ? node.pay_num : '');
+        }
+        html.push('</td>');
+        html.push('</tr>');
+        return html.join('');
+    }
+    function getTenderTreeHeaderHtml() {
+        const html = [];
+        const left = $('#sub-menu').css('display') === 'none' ? 56 : 176;
+        html.push('<table class="table table-hover table-bordered" id="progress-table">')
+        html.push('<thead style="position: sticky;left:'+ left +'px;top: 0;">', '<tr>');
+        html.push('<th class="text-center" style="min-width: 150px;">', '标段名称', '</th>');
+        html.push('<th class="text-center" style="width: 15%">', '累计划拨', '</th>');
+        html.push('<th class="text-center" style="width: 15%">', '累计支付', '</th>');
+        html.push('<th class="text-center" style="width: 15%">', '支付次数', '</th>');
+        html.push('</tr>', '</thead>');
+        return html.join('');
+    }
+    return { getTenderNodeHtml, getTenderTreeHeaderHtml }
+})();
+
+
+
+let auditUtils;
+$(function () {
+    autoFlashHeight();
+
+    $('#company_select').change(function () {
+        const company_id = parseInt($(this).val()) || 0;
+        setSelectValue('company', company_id);
+    });
+
+    $('#order_select').change(function () {
+        const qi = parseInt($(this).val()) || 0;
+        setSelectValue('qi', qi);
+    });
+
+    function setSelectValue(select, value) {
+        const routes = [];
+        const company_id = select === 'company' ? value : parseInt($('#company_select').val());
+        if (company_id) {
+            const companyInfo = _.find(userCompanyList, { id: company_id });
+            if (companyInfo) routes.push('company=' + companyInfo.name);
+        }
+        const qi = select === 'qi' ? value : parseInt($('#order_select').val());
+        if (qi) {
+            routes.push('qi=' + qi);
+        }
+        if (getLocalCache('account-pageSize')) {
+            routes.push('pageSize=' + getLocalCache('account-pageSize'));
+        }
+        window.location.href = `/sp/${spid}/financial/pay/stage` + (routes.length ? '?' + routes.join('&') : '');
+    }
+
+    $('body').on('click', '.c-body .tender-info', function () {
+        $('.c-body .tender-info').removeClass('table-warning');
+        $(this).addClass('table-warning');
+        const tid = parseInt($(this).attr('data-id'));
+        if (!tid) {
+            toastr.warning('未选择标段');
+            return;
+        }
+        console.log(tid);
+        const tenderPays = _.filter(pays, { tid });
+        console.log(tenderPays);
+        $('#qi_select').val('0');
+        const qi_options = ['<option value="0">筛选期数</option>'];
+        // 只取order大于0的并去除重复并倒序排序
+        const qis = _.orderBy(_.uniq(_.map(tenderPays, 'order')).filter(o => o > 0), null, 'desc');
+        for (const order of qis) {
+            qi_options.push('<option value="' + order + '">第' + order + '期</option>');
+        }
+        $('#qi_select').html(qi_options.join(''));
+        $('#used_selected').text('资金用途:全部');
+        // used_select清除如果存在用途为'<a class="dropdown-item to-log-link" data-val="" href="javascript:void(0);">全部</a>'这条remove掉
+        $('#used_select').find('a.to-log-link[data-val=""]').remove();
+        payListHtml(tenderPays, 0);
+    });
+
+    $('body').on('change', '#qi_select', function () {
+        const order = parseInt($(this).val());
+        const tid = parseInt($('.c-body .tender-info.table-warning').attr('data-id'));
+        if (!tid) {
+            toastr.warning('未选择标段');
+            return;
+        }
+        const tenderPays = _.filter(pays, { tid });
+        let newTenderPays = tenderPays;
+        if (order !== 0) {
+            newTenderPays = _.filter(tenderPays, { order });
+        }
+        const used = $('#used_selected').attr('data-val') || '';
+        if (used !== '') {
+            newTenderPays = _.filter(newTenderPays, { used });
+        }
+        const status = parseInt($('#status_selected').attr('data-val')) || 0;
+        payListHtml(newTenderPays, status);
+    });
+
+    $('body').on('click', '#used_select .to-log-link', function () {
+        const used = $(this).attr('data-val') || '';
+        $('#used_selected').attr('data-val', used);
+        $('#used_selected').text('资金用途:' + (used === '' ? '全部' : used));
+        if (used !== '' && $('#used_select').find('a.to-log-link[data-val=""]').length === 0) {
+            $('#used_select').prepend('<a class="dropdown-item to-log-link" data-val="" href="javascript:void(0);">全部</a>');
+        } else if (used === '') {
+            $('#used_select').find('a.to-log-link[data-val=""]').remove();
+        }
+        const tid = parseInt($('.c-body .tender-info.table-warning').attr('data-id'));
+        if (!tid) {
+            toastr.warning('未选择标段');
+            return;
+        }
+        let tenderPays = _.filter(pays, { tid });
+        const order = parseInt($('#qi_select').val()) || 0;
+        if (order !== 0) {
+            tenderPays = _.filter(tenderPays, { order });
+        }
+        if (used !== '') {
+            tenderPays = _.filter(tenderPays, { used });
+        }
+        const status = parseInt($('#status_selected').attr('data-val')) || 0;
+        payListHtml(tenderPays, status);
+    });
+
+    $('body').on('click', '#status_select .to-log-link', function () {
+        const status = parseInt($(this).attr('data-val')) || 0;
+        const tid = parseInt($('.c-body .tender-info.table-warning').attr('data-id'));
+        if (!tid) {
+            toastr.warning('未选择标段');
+            return;
+        }
+        let tenderPays = _.filter(pays, { tid });
+        const order = parseInt($('#qi_select').val()) || 0;
+        if (order !== 0) {
+            tenderPays = _.filter(tenderPays, { order });
+        }
+        const used = $('#used_selected').attr('data-val') || '';
+        if (used !== '') {
+            tenderPays = _.filter(tenderPays, { used });
+        }
+        payListHtml(tenderPays, status);
+    });
+
+    function payListHtml(tenderPays, status = 0) {
+        const status_options = [];
+        for (const fs in filter.status) {
+            const f = filter.status[fs];
+            let num = 0;
+            switch(f) {
+                case filter.status.pending:
+                    num = _.filter(tenderPays, function (item) {
+                        return (item.status === auditConst.status.checking && item.curAuditors && item.curAuditors.findIndex(x => { return x.aid === user_id; }) >= 0 && item.curAuditors.find(x => { return x.aid === user_id; }).status === auditConst.status.checking) || (item.uid === user_id && (item.status === auditConst.status.uncheck || item.status === auditConst.status.checkNo));
+                    }).length;
+                    break;
+                case filter.status.uncheck:
+                    num = _.filter(tenderPays, function (item) {
+                        return item.status === auditConst.status.uncheck || item.status === auditConst.status.checkNo;
+                    }).length;
+                    break;
+                case filter.status.checking:
+                    num = _.filter(tenderPays, function (item) {
+                        return item.status === auditConst.status.checking;
+                    }).length;
+                    break;
+                case filter.status.checked:
+                    num = _.filter(tenderPays, function (item) {
+                        return item.status === auditConst.status.checked;
+                    }).length;
+                    break;
+                default:
+                    break;
+            }
+            if (status !== f) status_options.push('<a class="dropdown-item to-log-link" data-val="' + f + '" href="javascript:void(0);">' + filter.statusString[f] + '(' + num + ')</a>');
+        }
+        if (status !== 0) status_options.unshift('<a class="dropdown-item to-log-link" data-val="0" href="javascript:void(0);">全部</a>');
+        $('#status_select').html(status_options.join(''));
+        $('#status_selected').attr('data-val', status);
+        $('#status_selected').text('审批状态:' + (status === 0 ? '全部' : filter.statusString[status]));
+        let newTenderPays = tenderPays;
+        if (status !== 0) {
+            newTenderPays = _.filter(tenderPays, function (item) {
+                switch(status) {
+                    case filter.status.pending:
+                        return (item.status === auditConst.status.checking && item.curAuditors && item.curAuditors.findIndex(x => { return x.aid === user_id; }) >= 0 && item.curAuditors.find(x => { return x.aid === user_id; }).status === auditConst.status.checking) || (item.uid === user_id && (item.status === auditConst.status.uncheck || item.status === auditConst.status.checkNo));
+                    case filter.status.uncheck:
+                        return item.status === auditConst.status.uncheck || item.status === auditConst.status.checkNo;
+                    case filter.status.checking:
+                        return item.status === auditConst.status.checking;
+                    case filter.status.checked:
+                        return item.status === auditConst.status.checked;
+                    default:
+                        return true;
+                }
+            });
+        }
+        let html = '';
+        for (const pay of newTenderPays) {
+            let statusHtml = '';
+            if (pay.status === auditConst.status.checked && pay.final_auditor_str) {
+                statusHtml = `<a href="#sp-list" data-toggle="modal" data-target="#sp-list" c-id="${pay.id}">${pay.final_auditor_str}</a>`;
+            } else if (pay.curAuditors.length > 0) {
+                if (pay.curAuditors[0].audit_type === auditType.key.common) {
+                    statusHtml = `<a href="#sp-list" data-toggle="modal" data-target="#sp-list" c-id="${pay.id}">${pay.curAuditors[0].name}${ pay.curAuditors[0].role !== '' && pay.curAuditors[0].role !== null? '-' + pay.curAuditors[0].role : ''}</a>`;
+                } else {
+                    statusHtml = `<a href="#sp-list" data-toggle="modal" data-target="#sp-list" c-id="${pay.id}">${transFormToChinese(pay.curAuditors[0].audit_order) + '审'}</a>`;
+                }
+            }
+            let operationHtml = '';
+            if (pay.status === auditConst.status.uncheck && pay.uid === user_id) {
+                operationHtml = `<a href="/sp/${spid}/financial/pay/${pay.id}/detail?from=tender" class="btn ${auditConst.statusButtonClass[pay.status]} btn-sm">${auditConst.statusButton[pay.status]}</a>`;
+            } else if (pay.status === auditConst.status.checkNo && pay.curAuditors && pay.uid === user_id) {
+                operationHtml = `<a href="/sp/${spid}/financial/pay/${pay.id}/detail?from=tender" class="btn ${auditConst.statusButtonClass[pay.status]} btn-sm">${auditConst.statusButton[pay.status]}</a>`;
+            } else if (pay.status === auditConst.status.checking && pay.curAuditors && pay.curAuditors.findIndex(x => { return x.aid === user_id; }) >= 0) {
+                const curAudit = pay.curAuditors.find(x => { return x.aid === user_id });
+                if (curAudit.status === auditConst.status.checking) {
+                    operationHtml = `<a href="/sp/${spid}/financial/pay/${pay.id}/detail?from=tender" class="btn ${auditConst.statusButtonClass[pay.status]} btn-sm">${auditConst.statusButton[pay.status]}</a>`;
+                } else {
+                    operationHtml = `<span class="${auditConst.auditStringClass[curAudit.status]}">${auditConst.auditString[curAudit.status]}</span>`;
+                }
+            } else {
+                operationHtml = `<span class="${auditConst.auditStringClass[pay.status]}">${auditConst.auditString[pay.status]}</span>`;
+            }
+            html += `<tr class="text-center" data-tid="${pay.order}">
+                            <td class="">${pay.stage ? '<a href="/sp/'+ spid + '/financial/pay/stage/' + pay.stage.id + '?from=tender" class="account-page-size">第' + pay.stage.order + '期</a>' : '' }</td>
+                            <td class=""><a href="/sp/${spid}/financial/pay/${pay.id}/detail?from=tender">${pay.code}</td>
+                            <td class="">${moment(pay.create_time).format('YYYY-MM-DD')}</td>
+                            <td class="">${pay.username}</td>
+                            <td class="">${pay.used}</td>
+                            <td class="">${pay.entities}</td>
+                            <td class="text-right">${pay.total_price}</td>
+                            <td class="text-left ${auditConst.auditProgressClass[pay.status]}">
+                                ${statusHtml}
+                                ${auditConst.auditProgress[pay.status]}
+                            </td>
+                            <td>
+                                ${operationHtml}
+                            </td>
+                        </tr>`;
+        }
+        $('#pay-list').html(html);
+    }
+
+    setTimeout(function () {
+        $('.c-body .tender-info').eq(0).click();// 需要延时加载
+    }, 500);
+
+    $.subMenu({
+        menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
+        toMenu: '#to-menu', toMiniMenu: '#to-mini-menu',
+        key: 'menu.1.0.0',
+        miniHint: '#sub-mini-hint', hintKey: 'menu.hint.1.0.1',
+        callback: function (info) {
+            if (info.mini) {
+                $('.panel-title').addClass('fluid');
+                $('#sub-menu').removeClass('panel-sidebar');
+            } else {
+                $('.panel-title').removeClass('fluid');
+                $('#sub-menu').addClass('panel-sidebar');
+            }
+            autoFlashHeight();
+        }
+    });
+});

+ 35 - 0
app/public/js/financial_transfer.js

@@ -9,6 +9,41 @@ $(function () {
         $('#add-transfer-form').submit();
     });
 
+    let editPeriod = null;
+    $('.edit-time').on('click', function () {
+        const t_time = $(this).data('time');
+        const ftid = parseInt($(this).data('ftid'));
+        console.log(t_time, ftid);
+        $('#edit-transfer-date').val('');
+        $('#edit-ftid').val(ftid);
+        $('#edit-transfer-date').val(t_time);
+        editPeriod = !editPeriod ? $('#edit-transfer-date').datepicker().data('datepicker') : editPeriod;
+        editPeriod.clear();
+        editPeriod.selectDate(new Date(t_time));
+    });
+
+    $('#edit-ok').click(function () {
+        const id = parseInt($('#edit-ftid').val());
+        if (!id) {
+            toastr.error('获取资金划拨信息失败');
+            return;
+        }
+        const trInfo = _.find(transferList, { id });
+        if (!trInfo) {
+            toastr.error('获取资金划拨信息失败');
+            return;
+        }
+        const t_time = $('#edit-transfer-date').val();
+        if (t_time === '') {
+            toastr.error('请选择划拨年月');
+            return false;
+        }
+        postData(window.location.pathname + '/update', {postType: 'edit-transfer-time', postData: { id, t_time }}, function (result) {
+            window.location.reload();
+        })
+    });
+
+
     $('body').on('click', '#transfer-list .del-transfer-btn', function () {
         const trid = $(this).data('id');
         deleteAfterHint(function () {

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

@@ -28,6 +28,7 @@ function autoFlashHeight(){
     $(".sjs-height-4").height($(window).height()-cHeader-pBarz-110+75);
     $(".sjs-height-5").height($(window).height()-cHeader-sBar-492+55);/*492*/
     $(".sjs-height-6").height($(window).height()-cHeader-34-sBar1);
+    $(".sjs-height-7").height($(window).height()-cHeader-34-41);
     $(".sp-wrap").height(bcontent-30);
     /*侧栏高度*/
     $(".sjs-sh-1").height($(window).height()-cHeader-sBar1-92+55);
@@ -212,7 +213,7 @@ $(function(){
     })
 });
 
-function setChangeFilterData(orderLocal) {
+function setChangeFilterData(orderLocal, filterString = '') {
     const filterData = [];
     const orderSetting = getLocalCache(orderLocal);
     if(orderSetting) {
@@ -223,8 +224,8 @@ function setChangeFilterData(orderLocal) {
     if (getLocalCache('account-pageSize')) {
         filterData.push('pageSize=' + getLocalCache('account-pageSize'));
     }
-    let filterString = '';
-    if (filterData.length > 0) filterString = filterString + '?' + filterData.join('&');
+    filterString = filterString ? filterString + '&' : filterString + '?';
+    if (filterData.length > 0) filterString = filterString + filterData.join('&');
     return filterString;
 }
 

+ 2 - 0
app/router.js

@@ -452,6 +452,8 @@ module.exports = app => {
     app.post('/sp/:id/financial/pay/:fpid/audit/check/again', sessionAuth, subProjectCheck, financialCheck, financialPayCheck, 'financialController.checkPayAgain');
     app.get('/sp/:id/financial/pay/list', sessionAuth, subProjectCheck, financialCheck, 'financialController.payList');
     app.post('/sp/:id/financial/pay/list/save', sessionAuth, subProjectCheck, financialCheck, 'financialController.payListSave');
+    app.get('/sp/:id/financial/pay/tender', sessionAuth, subProjectCheck, financialCheck, 'financialController.payTender');
+    app.post('/sp/:id/financial/pay/tender/save', sessionAuth, subProjectCheck, financialCheck, 'financialController.payTenderSave');
     app.get('/sp/:id/financial/summary', sessionAuth, subProjectCheck, financialCheck, 'financialController.summary');
     app.post('/sp/:id/financial/summary/load', sessionAuth, subProjectCheck, financialCheck, 'financialController.summaryLoad');
 

+ 4 - 4
app/service/financial_transfer.js

@@ -38,10 +38,10 @@ module.exports = app => {
         }
 
         async addTransfer(spid, date, remark) {
-            const node = await this.getDataByCondition({ spid, t_time: date });
-            if (node) {
-                throw '资金划拨年月已存在,请勿重复';
-            }
+            // const node = await this.getDataByCondition({ spid, t_time: date });
+            // if (node) {
+            //     throw '资金划拨年月已存在,请勿重复';
+            // }
             let pre_hb_tp = 0;
             const ftList = await this.getAllDataByCondition({ where: { spid } });
             if (ftList.length > 0) {

+ 2 - 2
app/view/change/apply_modal.ejs

@@ -113,7 +113,7 @@
                                     <% for (const rule of codeRule) { %>
                                         <% preview.push(rule.preview); %>
                                     <% } %>
-                                    <%- preview.join(tender.c_connector !== null && tender.c_connector !== '3' ? ruleConst.connectorString[tender.c_connector] : ''); %>
+                                    <%- preview.join(c_connector !== null && c_connector !== '3' ? ruleConst.connectorString[c_connector] : ''); %>
                                 <% } %>
                             </span>
                         </h5>
@@ -134,7 +134,7 @@
                             <select class="form-control form-control-sm connector-change">
                                 <option disabled selected>请选择</option>
                                 <% for (const index in ruleConst.connectorString) { %>
-                                    <option value="<%- index %>" <% if (tender.c_connector !== null && tender.c_connector === parseInt(index)) { %>selected<% } %>><%- ruleConst.connectorString[index] %></option>
+                                    <option value="<%- index %>" <% if (c_connector !== null && parseInt(c_connector) === parseInt(index)) { %>selected<% } %>><%- ruleConst.connectorString[index] %></option>
                                 <% } %>
                             </select>
                         </div>

+ 2 - 2
app/view/change/plan_modal.ejs

@@ -113,7 +113,7 @@
                                     <% for (const rule of codeRule) { %>
                                         <% preview.push(rule.preview); %>
                                     <% } %>
-                                    <%- preview.join(tender.c_connector !== null && tender.c_connector !== '3' ? ruleConst.connectorString[tender.c_connector] : ''); %>
+                                    <%- preview.join(c_connector !== null && c_connector !== '3' ? ruleConst.connectorString[c_connector] : ''); %>
                                 <% } %>
                             </span>
                         </h5>
@@ -134,7 +134,7 @@
                             <select class="form-control form-control-sm connector-change">
                                 <option disabled selected>请选择</option>
                                 <% for (const index in ruleConst.connectorString) { %>
-                                    <option value="<%- index %>" <% if (tender.c_connector !== null && tender.c_connector === parseInt(index)) { %>selected<% } %>><%- ruleConst.connectorString[index] %></option>
+                                    <option value="<%- index %>" <% if (c_connector !== null && parseInt(c_connector) === parseInt(index)) { %>selected<% } %>><%- ruleConst.connectorString[index] %></option>
                                 <% } %>
                             </select>
                         </div>

+ 2 - 2
app/view/change/project_modal.ejs

@@ -113,7 +113,7 @@
                                     <% for (const rule of codeRule) { %>
                                         <% preview.push(rule.preview); %>
                                     <% } %>
-                                    <%- preview.join(tender.c_connector !== null && tender.c_connector !== '3' ? ruleConst.connectorString[tender.c_connector] : ''); %>
+                                    <%- preview.join(c_connector !== null && c_connector !== '3' ? ruleConst.connectorString[c_connector] : ''); %>
                                 <% } %>
                             </span>
                         </h5>
@@ -134,7 +134,7 @@
                             <select class="form-control form-control-sm connector-change">
                                 <option disabled selected>请选择</option>
                                 <% for (const index in ruleConst.connectorString) { %>
-                                    <option value="<%- index %>" <% if (tender.c_connector !== null && tender.c_connector === parseInt(index)) { %>selected<% } %>><%- ruleConst.connectorString[index] %></option>
+                                    <option value="<%- index %>" <% if (c_connector !== null && parseInt(c_connector) === parseInt(index)) { %>selected<% } %>><%- ruleConst.connectorString[index] %></option>
                                 <% } %>
                             </select>
                         </div>

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

@@ -7,7 +7,7 @@
                 <div class="btn-group group-tab">
                     <a class="btn btn-sm btn-light account-page-size" href="/sp/<%- ctx.subProject.id %>/financial/pay/stage">支付列表</a>
                     <a class="btn btn-sm btn-light active" href="javascript:void(0);">汇总列表</a>
-                    <a class="btn btn-sm btn-light" href="/financial/pay">标段统计</a>
+                    <a class="btn btn-sm btn-light" href="/sp/<%- ctx.subProject.id %>/financial/pay/tender">标段统计</a>
                 </div>
                 <div class="d-inline-block col-sm-2">
                     <div class="input-group input-group-sm pr-1">

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

@@ -7,7 +7,7 @@
                 <div class="btn-group group-tab">
                     <a class="btn btn-sm btn-light active" href="javascript:void(0);">支付列表</a>
                     <a class="btn btn-sm btn-light account-page-size" href="/sp/<%- ctx.subProject.id %>/financial/pay/list">汇总列表</a>
-                    <a class="btn btn-sm btn-light" href="/financial/pay">标段统计</a>
+                    <a class="btn btn-sm btn-light" href="/sp/<%- ctx.subProject.id %>/financial/pay/tender">标段统计</a>
                 </div>
                 <div class="d-inline-block col-sm-3">
                     <div class="input-group input-group-sm pr-1">

+ 103 - 0
app/view/financial/pay_tender.ejs

@@ -0,0 +1,103 @@
+<% include ./sub_menu.ejs %>
+<div class="panel-content">
+    <div class="panel-title">
+        <div class="title-main  d-flex">
+            <% include ./sub_mini_menu.ejs %>
+            <div class="col-11 pl-0">
+                <div class="btn-group group-tab">
+                    <a class="btn btn-sm btn-light account-page-size" href="/sp/<%- ctx.subProject.id %>/financial/pay/stage">支付列表</a>
+                    <a class="btn btn-sm btn-light" href="/sp/<%- ctx.subProject.id %>/financial/pay/list">汇总列表</a>
+                    <a class="btn btn-sm btn-light active" href="javascript:void(0);">标段统计</a>
+                </div>
+            </div>
+            <div class="d-inline-block ml-auto">
+<!--                <a href="#batch-sp" data-toggle="modal" data-target="#batch-sp" class="btn btn-success btn-sm pull-right mr-2">批量审批</a>-->
+            </div>
+        </div>
+    </div>
+    <div class="content-wrap">
+        <div class="d-flex sjs-height-0" style="background-color: #fff">
+            <div class="col-4">
+                <div class="d-flex my-2">
+                    <div class="d-inline-block ml-1" id="show-level"></div>
+                </div>
+                <div class="sjs-height-7" style="overflow: auto;">
+                    <div class="c-body"></div>
+                </div>
+            </div>
+            <div class="col">
+                <div class="d-flex my-2">
+                    <div class="col-sm-2 pl-0">
+                        <div class="input-group input-group-sm pr-1">
+                            <select class="form-control form-control-sm col-auto" id="qi_select">
+                                <option value="0">筛选期数</option>
+                            </select>
+                        </div>
+                    </div>
+                    <div class="">
+                        <div class="input-group input-group-sm pr-1">
+                            <div class="btn-group">
+                                <button type="button" class="btn btn-sm btn-light text-primary dropdown-toggle" data-toggle="dropdown" id="used_selected" data-value="">资金用途:全部</button>
+                                <div class="dropdown-menu" aria-labelledby="used_selected" id="used_select">
+                                    <% for (const u of usedList) { %>
+                                        <a class="dropdown-item to-log-link" href="javascript:void(0)" data-val="<%- u %>"><%- u %></a>
+                                    <% } %>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="">
+                        <div class="input-group input-group-sm pr-1">
+                            <div class="btn-group">
+                                <button type="button" class="btn btn-sm btn-light text-primary dropdown-toggle" data-toggle="dropdown" id="status_selected" data-value="">审批状态:全部</button>
+                                <div class="dropdown-menu" aria-labelledby="status_selected" id="status_select">
+                                    <% for (const fs in filter.status) { %>
+                                        <% const f = filter.status[fs]; %>
+                                        <a class="dropdown-item to-log-link" data-val="<%- f %>" href="javascript:void(0);"><%- filter.statusString[f] %>()</a>
+                                    <% } %>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="ml-auto">
+<!--                        <a href="#batch-sp" data-toggle="modal" data-target="#batch-sp" class="btn btn-success btn-sm pull-right mr-2">批量审批</a>-->
+                    </div>
+                </div>
+                <div class="sjs-height-7" style="overflow: auto;">
+                    <table class="table table-bordered text-center">
+                        <thead>
+                        <tr>
+                            <th width="100px">关联期数</th>
+                            <th width="200px">支付编号</th>
+                            <th width="150px">申请时间</th>
+                            <th width="100px">申请人</th>
+                            <th width="200px">资金用途</th>
+                            <th width="300px">收款单位</th>
+                            <th width="150px">支付金额</th>
+                            <th width="200px">审批进度</th>
+                            <th width="150px">操作</th>
+                        </tr>
+                        </thead>
+                        <tbody id="pay-list">
+                        </tbody>
+                    </table>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+<script>
+    const user_id = <%- ctx.session.sessionUser.accountId %>;
+    const is_admin = <%- ctx.session.sessionUser.is_admin %>;
+    const category = JSON.parse(unescape('<%- escape(JSON.stringify(categoryData)) %>'));
+    const tenders = JSON.parse(unescape('<%- escape(JSON.stringify(tenders)) %>'));
+    const pays = JSON.parse(unescape('<%- escape(JSON.stringify(allPays)) %>'));
+    const fptReportTids = JSON.parse(unescape('<%- escape(JSON.stringify(fptReportTids)) %>'));
+    const auditConst = JSON.parse(unescape('<%- escape(JSON.stringify(auditConst)) %>'));
+    const auditType = JSON.parse(unescape('<%- escape(JSON.stringify(auditType)) %>'));
+    const filter = JSON.parse(unescape('<%- escape(JSON.stringify(filter)) %>'));
+    const selfCategoryLevel = '';
+    const pid = '<%- ctx.session.sessionProject.id %>';
+    const subProid = '<%- ctx.subProject.id %>';
+    const uphlname = 'user_' + user_id + '_pro_' + pid + '_sub_' + subProid + '_pay_tender_category_hide_list';
+</script>

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

@@ -35,7 +35,11 @@
                     <% for (const [i, t] of transferList.entries()) { %>
                     <tr class="text-center" data-id="<%- t.id %>">
                         <td class=""><%- (transferList.length - i) %></td>
-                        <td class=""><a href="/sp/<%- ctx.subProject.id %>/financial/transfer/<%- t.id %>/tender"><%- t.t_time %></a></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>
+                            <% } %>
+                        </td>
                         <td class="text-right"><%- t.total_price %></td>
                         <td class="text-right"><%- t.pre_hb_tp %></td>
                         <td class="text-right"><%- ctx.helper.add(t.total_price, t.pre_hb_tp) %></td>

+ 23 - 0
app/view/financial/transfer_modal.ejs

@@ -29,6 +29,29 @@
         </form>
     </div>
 </div>
+<% if (ctx.session.sessionUser.is_admin) { %>
+<div class="modal fade" id="edit" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">划拨年月编辑</h5>
+            </div>
+            <div class="modal-body">
+                <div class="form-group">
+                    <label>划拨年月</label>
+                    <input class="datepicker-here form-control form-control-sm" name="date" id="edit-transfer-date" readonly placeholder="点击选择划拨年月" data-view="months" data-min-view="months" data-date-format="yyyy-MM" data-language="zh" type="text">
+                </div>
+            </div>
+            <div class="modal-footer">
+                <input type="hidden" name="_csrf_j" value="<%= ctx.csrf %>" />
+                <input type="hidden" name="ftid" id="edit-ftid" value="">
+                <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
+                <button type="submit" class="btn btn-primary btn-sm" id="edit-ok" >确定修改</button>
+            </div>
+        </div>
+    </div>
+</div>
+<% } %>
 <% } %>
 <!--附件-->
 <div class="modal fade" id="transfer-file" data-backdrop="static" style="z-index: 1049">

+ 21 - 0
config/web.js

@@ -1963,6 +1963,27 @@ const JsFiles = {
                 ],
                 mergeFile: 'financial_pay_list',
             },
+            payTender: {
+                files: [
+                    '/public/js/decimal.min.js',
+                    '/public/js/math.min.js',
+                    '/public/js/component/menu.js',
+                    '/public/js/moment/moment.min.js',
+                ],
+                mergeFiles: [
+                    '/public/js/sub_menu.js',
+                    '/public/js/div_resizer.js',
+                    '/public/js/zh_calc.js',
+                    '/public/js/PinYinOrder.bundle.js',
+                    '/public/js/colResizable/colResizable-1.6.min.js',
+                    '/public/js/shares/tender_list_order.js',
+                    '/public/js/shares/show_level.js',
+                    '/public/js/tender_showhide.js',
+                    '/public/js/tender_list_base.js',
+                    '/public/js/financial_pay_tender.js',
+                ],
+                mergeFile: 'financial_pay_tender',
+            },
             payDetail: {
                 files: [
                     '/public/js/decimal.min.js',