Преглед на файлове

feature: 员工管理中,员工部门和职位改为多选

eyes4 преди 6 месеца
родител
ревизия
198f0dac03

+ 4 - 7
pmr-biz-manager/src/routes/api/biz/customer/stat.ts

@@ -1,16 +1,14 @@
 import {IApiProcessor, ICachedData, IMethodParams, IRequest} from "@core/Defined";
 import {Resp} from "@util/Resp";
-import {QueryTypes, WhereOptions} from "sequelize";
-import DataCURD from "@core/DataCURD";
+import {QueryTypes} from "sequelize";
 import {BizCustomer} from "@core-models/BizCustomer";
 import {BizCustomerLevel} from "@core-models/BizCustomerLevel";
 
-function stat(json: IRequest, params: IMethodParams, cached_data: ICachedData): Promise<any> {
+function stat(json: IRequest, params: IMethodParams, _cached_data: ICachedData): Promise<any> {
     return new Promise<any>(async (resolve, reject) => {
         try {
-
             let stat = await BizCustomer.sequelize!.query(`
-                select level.name, count(c.id), '个' as unit
+                select level.name, count(c.id) as value, '个' as unit
                 from ${BizCustomerLevel.table_name} level
                 left join ${BizCustomer.table_name} c on level.id = c.level_id
                 group by level.name, level.order_index
@@ -18,8 +16,7 @@ function stat(json: IRequest, params: IMethodParams, cached_data: ICachedData):
             `, {type: QueryTypes.SELECT, raw: true})
             if(!stat) return reject(Resp.gen_err(Resp.ResourceNotFound));
             // let result = DataCURD.filter_null(stat[0]);
-            let result = stat;
-            resolve({list: result});
+            resolve({list: stat});
         } catch (e) {
             reject(Resp.throw_err(e));
         }

+ 39 - 24
pmr-biz-manager/src/routes/api/cfg/staff/add.ts

@@ -9,7 +9,7 @@ interface IData {
     /**
      * 部门id,为空时直接放在公司一级下
      */
-    domain_id?: number;
+    domain_ids: number[];
     /**
      * 邮箱
      */
@@ -35,17 +35,20 @@ interface IData {
      */
     pass: string;
     /**
-     * 角色id
+     * 职位id
      */
-    role_id?: string;
+    role_ids: string[];
 }
 
 
 
+
 function add(json: IRequest, _params: IMethodParams, cached_data: ICachedData): Promise<any> {
     return new Promise<unknown>(async (resolve, reject) => {
         let data = <IData>json.data;
-        if (data.domain_id === undefined) data.domain_id = 1000;
+        let domain_ids: number[] = [];
+        if (data.domain_ids === undefined) domain_ids.push(1000);
+        else domain_ids = data.domain_ids;
 
         let t = await AcsUserInfo.sequelize!.transaction();
         try {
@@ -68,10 +71,13 @@ function add(json: IRequest, _params: IMethodParams, cached_data: ICachedData):
                 ext_info: {full_range: data.full_range, level: data.level}
             }, {transaction: t});
 
-            await AcsUserDomain.create({
-                user_id: data.mobile,
-                domain_id: data.domain_id,
-            }, {transaction: t});
+            for (let i = 0; i < domain_ids.length; i++) {
+                await AcsUserDomain.create({
+                    user_id: data.mobile,
+                    domain_id: domain_ids[i],
+                }, {transaction: t});
+            }
+
             await AcsUserDomain.create({
                 user_id: data.mobile,
                 domain_id: 100,
@@ -81,10 +87,12 @@ function add(json: IRequest, _params: IMethodParams, cached_data: ICachedData):
                 domain_id: 4,
             }, {transaction: t});
 
-            await AcsUserRole.upsert({
-                user_id: data.mobile,
-                role_id: data.role_id
-            }, {transaction: t});
+            for (let i = 0; i < data.role_ids.length; i++) {
+                await AcsUserRole.upsert({
+                    user_id: data.mobile,
+                    role_id: data.role_ids[i]
+                }, {transaction: t});
+            }
 
             await t.commit();
             resolve({});
@@ -106,11 +114,6 @@ const v1_0: IApiProcessor = {
                         "type": "string",
                         "title": "员工名称"
                     },
-                    "domain_id": {
-                        "type": "integer",
-                        "title": "部门id",
-                        "description": "为空时直接放在公司一级下"
-                    },
                     "mobile": {
                         "type": "string",
                         "title": "手机号",
@@ -139,26 +142,38 @@ const v1_0: IApiProcessor = {
                         "description": "默认0,越大级别越高",
                         "minimum": 0
                     },
-                    "role_id": {
-                        "type": "string",
-                        "title": "角色id"
+                    "role_ids": {
+                        "type": "array",
+                        "items": {
+                            "type": "string"
+                        },
+                        "title": "职位id"
+                    },
+                    "domain_ids": {
+                        "type": "array",
+                        "items": {
+                            "type": "integer"
+                        },
+                        "title": "部门id",
+                        "description": "为空时直接放在公司一级下"
                     }
                 },
                 "x-apifox-orders": [
                     "name",
-                    "domain_id",
+                    "role_ids",
+                    "domain_ids",
                     "mobile",
                     "email",
                     "pass",
                     "full_range",
-                    "level",
-                    "role_id"
+                    "level"
                 ],
                 "required": [
                     "name",
                     "mobile",
                     "pass",
-                    "role_id"
+                    "role_ids",
+                    "domain_ids"
                 ],
                 "title": "请求参数内容"
             },

+ 6 - 6
pmr-biz-manager/src/routes/api/cfg/staff/get_list.ts

@@ -45,7 +45,7 @@ export function get(json: IRequest, params: IMethodParams, cachedData: ICachedDa
             let count_sql = `
                 select count(distinct staff.id) 
                 from ${AcsUserInfo.table_name} staff, ${AcsUserDomain.table_name} user_domain, ${AcsDomain.table_name} domain
-                where staff.id = user_domain.user_id and user_domain.domain_id = domain.id and domain.path <@ '1.3.1000'
+                where staff.id = user_domain.user_id and user_domain.domain_id = domain.id and domain.path <@ '1.3.1000' and domain.category='org'
                 `;
             let select_sql = `
                select distinct staff.id,
@@ -57,16 +57,16 @@ export function get(json: IRequest, params: IMethodParams, cachedData: ICachedDa
                    COALESCE(staff.ext_info -> 'level', '0')::integer                        as level,
                    TO_CHAR(staff.reg_time, 'yyyy-MM-dd HH24' || ':' || 'MI' || ':' || 'ss') as reg_time,
                    TO_CHAR(staff.act_time, 'yyyy-MM-dd HH24' || ':' || 'MI' || ':' || 'ss') as act_time,
-                   array_agg(distinct domain.id) as domain_id,
-                   substring(array_agg(distinct domain.name)::text from 2 for char_length(array_agg(distinct domain.name)::text)-2) as domain_name,
-                   array_agg(distinct role_id) as role_id,
-                   substring(array_agg(distinct role.name)::text from 2 for char_length(array_agg(distinct role.name)::text)-2) as role_name
+                   array_agg(distinct domain.id) as domain_ids,
+                   substring(array_agg(distinct domain.name)::text from 2 for char_length(array_agg(distinct domain.name)::text)-2) as domain_names,
+                   array_agg(distinct role_id) as role_ids,
+                   substring(array_agg(distinct role.name)::text from 2 for char_length(array_agg(distinct role.name)::text)-2) as role_names
                 from ${AcsUserInfo.table_name} staff
                 left join tb_acs_user_domain user_domain on staff.id = user_domain.user_id
                 left join tb_acs_domain domain on user_domain.domain_id = domain.id
                 left join tb_acs_user_role user_role on staff.id = user_role.user_id
                 left join tb_acs_role role on user_role.role_id = role.id
-                where domain.path <@ '1.3.1000'
+                where domain.path <@ '1.3.1000' and domain.category='org'
             `;
             let conditions = ` `;
             let replacements: ISQLReplacements = {};

+ 49 - 30
pmr-biz-manager/src/routes/api/cfg/staff/modify.ts

@@ -1,15 +1,17 @@
 import {IApiProcessor, ICachedData, IMethodParams, IRequest} from "@core/Defined";
 import {AcsUserInfo} from "@core-models/AcsUserInfo";
-import {Op, Sequelize} from "sequelize";
+import {QueryTypes} from "sequelize";
 import {Resp} from "@util/Resp";
 import DataCURD from "@core/DataCURD";
 import {AcsUserDomain} from "@core-models/AcsUserDomain";
 import {AcsUserRole} from "@core-models/AcsUserRole";
+import {AcsDomain} from "@core-models/AcsDomain";
+
 interface IData {
     /**
      * 部门id
      */
-    domain_id?: number;
+    domain_ids?: number[];
     /**
      * 邮箱号
      */
@@ -39,16 +41,15 @@ interface IData {
      */
     pass?: string;
     /**
-     * 角色id
+     * 职位id
      */
-    role_id?: string;
+    role_ids?: string[];
     /**
      * 状态,0=锁定,1=正常
      */
     status?: number;
 }
 
-
 function get_where(json: IRequest, _params: IMethodParams, _cached_data: ICachedData): Promise<any> {
     return new Promise<any>(async (resolve, reject) => {
         try {
@@ -67,10 +68,10 @@ function modify(json: IRequest, params: IMethodParams, cached_data: ICachedData)
             let data = <IData>json.data;
             let staff = await AcsUserInfo.findOne({where:{id: data.id}, transaction: t});
             if (!staff) throw Resp.gen_err(Resp.ResourceNotFound);
-            data.name? staff.name = data.name : null;
-            data.memo? staff.memo = data.memo: null;
-            data.email? staff.email = data.email: null;
-            data.pass? staff.pass =data.pass: null;
+            // data.name? staff.name = data.name : null;
+            // data.memo? staff.memo = data.memo: null;
+            // data.email? staff.email = data.email: null;
+            // data.pass? staff.pass =data.pass: null;
 
 
             let ext_info: any = {
@@ -78,20 +79,32 @@ function modify(json: IRequest, params: IMethodParams, cached_data: ICachedData)
                 level: data.level,
             }
             ext_info = DataCURD.filter_null(ext_info);
-            staff.ext_info = {
+            ext_info = {
                 ...staff.ext_info,
                 ...ext_info
             }
-            if (data.role_id) {
-                await AcsUserRole.upsert({
-                    user_id: data.id,
-                    role_id: data.role_id
-                }, {transaction: t, returning: false})
+            await AcsUserInfo.update({...staff, ...data, ext_info: ext_info}, {where: {id: data.id}, transaction: t, returning: false});
+            if (data.role_ids) {
+                await AcsUserRole.destroy({where: {user_id: data.id}, transaction: t});
+                for (let role_id of data.role_ids) {
+                    await AcsUserRole.create({
+                        user_id: data.id,
+                        role_id: role_id
+                    }, {transaction: t, returning: false})
+                }
             }
 
-            await staff.save({transaction: t});
-            if (data.domain_id !== undefined) {
-                await AcsUserDomain.update({domain_id: data.domain_id}, {where: {user_id: data.id}, transaction: t, returning: []});
+            //await staff.save({transaction: t});
+            if (data.domain_ids !== undefined) {
+                await AcsUserDomain.sequelize!.query(`
+                    delete from ${AcsUserDomain.tableName} where user_id = :user_id and domain_id in (select id from ${AcsDomain.tableName} where category='org')
+                `, {type: QueryTypes.DELETE, transaction: t});
+                for (let domain_id of data.domain_ids) {
+                    await AcsUserDomain.create({user_id: data.id, domain_id: domain_id}, {
+                        transaction: t,
+                        returning: false
+                    });
+                }
             }
 
             await t.commit();
@@ -127,10 +140,6 @@ const v1_0: IApiProcessor = {
                         "type": "string",
                         "title": "备注"
                     },
-                    "domain_id": {
-                        "type": "integer",
-                        "title": "部门id"
-                    },
                     "status": {
                         "type": "integer",
                         "title": "状态",
@@ -150,9 +159,19 @@ const v1_0: IApiProcessor = {
                         "type": "integer",
                         "title": "级别"
                     },
-                    "role_id": {
-                        "type": "string",
-                        "title": "角色id"
+                    "domain_ids": {
+                        "type": "array",
+                        "items": {
+                            "type": "integer"
+                        },
+                        "title": "部门id"
+                    },
+                    "role_ids": {
+                        "type": "array",
+                        "items": {
+                            "type": "string"
+                        },
+                        "title": "职位id"
                     }
                 },
                 "x-apifox-orders": [
@@ -160,12 +179,12 @@ const v1_0: IApiProcessor = {
                     "name",
                     "email",
                     "memo",
-                    "domain_id",
+                    "role_ids",
+                    "domain_ids",
                     "status",
                     "pass",
                     "full_range",
-                    "level",
-                    "role_id"
+                    "level"
                 ],
                 "required": [
                     "id"
@@ -188,7 +207,7 @@ const v1_0: IApiProcessor = {
                     },
                     {
                         "required": [
-                            "domain_id"
+                            "domain_ids"
                         ]
                     },
                     {
@@ -213,7 +232,7 @@ const v1_0: IApiProcessor = {
                     },
                     {
                         "required": [
-                            "role_id"
+                            "role_ids"
                         ]
                     }
                 ],

+ 2 - 0
pmr-biz-manager/src/routes/api/prj/plan/set_progress.ts

@@ -71,6 +71,8 @@ function set_progress(json: IRequest, params: IMethodParams, cached_data: ICache
             if (data.progress === 100) {    // 不能直接设置任务完成度为100%,因为还有一个审核流程
                 data.progress = 99;
             }
+
+            // 如果条件正确的话,开启任务审核流程,第一个工作项是"提交审核"
             await create_task_approve_flow_if_not_exists(task.prj_id, cached_data.user_id, data.task_id, t);
 
             let result = await PrjPlanTask.update({progress: data.progress, status: status}, {

+ 9 - 8
pmr-biz-manager/src/utils/bpmn_work_helper.ts

@@ -5,7 +5,7 @@ import {PrjInfo} from "@core-models/PrjInfo";
 import {PrjPlanTaskDraft} from "@core-models/PrjPlanTaskDraft";
 import {PrjTaskOutcome} from "@core-models/PrjTaskOutcome";
 import {PrjTaskOutcomeDraft} from "@core-models/PrjTaskOutcomeDraft";
-import {QueryTypes, Sequelize, Transaction} from "sequelize";
+import {QueryTypes, Transaction} from "sequelize";
 import {ChangeMarker, TaskStatus} from "@src/utils/define";
 import {BpmnModel} from "@core-models/BpmnModel";
 import {FlowEngine} from "@src/bpmn/flow_engine";
@@ -23,7 +23,7 @@ export async function bpmn_flow_on_end(id: string, model_id: string, prj_id: str
             await PrjInfo.update({
                 phase_id: 'created',
                 started_at: dayjs().format('YYYY-MM-DD 00:00:00')
-            }, {where: {id: prj_id}});
+            }, {where: {id: prj_id}, returning: false});
             await PrjLogger.log({
                 creator_id: owner,
                 creator_name: user_name,
@@ -32,7 +32,7 @@ export async function bpmn_flow_on_end(id: string, model_id: string, prj_id: str
             });
             break;
         case 'plan':
-            await PrjInfo.update({phase_id: 'doing'}, {where: {id: prj_id}});
+            await PrjInfo.update({phase_id: 'doing'}, {where: {id: prj_id}, returning: false});
             await PrjPlanTask.increment({version: 1}, {where: {prj_id: prj_id}});
             await PrjLogger.log({
                 creator_id: owner,
@@ -44,14 +44,14 @@ export async function bpmn_flow_on_end(id: string, model_id: string, prj_id: str
         case 'plan_alter':
             let t = await PrjPlanTask.sequelize!.transaction();
             try {
-                await PrjInfo.update({phase_id: 'doing'}, {where: {id: prj_id}, transaction: t});
+                await PrjInfo.update({phase_id: 'doing'}, {returning: false, where: {id: prj_id}, transaction: t});
                 await PrjLogger.log({
                     creator_id: owner,
                     creator_name: user_name,
                     prj_id: prj_id,
                     content: `项目计划变更成功`,
                     t
-                });
+                }as any);
                 // 更新计划变更版本
                 await PrjPlanTaskDraft.increment({version: 1}, {
                     where: {prj_id: prj_id},
@@ -146,7 +146,8 @@ export async function bpmn_flow_on_end(id: string, model_id: string, prj_id: str
                     status: TaskStatus.Completed,
                     completed_at: dayjs().format('YYYY-MM-DD HH:mm:ss'),
                 }, {
-                    where: {id: flow_case.task_id}
+                    where: {id: flow_case.task_id},
+                    returning: false
                 });
                 await PrjLogger.log({
                     creator_id: owner,
@@ -166,11 +167,11 @@ export async function create_task_approve_flow_if_not_exists(prj_id: string, own
         where: {prj_id: prj_id, task_id: task_id, model_id: 'task'},
         transaction: t,
         raw: true
-    });
+    } as any);
     if (flow) return;
 
     // 如果审核人不存在,不开启流程
-    let task = await PrjPlanTask.findOne({where: {id: task_id}, transaction: t, raw: true});
+    let task = await PrjPlanTask.findOne({where: {id: task_id}, transaction: t, raw: true} as any);
     if (!task) return;
     let checkers = task.checkers;
     if (!checkers || checkers.length === 0) return;

+ 1 - 1
pmr-biz-manager/src/utils/prj_logger.ts

@@ -22,7 +22,7 @@ export class PrjLogger {
             content: info.content,
             prj_id: info.prj_id,
             task_id: info.task_id
-        }, {transaction: info.t});
+        }, {transaction: <any>info.t});
     }
 
     static async removed(info: IPrjLogInfo) {