Browse Source

项目合同管理功能

ellisran 4 months ago
parent
commit
4a4ebc3324

+ 5 - 5
app/controller/contract_controller.js

@@ -169,7 +169,7 @@ module.exports = app => {
                         // 判断用户是单个还是数组
                         uids = data.id instanceof Array ? data.id : [data.id];
                         // 判断该用户的组是否已加入到表中,已加入则提示无需添加
-                        auditList = await ctx.service.contractAudit.getAllDataByCondition({ where: options });
+                        auditList = await ctx.service.contractAudit.getList(options);
                         const addAidList = ctx.helper._.difference(uids, ctx.helper._.map(auditList, 'uid'));
                         if (addAidList.length === 0) {
                             throw '用户已存在成员管理中,无需重复添加';
@@ -181,16 +181,16 @@ module.exports = app => {
                     case 'del-audit':
                         uids = data.id instanceof Array ? data.id : [data.id];
                         const cloneOptions = ctx.helper._.cloneDeep(options);
-                        cloneOptions.id = uids;
-                        auditList = await ctx.service.contractAudit.getAllDataByCondition({ where: cloneOptions });
+                        cloneOptions.uid = uids;
+                        auditList = options.spid ? await ctx.service.subProjPermission.getContractAuditList(options.spid, uids) : await ctx.service.contractAudit.getAllDataByCondition({ where: cloneOptions });
                         if (auditList.length !== uids.length) {
                             throw '该用户已不存在成员管理中,移除失败';
                         }
-                        await ctx.service.contractAudit.delAudit(uids);
+                        await ctx.service.contractAudit.delAudit(options, ctx.helper._.map(auditList, 'id'));
                         responseData.data = await ctx.service.contractAudit.getList(options);
                         break;
                     case 'save-permission':
-                        result = await ctx.service.contractAudit.updatePermission(data.updateData);
+                        result = await ctx.service.contractAudit.updatePermission(options, data.updateData);
                         if (!result) {
                             throw '修改权限失败';
                         }

+ 1 - 1
app/middleware/contract_check.js

@@ -35,7 +35,7 @@ module.exports = options => {
             // 权限控制
             const cloneOptions = _.cloneDeep(options);
             cloneOptions.uid = this.session.sessionUser.accountId;
-            const result = yield this.service.contractAudit.getDataByCondition(cloneOptions);
+            const result = tid ? yield this.service.contractAudit.getDataByCondition(cloneOptions) : false;
             // const result = yield this.service.contractAudit.checkPermission(options, this.session.sessionUser.accountId);
             if (!result && !this.session.sessionUser.is_admin) {
                 throw '当前账号权限不足,请联系管理员添加权限';

+ 1 - 1
app/public/js/contract_detail.js

@@ -1684,7 +1684,7 @@ $(document).ready(function() {
                     contractTreeAudits = result;
                     sqTreeSpreadObj.setTreeAudits(sqSheet);
                 });
-            }, '确认除「当前节点授权用户」?');
+            }, '确认除「当前节点授权用户」?');
         });
     }
 

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

@@ -57,6 +57,29 @@ $(document).ready(() => {
             window.location.reload();
         });
     });
+    $('[name=permission-check]').click(function() {
+        const ptype = $(this).attr('ptype');
+        if (ptype === 'contract') {
+            const pvalue = $(this).attr('pvalue');
+            if (this.checked) {
+                if ((pvalue === '1' || pvalue === '2') && !$('[ptype=contract][pvalue="3"]').prop('checked') && !$('[ptype=contract][pvalue="4"]').prop('checked')) {
+                    $('[ptype=contract][pvalue="5"]').prop('checked', true);
+                }
+                if (pvalue === '3' || pvalue === '4') {
+                    $('[ptype=contract][pvalue="5"]').prop('checked', false);
+                } else if (pvalue === '5') {
+                    $('[ptype=contract][pvalue="3"]').prop('checked', false);
+                    $('[ptype=contract][pvalue="4"]').prop('checked', false);
+                }
+            } else if (!this.checked) {
+                if (pvalue === '3' || pvalue === '4') {
+                    if (!$('[ptype=contract][pvalue="3"]').prop('checked') && !$('[ptype=contract][pvalue="4"]').prop('checked')) {
+                        $('[ptype=contract][pvalue="5"]').prop('checked', true);
+                    }
+                }
+            }
+        }
+    });
     $('[name=set-permission]').click(function() {
         const data = JSON.parse(this.getAttribute('data-account'));
         const permissionCheck = $('[name="permission-check"]');
@@ -131,4 +154,4 @@ $(document).ready(() => {
             window.location.reload();
         })
     });
-});
+});

+ 1 - 0
app/router.js

@@ -295,6 +295,7 @@ module.exports = app => {
     app.get('/sp/:id/contract/tender/:tid/detail/:type/:cid/pay/:cpid/file/:fid/download', sessionAuth, subProjectCheck, contractCheck, 'contractController.downloadFile');
     // 项目合同管理
     app.get('/sp/:id/contract', sessionAuth, subProjectCheck, contractCheck, 'contractController.detail');
+    app.post('/sp/:id/contract/audit/save', sessionAuth, subProjectCheck, contractCheck, 'contractController.auditSave');
     app.get('/sp/:id/contract/detail', sessionAuth, subProjectCheck, contractCheck, 'contractController.detail');
     app.get('/sp/:id/contract/detail/:type', sessionAuth, subProjectCheck, contractCheck, 'contractController.detail');
     app.post('/sp/:id/contract/load', sessionAuth, subProjectCheck, contractCheck, 'contractController.loadDetail');

+ 43 - 18
app/service/contract_audit.js

@@ -23,7 +23,7 @@ module.exports = app => {
         }
 
         async getList(options) {
-            const list = await this.db.select(this.tableName, { where: options, orders: [['id', 'desc']] });
+            const list = options.spid ? await this.ctx.service.subProjPermission.getContractAuditList(options.spid) : await this.db.select(this.tableName, { where: options, orders: [['id', 'desc']] });
             for (const l of list) {
                 const accountInfo = await this.ctx.service.projectAccount.getDataById(l.uid);
                 l.name = accountInfo.name;
@@ -36,6 +36,22 @@ module.exports = app => {
 
         async saveAudits(options, accountList, transaction = null) {
             // 判断是否已存在该用户,存在则不插入
+            if (options.spid) {
+                const spAudits = await this.ctx.service.subProjPermission.getAllDataByCondition({ where: { spid: options.spid, uid: this._.map(accountList, 'id') } });
+                const insertData = [];
+                for (const a of spAudits) {
+                    if (!a.contract_permission) {
+                        insertData.push({
+                            id: a.id,
+                            contract_permission: '5',
+                        });
+                    }
+                }
+                if (insertData.length > 0) {
+                    return transaction ? await transaction.updateRows(this.ctx.service.subProjPermission.tableName, insertData) : await this.db.updateRows(this.ctx.service.subProjPermission.tableName, insertData);
+                }
+                return false;
+            }
             const pauditList = await this.getAllDataByCondition({ where: options });
             const pushData = [];
             for (const a of this._.uniqBy(accountList, 'id')) {
@@ -55,29 +71,38 @@ module.exports = app => {
             return false;
         }
 
-        async delAudit(id) {
-            return await this.db.delete(this.tableName, { id });
+        async delAudit(options, ids) {
+            if (options.spid) {
+                const updateData = [];
+                for (const id of ids) {
+                    updateData.push({
+                        id,
+                        contract_permission: '',
+                    });
+                }
+                return await this.db.updateRows(this.ctx.service.subProjPermission.tableName, updateData);
+            }
+            return await this.db.delete(this.tableName, { id: ids });
         }
 
-        async updatePermission(updateData) {
-            if (!updateData.id) {
+        async updatePermission(options, updateData) {
+            if (!updateData.uid) {
                 return false;
             }
-            return await this.db.update(this.tableName, updateData);
-        }
-
-        async checkPermission(options, uid) {
-            if (this.ctx.session.sessionUser.is_admin) {
-                return true;
+            if (options.spid) {
+                const spAudit = await this.ctx.service.subProjPermission.getDataByCondition({ spid: options.spid, uid: updateData.uid });
+                if (!spAudit) {
+                    return false;
+                }
+                const newContractPermission = await this.ctx.service.subProjPermission.getNewContractPermission(spAudit.contract_permission, updateData);
+                return await this.db.update(this.ctx.service.subProjPermission.tableName, { id: spAudit.id, contract_permission: newContractPermission });
             }
-            let flag = false;
-            const cloneOptions = this._.cloneDeep(options);
-            cloneOptions.uid = uid;
-            const info = await this.getDataByCondition(cloneOptions);
-            if (info) {
-                flag = true;
+            const contractAudit = await this.getDataByCondition({ tid: options.tid, uid: updateData.uid });
+            if (!contractAudit) {
+                return false;
             }
-            return flag;
+            updateData.id = contractAudit.id;
+            return await this.db.update(this.tableName, updateData);
         }
 
         async getUserPermissionEdit(options, uid) {

+ 126 - 5
app/service/sub_proj_permission.js

@@ -51,7 +51,7 @@ module.exports = app => {
                     add: { title: '添加合同', value: 2 },
                     node: { title: '授权查看本节点合同', value: 3 },
                     unit: { title: '授权查看本单位合同', value: 4 },
-
+                    view: { title: '查看所有合同', value: 5 },
                 },
                 fund_trans: {
                     view: { title: '查看', value: 1 },
@@ -66,7 +66,13 @@ module.exports = app => {
             this.PermissionBlock = [
                 { key: 'datacollect', name: '决策大屏', field: 'datacollect_permission' },
                 { key: 'info', name: '项目概况', field: 'info_permission' },
-                { key: 'contract', name: '合同管理', field: 'contract_permission', hint: ['1、编辑节点:编辑合同管理内页树结构', '2、添加合同:允许添加合同', '3、授权查看本节点合同:授权节点下查看所有人上传的合同', '4、授权查看本单位合同:授权节点下查看本单位人员添加的所有合同'] },
+                { key: 'contract', name: '合同管理', field: 'contract_permission', hint: ['1、编辑节点:编辑合同管理内页树结构',
+                        '2、添加合同:允许添加合同',
+                        '3、授权查看本节点合同:授权节点下查看所有人上传的合同',
+                        '4、授权查看本单位合同:授权节点下查看本单位人员添加的所有合同',
+                        '5、查看所有合同:查看所有合同,包括其他单位人员添加的合同',
+                        '注:查看合同第3、4、5必须选择其一,否则无法查看本项目合同管理',
+                    ] },
                 { key: 'file', name: '资料归集', field: 'file_permission' },
                 { key: 'budget', name: '动态投资', field: 'budget_permission' },
                 {
@@ -246,7 +252,8 @@ module.exports = app => {
         async _updateUserPermission(data) {
             const datas = data instanceof Array ? data : [data];
             const updateData = [];
-            datas.forEach(x => {
+            // const contractData = [];
+            for (const x of datas) {
                 const ud = { id: x.id };
                 for (const p of this.PermissionBlock) {
                     if (p.children) {
@@ -255,11 +262,65 @@ module.exports = app => {
                         }
                     } else {
                         if (x[p.field] !== undefined) ud[p.field] = x[p.field] || '';
+                        // if (p.field === 'contract_permission') {
+                        //     const spAudit = await this.getDataById(x.id);
+                        //     if (spAudit) {
+                        //         const contractAudit = await this.ctx.service.contractAudit.getDataByCondition({ spid: spAudit.spid, uid: spAudit.uid });
+                        //         const contractPermission = x.contract_permission ? this._.map(x.contract_permission.split(','), this._.toInteger) : [];
+                        //         const newContractPermission = contractPermission.length > 0 ? await this.getContractPermission(contractPermission) : [];
+                        //         console.log(newContractPermission, contractAudit);
+                        //         if (!contractAudit && contractPermission.length === 0) continue;
+                        //         if (contractAudit) {
+                        //             if (contractPermission.length === 0 || this._.intersection([3,4,5], contractPermission).length === 0) {
+                        //                 contractData.push({ delete: { id: contractAudit.id }});
+                        //             } else if (contractAudit.permission_add !== newContractPermission.permission_add ||
+                        //                 contractAudit.permission_edit !== newContractPermission.permission_edit ||
+                        //                 contractAudit.permission_show_unit !== newContractPermission.permission_show_unit ||
+                        //                 contractAudit.permission_show_node !== newContractPermission.permission_show_node) {
+                        //                 contractData.push({ update: { id: contractAudit.id,
+                        //                     permission_add: newContractPermission.permission_add,
+                        //                     permission_edit: newContractPermission.permission_edit,
+                        //                     permission_show_unit: newContractPermission.permission_show_unit,
+                        //                     permission_show_node: newContractPermission.permission_show_node,
+                        //                 }});
+                        //             }
+                        //         } else if (!contractAudit && contractPermission.length > 0) {
+                        //             contractData.push({ add: {
+                        //                 spid: spAudit.spid,
+                        //                 tid: null,
+                        //                 uid: spAudit.uid,
+                        //                 permission_add: newContractPermission.permission_add,
+                        //                 permission_edit: newContractPermission.permission_edit,
+                        //                 permission_show_unit: newContractPermission.permission_show_unit,
+                        //                 permission_show_node: newContractPermission.permission_show_node,
+                        //                 create_time: new Date(),
+                        //             }});
+                        //         }
+                        //     }
+                        // }
                     }
                 }
                 updateData.push(ud);
-            });
-            await this.db.updateRows(this.tableName, updateData);
+            }
+            const conn = await this.db.beginTransaction();
+            try {
+                // if (contractData.length > 0) {
+                //     for (const d of contractData) {
+                //         if (d.add) {
+                //             await conn.insert(this.ctx.service.contractAudit.tableName, d.add);
+                //         } else if (d.update) {
+                //             await conn.update(this.ctx.service.contractAudit.tableName, d.update);
+                //         } else if (d.delete) {
+                //             await conn.delete(this.ctx.service.contractAudit.tableName, d.delete);
+                //         }
+                //     }
+                // }
+                await conn.updateRows(this.tableName, updateData);
+                await conn.commit();
+            } catch(err) {
+                await conn.rollback();
+                throw err;
+            }
             return updateData;
         }
 
@@ -308,6 +369,11 @@ module.exports = app => {
                     if (!viewPermission || ctx.subProject.permission[c.field].indexOf(viewPermission.value) >= 0) canView = true;
                 }
                 return canView;
+            } else if (ctx.controllerName === 'contract') {
+                if (ctx.url.indexOf('contract/tender') >= 0) return true;
+                const contractViewPermission = this._.map(permissionBlock.permission.filter(x => { return ['view', 'unit', 'node'].indexOf(x.key) >= 0; }), 'value');
+                if (!contractViewPermission) return true;
+                return this._.intersection(ctx.subProject.permission[permissionBlock.field], contractViewPermission).length > 0;
             } else {
                 const viewPermission = permissionBlock.permission.find(x => { return x.key === 'view'; });
                 if (!viewPermission) return true;
@@ -315,6 +381,61 @@ module.exports = app => {
             }
         };
 
+        async getContractAuditList(spid, uid = null) {
+            const uidSql = uid ? 'AND uid in (' + uid.join(',') + ')' : '';
+            const sql = `SELECT * FROM ?? WHERE spid = ? AND contract_permission <> ''` + uidSql;
+            const sqlParams = [this.tableName, spid];
+            const result = await this.db.query(sql, sqlParams);
+            const list = [];
+            for (const r of result) {
+                const permission = await this.getContractPermission(this._.map(r.contract_permission.split(','), this._.toInteger));
+                list.push({
+                    id: r.id,
+                    spid: r.spid,
+                    tid: null,
+                    uid: r.uid,
+                    permission_add: permission.permission_add,
+                    permission_edit: permission.permission_edit,
+                    permission_show_unit: permission.permission_show_unit,
+                    permission_show_node: permission.permission_show_node,
+                });
+            }
+            return list;
+        }
+
+        async getNewContractPermission(permission, newContractPermission) {
+            const oldPermission = await this.getContractPermission(this._.map(permission.split(','), this._.toInteger));
+            if (newContractPermission.permission_add !== undefined) {
+                oldPermission.permission_add = newContractPermission.permission_add;
+            }
+            if (newContractPermission.permission_edit !== undefined) {
+                oldPermission.permission_edit = newContractPermission.permission_edit;
+            }
+            if (newContractPermission.permission_show_unit !== undefined) {
+                oldPermission.permission_show_unit = newContractPermission.permission_show_unit;
+            }
+            if (newContractPermission.permission_show_node !== undefined) {
+                oldPermission.permission_show_node = newContractPermission.permission_show_node;
+            }
+            const permissionArr = [];
+            if (oldPermission.permission_edit) permissionArr.push(1);
+            if (oldPermission.permission_add) permissionArr.push(2);
+            if (oldPermission.permission_show_unit) permissionArr.push(3);
+            if (oldPermission.permission_show_node) permissionArr.push(4);
+            if (!oldPermission.permission_show_unit && !oldPermission.permission_show_node) permissionArr.push(5);
+            return permissionArr.join(',');
+        }
+
+        async getContractPermission(cp) {
+            const permission = {
+                permission_edit: cp.indexOf(1) !== -1 ? 1: 0,
+                permission_add: cp.indexOf(2) !== -1 ? 1: 0,
+                permission_show_unit: cp.indexOf(3) !== -1 ? 1: 0,
+                permission_show_node: cp.indexOf(4) !== -1 ? 1: 0,
+            };
+            return permission;
+        }
+
         async getFinancailPermission(trans_permission, pay_permission) {
             const permission = {
                 transfer_show: trans_permission.indexOf(1) !== -1,

+ 1 - 1
app/view/contract/detail.ejs

@@ -35,7 +35,7 @@
             <% } %>
             <div class="ml-auto">
                 <% if (ctx.session.sessionUser.is_admin) { %>
-                <a href="javascript:void(0);" data-stid="<%- ctx.contractOptions.spid || ctx.contractOptions.tid %>" class="btn btn-sm btn-primary get-audits mr-2">成员管理</a>
+                <a href="javascript:void(0);" data-stid="<%- ctx.contract_tender ? ctx.contractOptions.tid : '' %>" class="btn btn-sm btn-primary get-audits mr-2">成员管理</a>
                 <a href="#empower" data-toggle="modal" data-target="#empower" class="btn btn-sm btn-primary mr-2">节点授权</a>
                 <% } %>
 <!--                <a href="#cons-relat" data-toggle="modal" data-target="#cons-relat" class="btn btn-primary btn-sm pull-right">关联合同</a>-->

+ 16 - 17
app/view/contract/modal.ejs

@@ -175,12 +175,13 @@
         $('body').on('click', '#authority-list dl dd', function () {
             const id = parseInt($(this).data('id'));
             if (!isNaN(id) && id !== 0) {
-                postData(`/sp/${spid}/contract/tender/${$('#stid').val()}/audit/save`, {type: 'add-audit', id: id}, function (result) {
+                postData(auditSaveUrl, {type: 'add-audit', id: id}, function (result) {
                     setList(result);
                 })
             }
         });
         let first = 1;
+        let auditSaveUrl = '';
         $('#authority-list').on('shown.bs.modal', function () {
             if (first) {
                 const option = {
@@ -190,18 +191,16 @@
                 $("#contract-audit-table").bootstrapTable('destroy').bootstrapTable(option);
                 first = 0;
             }
-            const stid = $('#stid').val();
-            if (stid) {
-                postData(`/sp/${spid}/contract/tender/${$('#stid').val()}/audit/save`, { type: 'list' }, function (result) {
-                    setList(result);
-                });
-            }
+            postData(auditSaveUrl, { type: 'list' }, function (result) {
+                setList(result);
+            });
         });
         $('body').on('click', '.get-audits', function () {
             const stid = $(this).data('stid');
             $('#stid').val(stid);
+            auditSaveUrl = stid ? `/sp/${spid}/contract/tender/${stid}/audit/save`: `/sp/${spid}/contract/audit/save`;
             $('#contract-audit-list').html('');
-            postData(`/sp/${spid}/contract/tender/${$('#stid').val()}/audit/save`, { type: 'check' }, function (result) {
+            postData(auditSaveUrl, { type: 'check' }, function (result) {
                 $('#authority-list').modal('show');
             });
         });
@@ -213,19 +212,19 @@
                             <td>${ca.name}</td>
                             <td>${ca.role}</td>
                             <td>
-                                <input type="checkbox" class="permission-checkbox" data-type="permission_edit" value="${ca.id}" ${ca.permission_edit ? 'checked' : ''}>
+                                <input type="checkbox" class="permission-checkbox" data-type="permission_edit" value="${ca.uid}" ${ca.permission_edit ? 'checked' : ''}>
                             </td>
                             <td>
-                                <input type="checkbox" class="permission-checkbox" data-type="permission_add" value="${ca.id}" ${ca.permission_add ? 'checked' : ''}>
+                                <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_show_unit" value="${ca.id}" ${ca.permission_show_unit ? 'checked' : ''}>
+                                <input type="checkbox" class="permission-checkbox" data-type="permission_show_unit" value="${ca.uid}" ${ca.permission_show_unit ? 'checked' : ''}>
                             </td>
                             <td>
-                                <input type="checkbox" class="permission-checkbox" data-type="permission_show_node" value="${ca.id}" ${ca.permission_show_node ? 'checked' : ''}>
+                                <input type="checkbox" class="permission-checkbox" data-type="permission_show_node" value="${ca.uid}" ${ca.permission_show_node ? 'checked' : ''}>
                             </td>
                             <td>
-                                <a href="#del-contract-audit" data-toggle="modal" data-target="#del-contract-audit" class="btn btn-outline-danger btn-sm ml-1 del-contract-audit-a" data-id="${ca.id}">移除</a>
+                                <a href="#del-contract-audit" data-toggle="modal" data-target="#del-contract-audit" class="btn btn-outline-danger btn-sm ml-1 del-contract-audit-a" data-id="${ca.uid}">移除</a>
                             </td>
                         </tr>`;
             }
@@ -240,7 +239,7 @@
 
         $('#del-audit-btn').click(function () {
             let uids = $('#del-audit-ids').val();
-            postData(`/sp/${spid}/contract/tender/${$('#stid').val()}/audit/save`, { type: 'del-audit', id: uids.split(',') }, function (result) {
+            postData(auditSaveUrl, { type: 'del-audit', id: uids.split(',') }, function (result) {
                 // toastr.success(`成功添加 位用户`);
                 $('#del-contract-audit').modal('hide');
                 setList(result);
@@ -251,10 +250,10 @@
         $('body').on('click', '.permission-checkbox', function () {
             const type = $(this).attr('data-type');
             const value = $(this).is(':checked') ? 1 : 0;
-            const id = parseInt($(this).val());
-            const updateInfo = { id };
+            const uid = parseInt($(this).val());
+            const updateInfo = { uid };
             updateInfo[type] = value;
-            postData(`/sp/${spid}/contract/tender/${$('#stid').val()}/audit/save`, { type: 'save-permission', updateData: updateInfo }, function (result) {
+            postData(auditSaveUrl, { type: 'save-permission', updateData: updateInfo }, function (result) {
             })
         });
     });

+ 1 - 1
app/view/sp_setting/user_modal.ejs

@@ -77,7 +77,7 @@
                                     <% for (const p of pb.permission) { %>
                                     <div class="col-md-3">
                                         <div class="form-check">
-                                            <input class="form-check-input" type="checkbox" name="permission-check" id="icb-<%- pb.key %>-<%p.value%>" ptype="<%- pb.key %>" pvalue="<%- p.value %>">
+                                            <input class="form-check-input" type="checkbox" name="permission-check" id="icb-<%- pb.key %>-<%- p.value %>" ptype="<%- pb.key %>" pvalue="<%- p.value %>">
                                             <label class="form-check-label" for="icb-<%- pb.key %>-<%- p.value %>"><%- p.title %></label>
                                         </div>
                                     </div>

+ 38 - 3
db_script/sub_project_permission_financial.js

@@ -20,7 +20,7 @@ const getInsertSql = function (tableName, data) {
     }
     return [`INSERT INTO ${tableName} (${column.join(',')}) VALUES (${query.join(',')})`, value];
 };
-
+console.log('Copy sub_project_permission properties: fund_trans, fund_pay, contract');
 const doComplete = async function(spid) {
     try {
         const filter = spid ? ` where spid = '${spid}'` : '';
@@ -49,7 +49,7 @@ const doComplete = async function(spid) {
                     fund_pay_permission.push(3);
                 }
                 if (fund_trans_permission.length > 0 || fund_pay_permission.length > 0) {
-                    console.log('Copy sub_project_permission: ' + a.uid + ' ' + a.spid + ' ');
+                    console.log('Copy sub_project_permission_financial: ' + a.uid + ' ' + a.spid + ' ');
                     if (existSubProjPermission.length === 0) {
                         const sp_permission = { id: uuid.v4(), spid: existSubProj[0].id, pid: existSubProj[0].project_id, uid: a.uid, fund_trans_permission: fund_trans_permission.length > 0 ? fund_trans_permission.join(',') : '', fund_pay_permission: fund_pay_permission.length > 0 ? fund_pay_permission.join(',') : '' };
                         const [spSql, spSqlParam] = getInsertSql('zh_sub_project_permission', sp_permission);
@@ -59,8 +59,43 @@ const doComplete = async function(spid) {
                     }
                 }
             }
-            console.log('END Update;');
         }
+        const contractAudits = await querySql(`Select * From zh_contract_audit ${filter ? filter + ' and' : 'where'} tid is NULL`);
+        for (const a of contractAudits) {
+            const existSubProj = await querySql('SELECT * FROM zh_sub_project where id = ? and is_folder = 0 and is_delete = 0;', [a.spid]);
+            if (existSubProj.length === 0) {
+                continue;
+            } else {
+                const existSubProjPermission = await querySql('SELECT * FROM zh_sub_project_permission WHERE spid = ? and uid = ?', [existSubProj[0].id, a.uid]);
+                const contract_permission = [];
+                if (a.permission_add) {
+                    contract_permission.push(2);
+                }
+                if (a.permission_edit) {
+                    contract_permission.push(1);
+                }
+                if (a.permission_show_unit) {
+                    contract_permission.push(3);
+                }
+                if (a.permission_show_node) {
+                    contract_permission.push(4);
+                }
+                if (!a.permission_show_node && !a.permission_show_unit) {
+                    contract_permission.push(5);
+                }
+                if (contract_permission > 0) {
+                    console.log('Copy sub_project_permission_contract: ' + a.uid + ' ' + a.spid + ' ');
+                    if (existSubProjPermission.length === 0) {
+                        const sp_permission = { id: uuid.v4(), spid: existSubProj[0].id, pid: existSubProj[0].project_id, uid: a.uid, contract_permission: contract_permission.length > 0 ? contract_permission.join(',') : '' };
+                        const [spSql, spSqlParam] = getInsertSql('zh_sub_project_permission', sp_permission);
+                        await querySql(spSql, spSqlParam);
+                    } else {
+                        await querySql('Update zh_sub_project_permission SET contract_permission = ? WHERE id = ?; ', [contract_permission.length > 0 ? contract_permission.join(',') : '', existSubProjPermission[0].id]);
+                    }
+                }
+            }
+        }
+        console.log('END Update;');
     } catch (err) {
         console.log(err);
     }