mirror of
https://github.com/veops/cmdb.git
synced 2025-08-07 22:17:37 +08:00
前后端全面升级
This commit is contained in:
0
cmdb-api/api/lib/common_setting/__init__.py
Normal file
0
cmdb-api/api/lib/common_setting/__init__.py
Normal file
95
cmdb-api/api/lib/common_setting/acl.py
Normal file
95
cmdb-api/api/lib/common_setting/acl.py
Normal file
@@ -0,0 +1,95 @@
|
||||
# -*- coding:utf-8 -*-
|
||||
from flask import abort
|
||||
from flask import current_app
|
||||
|
||||
from api.lib.common_setting.resp_format import ErrFormat
|
||||
from api.lib.perm.acl.cache import RoleCache, AppCache
|
||||
from api.lib.perm.acl.role import RoleCRUD, RoleRelationCRUD
|
||||
from api.lib.perm.acl.user import UserCRUD
|
||||
|
||||
|
||||
class ACLManager(object):
|
||||
def __init__(self, app_name='acl', uid=None):
|
||||
self.log = current_app.logger
|
||||
self.app_name = app_name
|
||||
self.uid = uid
|
||||
|
||||
@staticmethod
|
||||
def get_all_users():
|
||||
try:
|
||||
numfound, users = UserCRUD.search(None, 1, 999999)
|
||||
users = [i.to_dict() for i in users]
|
||||
for u in users:
|
||||
u.pop('password', None)
|
||||
u.pop('key', None)
|
||||
u.pop('secret', None)
|
||||
return users
|
||||
except Exception as e:
|
||||
current_app.logger.error(str(e))
|
||||
raise Exception(ErrFormat.acl_get_all_users_failed.format(str(e)))
|
||||
|
||||
@staticmethod
|
||||
def create_user(payload):
|
||||
user = UserCRUD.add(**payload)
|
||||
return user.to_dict()
|
||||
|
||||
@staticmethod
|
||||
def edit_user(uid, payload):
|
||||
user = UserCRUD.update(uid, **payload)
|
||||
return user.to_dict()
|
||||
|
||||
def get_all_roles(self):
|
||||
numfound, roles = RoleCRUD.search(
|
||||
None, self.app_name, 1, 999999, True, True, False)
|
||||
return roles
|
||||
|
||||
def remove_user_from_role(self, user_rid, payload):
|
||||
app_id = self.app_name
|
||||
app = AppCache.get(app_id)
|
||||
if app and app.name == "acl":
|
||||
app_id = None # global
|
||||
|
||||
RoleRelationCRUD.delete2(
|
||||
payload.get('parent_id'), user_rid, app_id)
|
||||
return dict(
|
||||
message="success"
|
||||
)
|
||||
|
||||
def add_user_to_role(self, role_id, payload):
|
||||
app_id = self.app_name
|
||||
app = AppCache.get(self.app_name)
|
||||
if app and app.name == "acl":
|
||||
app_id = None
|
||||
role = RoleCache.get(role_id)
|
||||
res = RoleRelationCRUD.add(
|
||||
role, role_id, payload['child_ids'], app_id)
|
||||
return res
|
||||
|
||||
@staticmethod
|
||||
def create_role(payload):
|
||||
payload['is_app_admin'] = payload.get('is_app_admin', False)
|
||||
role = RoleCRUD.add_role(**payload)
|
||||
return role.to_dict()
|
||||
|
||||
@staticmethod
|
||||
def edit_role(_id, payload):
|
||||
role = RoleCRUD.update_role(_id, **payload)
|
||||
return role.to_dict()
|
||||
|
||||
@staticmethod
|
||||
def delete_role(_id, payload):
|
||||
RoleCRUD.delete_role(_id)
|
||||
return dict(rid=_id)
|
||||
|
||||
def get_user_info(self, username):
|
||||
from api.lib.perm.acl.acl import ACLManager as ACL
|
||||
user_info = ACL().get_user_info(username, self.app_name)
|
||||
result = dict(name=user_info.get('nickname') or username,
|
||||
username=user_info.get('username') or username,
|
||||
email=user_info.get('email'),
|
||||
uid=user_info.get('uid'),
|
||||
rid=user_info.get('rid'),
|
||||
role=dict(permissions=user_info.get('parents')),
|
||||
avatar=user_info.get('avatar'))
|
||||
|
||||
return result
|
24
cmdb-api/api/lib/common_setting/company_info.py
Normal file
24
cmdb-api/api/lib/common_setting/company_info.py
Normal file
@@ -0,0 +1,24 @@
|
||||
# -*- coding:utf-8 -*-
|
||||
|
||||
from api.models.common_setting import CompanyInfo
|
||||
|
||||
|
||||
class CompanyInfoCRUD(object):
|
||||
|
||||
@staticmethod
|
||||
def get():
|
||||
return CompanyInfo.get_by(first=True) or {}
|
||||
|
||||
@staticmethod
|
||||
def create(**kwargs):
|
||||
return CompanyInfo.create(**kwargs)
|
||||
|
||||
@staticmethod
|
||||
def update(_id, **kwargs):
|
||||
kwargs.pop('id', None)
|
||||
existed = CompanyInfo.get_by_id(_id)
|
||||
if not existed:
|
||||
return CompanyInfoCRUD.create(**kwargs)
|
||||
else:
|
||||
existed = existed.update(**kwargs)
|
||||
return existed
|
14
cmdb-api/api/lib/common_setting/const.py
Normal file
14
cmdb-api/api/lib/common_setting/const.py
Normal file
@@ -0,0 +1,14 @@
|
||||
from api.lib.common_setting.utils import BaseEnum
|
||||
|
||||
COMMON_SETTING_QUEUE = "common_setting_async"
|
||||
|
||||
|
||||
class OperatorType(BaseEnum):
|
||||
EQUAL = 1 # 等于
|
||||
NOT_EQUAL = 2 # 不等于
|
||||
IN = 3 # 包含
|
||||
NOT_IN = 4 # 不包含
|
||||
GREATER_THAN = 5 # 大于
|
||||
LESS_THAN = 6 # 小于
|
||||
IS_EMPTY = 7 # 为空
|
||||
IS_NOT_EMPTY = 8 # 不为空
|
435
cmdb-api/api/lib/common_setting/department.py
Normal file
435
cmdb-api/api/lib/common_setting/department.py
Normal file
@@ -0,0 +1,435 @@
|
||||
# -*- coding:utf-8 -*-
|
||||
|
||||
from flask import abort
|
||||
from treelib import Tree
|
||||
from wtforms import Form
|
||||
from wtforms import IntegerField
|
||||
from wtforms import StringField
|
||||
from wtforms import validators
|
||||
|
||||
from api.lib.common_setting.resp_format import ErrFormat
|
||||
from api.lib.common_setting.utils import get_df_from_read_sql
|
||||
from api.lib.perm.acl.role import RoleCRUD
|
||||
from api.models.common_setting import Department, Employee
|
||||
|
||||
sub_departments_column_name = 'sub_departments'
|
||||
|
||||
|
||||
def drop_ts_column(df):
|
||||
columns = list(df.columns)
|
||||
remove_columns = []
|
||||
for column in ['created_at', 'updated_at', 'deleted_at', 'last_login']:
|
||||
targets = list(filter(lambda c: c.startswith(column), columns))
|
||||
if targets:
|
||||
remove_columns.extend(targets)
|
||||
|
||||
remove_columns = list(set(remove_columns))
|
||||
|
||||
return df.drop(remove_columns, axis=1) if len(remove_columns) > 0 else df
|
||||
|
||||
|
||||
def get_department_df():
|
||||
criterion = [
|
||||
Department.deleted == 0,
|
||||
]
|
||||
query = Department.query.filter(
|
||||
*criterion
|
||||
)
|
||||
df = get_df_from_read_sql(query)
|
||||
if df.empty:
|
||||
return
|
||||
return drop_ts_column(df)
|
||||
|
||||
|
||||
def get_all_employee_df(block=0):
|
||||
criterion = [
|
||||
Employee.deleted == 0,
|
||||
]
|
||||
if block >= 0:
|
||||
criterion.append(
|
||||
Employee.block == block
|
||||
)
|
||||
|
||||
entities = [getattr(Employee, c) for c in Employee.get_columns(
|
||||
).keys() if c not in ['deleted', 'deleted_at']]
|
||||
query = Employee.query.with_entities(
|
||||
*entities
|
||||
).filter(
|
||||
*criterion
|
||||
)
|
||||
df = get_df_from_read_sql(query)
|
||||
if df.empty:
|
||||
return df
|
||||
return drop_ts_column(df)
|
||||
|
||||
|
||||
class DepartmentTree(object):
|
||||
def __init__(self, append_employee=False, block=-1):
|
||||
self.append_employee = append_employee
|
||||
self.block = block
|
||||
self.d_df = get_department_df()
|
||||
self.employee_df = get_all_employee_df(
|
||||
block) if append_employee else None
|
||||
|
||||
def prepare(self):
|
||||
pass
|
||||
|
||||
def get_employees_by_d_id(self, d_id):
|
||||
_df = self.employee_df[
|
||||
self.employee_df['department_id'].eq(d_id)
|
||||
].sort_values(by=['direct_supervisor_id'], ascending=True)
|
||||
if _df.empty:
|
||||
return []
|
||||
|
||||
if self.block != -1:
|
||||
_df = _df[
|
||||
_df['block'].eq(self.block)
|
||||
]
|
||||
|
||||
return _df.to_dict('records')
|
||||
|
||||
def get_tree_departments(self):
|
||||
# 一级部门
|
||||
top_df = self.d_df[self.d_df['department_parent_id'].eq(-1)]
|
||||
if top_df.empty:
|
||||
return []
|
||||
|
||||
d_list = []
|
||||
|
||||
for index in top_df.index:
|
||||
top_d = top_df.loc[index].to_dict()
|
||||
|
||||
department_id = top_d['department_id']
|
||||
|
||||
# 检查 department_id 是否作为其他部门的 parent
|
||||
sub_df = self.d_df[
|
||||
self.d_df['department_parent_id'].eq(department_id)
|
||||
].sort_values(by=['sort_value'], ascending=True)
|
||||
|
||||
employees = []
|
||||
|
||||
if self.append_employee:
|
||||
# 要包含员工
|
||||
employees = self.get_employees_by_d_id(department_id)
|
||||
|
||||
top_d['employees'] = employees
|
||||
|
||||
if sub_df.empty:
|
||||
top_d[sub_departments_column_name] = []
|
||||
d_list.append(top_d)
|
||||
continue
|
||||
|
||||
self.parse_sub_department(sub_df, top_d)
|
||||
d_list.append(top_d)
|
||||
|
||||
return d_list
|
||||
|
||||
def get_all_departments(self, is_tree=1):
|
||||
if self.d_df.empty:
|
||||
return []
|
||||
|
||||
if is_tree != 1:
|
||||
return self.d_df.to_dict('records')
|
||||
|
||||
return self.get_tree_departments()
|
||||
|
||||
def parse_sub_department(self, df, top_d):
|
||||
sub_departments = []
|
||||
for s_index in df.index:
|
||||
d = df.loc[s_index].to_dict()
|
||||
sub_df = self.d_df[
|
||||
self.d_df['department_parent_id'].eq(
|
||||
df.at[s_index, 'department_id'])
|
||||
].sort_values(by=['sort_value'], ascending=True)
|
||||
employees = []
|
||||
|
||||
if self.append_employee:
|
||||
# 要包含员工
|
||||
employees = self.get_employees_by_d_id(
|
||||
df.at[s_index, 'department_id'])
|
||||
|
||||
d['employees'] = employees
|
||||
|
||||
if sub_df.empty:
|
||||
d[sub_departments_column_name] = []
|
||||
sub_departments.append(d)
|
||||
continue
|
||||
|
||||
self.parse_sub_department(sub_df, d)
|
||||
sub_departments.append(d)
|
||||
|
||||
top_d[sub_departments_column_name] = sub_departments
|
||||
|
||||
|
||||
class DepartmentForm(Form):
|
||||
department_name = StringField(validators=[
|
||||
validators.DataRequired(message="部门名称不能为空"),
|
||||
validators.Length(max=255),
|
||||
])
|
||||
|
||||
department_director_id = IntegerField(validators=[], default=0)
|
||||
department_parent_id = IntegerField(validators=[], default=1)
|
||||
|
||||
|
||||
class DepartmentCRUD(object):
|
||||
|
||||
@staticmethod
|
||||
def add(**kwargs):
|
||||
DepartmentCRUD.check_department_name_unique(kwargs['department_name'])
|
||||
department_parent_id = kwargs.get('department_parent_id', 0)
|
||||
DepartmentCRUD.check_department_parent_id(department_parent_id)
|
||||
|
||||
DepartmentCRUD.check_department_parent_id_allow(
|
||||
-1, department_parent_id)
|
||||
|
||||
try:
|
||||
role = RoleCRUD.add_role(name=kwargs['department_name'])
|
||||
except Exception as e:
|
||||
return abort(400, ErrFormat.acl_add_role_failed.format(str(e)))
|
||||
|
||||
kwargs['acl_rid'] = role.id
|
||||
try:
|
||||
db_department = Department.create(
|
||||
**kwargs
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
return abort(400, str(e))
|
||||
|
||||
return db_department
|
||||
|
||||
@staticmethod
|
||||
def check_department_parent_id_allow(d_id, department_parent_id):
|
||||
if department_parent_id == 0:
|
||||
return
|
||||
# 检查 department_parent_id 是否在许可范围内
|
||||
allow_p_d_id_list = DepartmentCRUD.get_allow_parent_d_id_by(d_id)
|
||||
target = list(
|
||||
filter(lambda d: d['department_id'] == department_parent_id, allow_p_d_id_list))
|
||||
if len(target) == 0:
|
||||
try:
|
||||
d = Department.get_by(
|
||||
first=True, to_dict=False, department_id=department_parent_id)
|
||||
name = d.department_name if d else ErrFormat.department_id_not_found.format(department_parent_id)
|
||||
except Exception as e:
|
||||
name = ErrFormat.department_id_not_found.format(department_parent_id)
|
||||
abort(400, ErrFormat.cannot_to_be_parent_department.format(name))
|
||||
|
||||
@staticmethod
|
||||
def check_department_parent_id(department_parent_id):
|
||||
if int(department_parent_id) < 0:
|
||||
abort(400, ErrFormat.parent_department_id_must_more_than_zero)
|
||||
|
||||
@staticmethod
|
||||
def check_department_name_unique(name, _id=0):
|
||||
criterion = [
|
||||
Department.department_name == name,
|
||||
Department.deleted == 0,
|
||||
]
|
||||
if _id > 0:
|
||||
criterion.append(
|
||||
Department.department_id != _id
|
||||
)
|
||||
|
||||
res = Department.query.filter(
|
||||
*criterion
|
||||
).all()
|
||||
|
||||
res and abort(
|
||||
400, ErrFormat.department_name_already_exists.format(name)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def edit(_id, **kwargs):
|
||||
DepartmentCRUD.check_department_name_unique(
|
||||
kwargs['department_name'], _id)
|
||||
kwargs.pop('department_id', None)
|
||||
existed = Department.get_by(
|
||||
first=True, department_id=_id, to_dict=False)
|
||||
if not existed:
|
||||
abort(404, ErrFormat.department_id_not_found.format(_id))
|
||||
|
||||
department_parent_id = kwargs.get('department_parent_id', 0)
|
||||
DepartmentCRUD.check_department_parent_id(department_parent_id)
|
||||
if department_parent_id > 0:
|
||||
DepartmentCRUD.check_department_parent_id_allow(
|
||||
_id, department_parent_id)
|
||||
|
||||
try:
|
||||
RoleCRUD.update_role(
|
||||
existed.acl_rid, name=kwargs['department_name'])
|
||||
except Exception as e:
|
||||
return abort(400, ErrFormat.acl_update_role_failed.format(str(e)))
|
||||
|
||||
try:
|
||||
existed.update(**kwargs)
|
||||
except Exception as e:
|
||||
return abort(400, str(e))
|
||||
|
||||
@staticmethod
|
||||
def delete(_id):
|
||||
existed = Department.get_by(
|
||||
first=True, department_id=_id, to_dict=False)
|
||||
if not existed:
|
||||
abort(404, ErrFormat.department_id_not_found.format(_id))
|
||||
try:
|
||||
RoleCRUD.delete_role(existed.acl_rid)
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
return existed.soft_delete()
|
||||
|
||||
@staticmethod
|
||||
def get_allow_parent_d_id_by(department_id):
|
||||
"""
|
||||
获取可以成为 department_id 的 department_parent_id 的 list
|
||||
"""
|
||||
tree_list = DepartmentCRUD.get_department_tree_list()
|
||||
|
||||
allow_d_id_list = []
|
||||
|
||||
for tree in tree_list:
|
||||
if department_id > 0:
|
||||
try:
|
||||
tree.remove_subtree(department_id)
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
[allow_d_id_list.append({'department_id': int(n.identifier), 'department_name': n.tag}) for n in
|
||||
tree.all_nodes()]
|
||||
|
||||
return allow_d_id_list
|
||||
|
||||
@staticmethod
|
||||
def update_department_sort(department_list):
|
||||
d_map = {d['id']: d['sort_value'] for d in department_list}
|
||||
d_id = [d['id'] for d in department_list]
|
||||
|
||||
db_list = Department.query.filter(
|
||||
Department.department_id.in_(d_id),
|
||||
Department.deleted == 0
|
||||
).all()
|
||||
|
||||
for existed in db_list:
|
||||
existed.update(sort_value=d_map[existed.department_id])
|
||||
|
||||
return []
|
||||
|
||||
@staticmethod
|
||||
def get_all_departments_with_employee(block):
|
||||
return DepartmentTree(True, block).get_all_departments(1)
|
||||
|
||||
@staticmethod
|
||||
def get_department_tree_list():
|
||||
df = get_department_df()
|
||||
if df.empty:
|
||||
return []
|
||||
|
||||
# 一级部门
|
||||
top_df = df[df['department_parent_id'].eq(-1)]
|
||||
if top_df.empty:
|
||||
return []
|
||||
|
||||
tree_list = []
|
||||
|
||||
for index in top_df.index:
|
||||
tree = Tree()
|
||||
identifier_root = top_df.at[index, 'department_id']
|
||||
tree.create_node(
|
||||
top_df.at[index, 'department_name'],
|
||||
identifier_root
|
||||
)
|
||||
|
||||
# 检查 department_id 是否作为其他部门的 parent
|
||||
sub_df = df[
|
||||
df['department_parent_id'].eq(identifier_root)
|
||||
]
|
||||
if sub_df.empty:
|
||||
tree_list.append(tree)
|
||||
continue
|
||||
|
||||
DepartmentCRUD.parse_sub_department_node(
|
||||
sub_df, df, tree, identifier_root)
|
||||
|
||||
tree_list.append(tree)
|
||||
|
||||
return tree_list
|
||||
|
||||
@staticmethod
|
||||
def parse_sub_department_node(df, all_df, tree, parent_id):
|
||||
for s_index in df.index:
|
||||
tree.create_node(
|
||||
df.at[s_index, 'department_name'],
|
||||
df.at[s_index, 'department_id'],
|
||||
parent=parent_id
|
||||
)
|
||||
|
||||
sub_df = all_df[
|
||||
all_df['department_parent_id'].eq(
|
||||
df.at[s_index, 'department_id'])
|
||||
]
|
||||
if sub_df.empty:
|
||||
continue
|
||||
|
||||
DepartmentCRUD.parse_sub_department_node(
|
||||
sub_df, all_df, tree, df.at[s_index, 'department_id'])
|
||||
|
||||
@staticmethod
|
||||
def get_departments_and_ids(department_parent_id, block):
|
||||
query = Department.query.filter(
|
||||
Department.department_parent_id == department_parent_id,
|
||||
Department.deleted == 0,
|
||||
).order_by(Department.sort_value.asc())
|
||||
df = get_df_from_read_sql(query)
|
||||
if df.empty:
|
||||
return [], []
|
||||
|
||||
tree_list = DepartmentCRUD.get_department_tree_list()
|
||||
employee_df = get_all_employee_df(block)
|
||||
|
||||
department_id_list = list(df['department_id'].values)
|
||||
query = Department.query.filter(
|
||||
Department.department_parent_id.in_(department_id_list),
|
||||
Department.deleted == 0,
|
||||
).order_by(Department.sort_value.asc()).group_by(Department.department_id)
|
||||
sub_df = get_df_from_read_sql(query)
|
||||
if sub_df.empty:
|
||||
df['has_sub'] = 0
|
||||
|
||||
def handle_row_employee_count(row):
|
||||
return len(employee_df[employee_df['department_id'] == row['department_id']])
|
||||
|
||||
df['employee_count'] = df.apply(
|
||||
lambda row: handle_row_employee_count(row), axis=1)
|
||||
|
||||
else:
|
||||
sub_map = {d['department_parent_id']: 1 for d in sub_df.to_dict('records')}
|
||||
|
||||
def handle_row(row):
|
||||
d_ids = DepartmentCRUD.get_department_id_list_by_root(
|
||||
row['department_id'], tree_list)
|
||||
row['employee_count'] = len(
|
||||
employee_df[employee_df['department_id'].isin(d_ids)])
|
||||
|
||||
row['has_sub'] = sub_map.get(row['department_id'], 0)
|
||||
|
||||
return row
|
||||
|
||||
df = df.apply(lambda row: handle_row(row), axis=1)
|
||||
|
||||
return df.to_dict('records'), department_id_list
|
||||
|
||||
@staticmethod
|
||||
def get_department_id_list_by_root(root_department_id, tree_list=None):
|
||||
if tree_list is None:
|
||||
tree_list = DepartmentCRUD.get_department_tree_list()
|
||||
id_list = []
|
||||
for tree in tree_list:
|
||||
try:
|
||||
tmp_tree = tree.subtree(root_department_id)
|
||||
[id_list.append(int(n.identifier))
|
||||
for n in tmp_tree.all_nodes()]
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
return id_list
|
842
cmdb-api/api/lib/common_setting/employee.py
Normal file
842
cmdb-api/api/lib/common_setting/employee.py
Normal file
@@ -0,0 +1,842 @@
|
||||
# -*- coding:utf-8 -*-
|
||||
|
||||
import traceback
|
||||
from datetime import datetime
|
||||
|
||||
import pandas as pd
|
||||
from flask import abort
|
||||
from flask_login import current_user
|
||||
from sqlalchemy import or_, literal_column, func, not_, and_
|
||||
from werkzeug.datastructures import MultiDict
|
||||
from wtforms import Form
|
||||
from wtforms import IntegerField
|
||||
from wtforms import StringField
|
||||
from wtforms import validators
|
||||
|
||||
from api.extensions import db
|
||||
from api.lib.common_setting.acl import ACLManager
|
||||
from api.lib.common_setting.const import COMMON_SETTING_QUEUE, OperatorType
|
||||
from api.lib.common_setting.resp_format import ErrFormat
|
||||
from api.lib.common_setting.utils import get_df_from_read_sql
|
||||
from api.models.common_setting import Employee, Department
|
||||
|
||||
|
||||
def edit_acl_user(uid, **kwargs):
|
||||
user_data = {column: kwargs.get(
|
||||
column, '') for column in acl_user_columns if kwargs.get(column, '')}
|
||||
if 'block' in kwargs:
|
||||
user_data['block'] = kwargs.get('block')
|
||||
try:
|
||||
acl = ACLManager()
|
||||
return acl.edit_user(uid, user_data)
|
||||
except Exception as e:
|
||||
abort(400, ErrFormat.acl_edit_user_failed.format(str(e)))
|
||||
|
||||
|
||||
def get_block_value(value):
|
||||
if value in ['False', 'false', '0', 0]:
|
||||
value = False
|
||||
else:
|
||||
value = True
|
||||
|
||||
return value
|
||||
|
||||
|
||||
def get_employee_list_by_direct_supervisor_id(direct_supervisor_id):
|
||||
return Employee.get_by(direct_supervisor_id=direct_supervisor_id)
|
||||
|
||||
|
||||
def get_department_list_by_director_id(director_id):
|
||||
return Department.get_by(department_director_id=director_id)
|
||||
|
||||
|
||||
def raise_exception(err):
|
||||
raise Exception(err)
|
||||
|
||||
|
||||
def check_department_director_id_or_direct_supervisor_id(_id):
|
||||
get_employee_list_by_direct_supervisor_id(
|
||||
_id) and raise_exception(ErrFormat.cannot_block_this_employee_is_other_direct_supervisor)
|
||||
get_department_list_by_director_id(
|
||||
_id) and raise_exception(ErrFormat.cannot_block_this_employee_is_department_manager)
|
||||
|
||||
|
||||
class EmployeeCRUD(object):
|
||||
@staticmethod
|
||||
def get_employee_by_id(_id):
|
||||
return Employee.get_by(
|
||||
first=True, to_dict=False, deleted=0, employee_id=_id
|
||||
) or abort(404, ErrFormat.employee_id_not_found.format(_id))
|
||||
|
||||
@staticmethod
|
||||
def get_employee_by_uid_with_create(_uid):
|
||||
"""
|
||||
根据 uid 获取员工信息,不存在则创建
|
||||
"""
|
||||
try:
|
||||
return EmployeeCRUD.get_employee_by_uid(_uid).to_dict()
|
||||
except Exception as e:
|
||||
if '不存在' not in str(e):
|
||||
abort(400, str(e))
|
||||
|
||||
try:
|
||||
acl = ACLManager('acl')
|
||||
user_info = acl.get_user_info(_uid)
|
||||
return EmployeeCRUD.check_acl_user_and_create(user_info)
|
||||
|
||||
except Exception as e:
|
||||
abort(400, str(e))
|
||||
|
||||
@staticmethod
|
||||
def get_employee_by_uid(_uid):
|
||||
return Employee.get_by(
|
||||
first=True, to_dict=False, deleted=0, acl_uid=_uid
|
||||
) or abort(404, ErrFormat.acl_uid_not_found.format(_uid))
|
||||
|
||||
@staticmethod
|
||||
def check_acl_user_and_create(user_info):
|
||||
existed = Employee.get_by(
|
||||
first=True, to_dict=False, username=user_info['username'])
|
||||
if existed:
|
||||
existed.update(
|
||||
acl_uid=user_info['uid'],
|
||||
)
|
||||
return existed.to_dict()
|
||||
# 创建员工
|
||||
if not user_info.get('nickname', None):
|
||||
user_info['nickname'] = user_info['name']
|
||||
|
||||
form = EmployeeAddForm(MultiDict(user_info))
|
||||
data = form.data
|
||||
data['password'] = ''
|
||||
data['acl_uid'] = user_info['uid']
|
||||
|
||||
employee = CreateEmployee().create_single(**data)
|
||||
return employee.to_dict()
|
||||
|
||||
@staticmethod
|
||||
def add(**kwargs):
|
||||
try:
|
||||
return CreateEmployee().create_single(**kwargs)
|
||||
except Exception as e:
|
||||
abort(400, str(e))
|
||||
|
||||
@staticmethod
|
||||
def update(_id, **kwargs):
|
||||
EmployeeCRUD.check_email_unique(kwargs['email'], _id)
|
||||
|
||||
existed = EmployeeCRUD.get_employee_by_id(_id)
|
||||
|
||||
try:
|
||||
edit_acl_user(existed.acl_uid, **kwargs)
|
||||
|
||||
for column in employee_pop_columns:
|
||||
kwargs.pop(column, None)
|
||||
|
||||
new_department_id = kwargs.get('department_id', None)
|
||||
e_list = []
|
||||
if new_department_id is not None and new_department_id != existed.department_id:
|
||||
e_list = [dict(
|
||||
e_acl_rid=existed.acl_rid,
|
||||
department_id=existed.department_id
|
||||
)]
|
||||
|
||||
existed.update(**kwargs)
|
||||
|
||||
if len(e_list) > 0:
|
||||
from api.tasks.common_setting import edit_employee_department_in_acl
|
||||
# fixme: comment next line
|
||||
# edit_employee_department_in_acl(e_list, new_department_id, current_user.uid)
|
||||
|
||||
edit_employee_department_in_acl.apply_async(
|
||||
args=(e_list, new_department_id, current_user.uid),
|
||||
queue=COMMON_SETTING_QUEUE
|
||||
)
|
||||
|
||||
return existed
|
||||
except Exception as e:
|
||||
return abort(400, str(e))
|
||||
|
||||
@staticmethod
|
||||
def edit_employee_by_uid(_uid, **kwargs):
|
||||
existed = EmployeeCRUD.get_employee_by_uid(_uid)
|
||||
try:
|
||||
user = edit_acl_user(_uid, **kwargs)
|
||||
|
||||
for column in employee_pop_columns:
|
||||
if kwargs.get(column):
|
||||
kwargs.pop(column)
|
||||
|
||||
return existed.update(**kwargs)
|
||||
except Exception as e:
|
||||
return abort(400, str(e))
|
||||
|
||||
@staticmethod
|
||||
def change_password_by_uid(_uid, password):
|
||||
existed = EmployeeCRUD.get_employee_by_uid(_uid)
|
||||
try:
|
||||
user = edit_acl_user(_uid, password=password)
|
||||
except Exception as e:
|
||||
return abort(400, str(e))
|
||||
|
||||
@staticmethod
|
||||
def get_all_position():
|
||||
criterion = [
|
||||
Employee.deleted == 0,
|
||||
]
|
||||
results = Employee.query.with_entities(
|
||||
Employee.position_name
|
||||
).filter(*criterion).group_by(
|
||||
Employee.position_name
|
||||
).order_by(
|
||||
func.CONVERT(literal_column('position_name using gbk'))
|
||||
).all()
|
||||
|
||||
return [item[0] for item in results if (item[0] is not None and item[0] != '')]
|
||||
|
||||
@staticmethod
|
||||
def get_employee_count(block_status):
|
||||
criterion = [
|
||||
Employee.deleted == 0
|
||||
]
|
||||
|
||||
if block_status >= 0:
|
||||
criterion.append(
|
||||
Employee.block == block_status
|
||||
)
|
||||
|
||||
return Employee.query.filter(
|
||||
*criterion
|
||||
).count()
|
||||
|
||||
@staticmethod
|
||||
def import_employee(employee_list):
|
||||
return CreateEmployee().batch_create(employee_list)
|
||||
|
||||
@staticmethod
|
||||
def get_export_employee_df(block_status):
|
||||
criterion = [
|
||||
Employee.deleted == 0
|
||||
]
|
||||
if block_status >= 0:
|
||||
criterion.append(
|
||||
Employee.block == block_status
|
||||
)
|
||||
|
||||
query = Employee.query.with_entities(
|
||||
Employee.employee_id,
|
||||
Employee.nickname,
|
||||
Employee.email,
|
||||
Employee.sex,
|
||||
Employee.mobile,
|
||||
Employee.position_name,
|
||||
Employee.last_login,
|
||||
Employee.department_id,
|
||||
Employee.direct_supervisor_id,
|
||||
).filter(*criterion)
|
||||
df = get_df_from_read_sql(query)
|
||||
if df.empty:
|
||||
return df
|
||||
|
||||
query = Department.query.filter(
|
||||
*criterion
|
||||
)
|
||||
department_df = get_df_from_read_sql(query)
|
||||
|
||||
def find_name(row):
|
||||
department_id = row['department_id']
|
||||
_df = department_df[department_df['department_id']
|
||||
== department_id]
|
||||
row['department_name'] = '' if _df.empty else _df.iloc[0]['department_name']
|
||||
|
||||
direct_supervisor_id = row['direct_supervisor_id']
|
||||
_df = df[df['employee_id'] == direct_supervisor_id]
|
||||
row['nickname_direct_supervisor'] = '' if _df.empty else _df.iloc[0]['nickname']
|
||||
|
||||
if isinstance(row['last_login'], pd.Timestamp):
|
||||
try:
|
||||
row['last_login'] = str(row['last_login'])
|
||||
except:
|
||||
row['last_login'] = ''
|
||||
else:
|
||||
row['last_login'] = ''
|
||||
|
||||
return row
|
||||
|
||||
df = df.apply(find_name, axis=1)
|
||||
df.drop(['department_id', 'direct_supervisor_id',
|
||||
'employee_id'], axis=1, inplace=True)
|
||||
return df
|
||||
|
||||
@staticmethod
|
||||
def batch_employee(column_name, column_value, employee_id_list):
|
||||
if not column_value:
|
||||
abort(400, ErrFormat.value_is_required)
|
||||
if column_name in ['password', 'block']:
|
||||
return EmployeeCRUD.batch_edit_password_or_block_column(column_name, employee_id_list, column_value, True)
|
||||
|
||||
elif column_name in ['department_id']:
|
||||
return EmployeeCRUD.batch_edit_employee_department(employee_id_list, column_value)
|
||||
|
||||
elif column_name in [
|
||||
'direct_supervisor_id', 'position_name'
|
||||
]:
|
||||
return EmployeeCRUD.batch_edit_column(column_name, employee_id_list, column_value, False)
|
||||
|
||||
else:
|
||||
abort(400, ErrFormat.column_name_not_support)
|
||||
|
||||
@staticmethod
|
||||
def batch_edit_employee_department(employee_id_list, column_value):
|
||||
err_list = []
|
||||
employee_list = []
|
||||
for _id in employee_id_list:
|
||||
try:
|
||||
existed = EmployeeCRUD.get_employee_by_id(_id)
|
||||
employee = dict(
|
||||
e_acl_rid=existed.acl_rid,
|
||||
department_id=existed.department_id
|
||||
)
|
||||
employee_list.append(employee)
|
||||
existed.update(department_id=column_value)
|
||||
|
||||
except Exception as e:
|
||||
err_list.append({
|
||||
'employee_id': _id,
|
||||
'err': str(e),
|
||||
})
|
||||
from api.tasks.common_setting import edit_employee_department_in_acl
|
||||
edit_employee_department_in_acl.apply_async(
|
||||
args=(employee_list, column_value, current_user.uid),
|
||||
queue=COMMON_SETTING_QUEUE
|
||||
)
|
||||
return err_list
|
||||
|
||||
@staticmethod
|
||||
def batch_edit_password_or_block_column(column_name, employee_id_list, column_value, is_acl=False):
|
||||
if column_name == 'block':
|
||||
err_list = []
|
||||
success_list = []
|
||||
for _id in employee_id_list:
|
||||
try:
|
||||
employee = EmployeeCRUD.edit_employee_block_column(
|
||||
_id, is_acl, **{column_name: column_value})
|
||||
success_list.append(employee)
|
||||
except Exception as e:
|
||||
err_list.append({
|
||||
'employee_id': _id,
|
||||
'err': str(e),
|
||||
})
|
||||
return err_list
|
||||
else:
|
||||
return EmployeeCRUD.batch_edit_column(column_name, employee_id_list, column_value, is_acl)
|
||||
|
||||
@staticmethod
|
||||
def batch_edit_column(column_name, employee_id_list, column_value, is_acl=False):
|
||||
err_list = []
|
||||
for _id in employee_id_list:
|
||||
try:
|
||||
EmployeeCRUD.edit_employee_single_column(
|
||||
_id, is_acl, **{column_name: column_value})
|
||||
except Exception as e:
|
||||
err_list.append({
|
||||
'employee_id': _id,
|
||||
'err': str(e),
|
||||
})
|
||||
|
||||
return err_list
|
||||
|
||||
@staticmethod
|
||||
def edit_employee_single_column(_id, is_acl=False, **kwargs):
|
||||
existed = EmployeeCRUD.get_employee_by_id(_id)
|
||||
|
||||
if is_acl:
|
||||
return edit_acl_user(existed.acl_uid, **kwargs)
|
||||
|
||||
try:
|
||||
for column in employee_pop_columns:
|
||||
if kwargs.get(column):
|
||||
kwargs.pop(column)
|
||||
|
||||
return existed.update(**kwargs)
|
||||
except Exception as e:
|
||||
return abort(400, str(e))
|
||||
|
||||
@staticmethod
|
||||
def edit_employee_block_column(_id, is_acl=False, **kwargs):
|
||||
existed = EmployeeCRUD.get_employee_by_id(_id)
|
||||
value = get_block_value(kwargs.get('block'))
|
||||
if value is True:
|
||||
# 判断该用户是否为 部门负责人,或者员工的直接上级
|
||||
check_department_director_id_or_direct_supervisor_id(_id)
|
||||
|
||||
if is_acl:
|
||||
kwargs['block'] = value
|
||||
edit_acl_user(existed.acl_uid, **kwargs)
|
||||
data = existed.to_dict()
|
||||
return data
|
||||
|
||||
@staticmethod
|
||||
def check_email_unique(email, _id=0):
|
||||
criterion = [
|
||||
Employee.email == email,
|
||||
Employee.deleted == 0,
|
||||
]
|
||||
if _id > 0:
|
||||
criterion.append(
|
||||
Employee.employee_id != _id
|
||||
)
|
||||
res = Employee.query.filter(
|
||||
*criterion
|
||||
).all()
|
||||
|
||||
if res:
|
||||
err = ErrFormat.email_already_exists.format(email)
|
||||
raise Exception(err)
|
||||
|
||||
@staticmethod
|
||||
def get_employee_list_by_body(department_id, block_status, search='', order='', conditions=[], page=1,
|
||||
page_size=10):
|
||||
criterion = [
|
||||
Employee.deleted == 0
|
||||
]
|
||||
|
||||
if block_status >= 0:
|
||||
criterion.append(
|
||||
Employee.block == block_status
|
||||
)
|
||||
|
||||
if len(search) > 0:
|
||||
search_key = f"%{search}%"
|
||||
criterion.append(
|
||||
or_(
|
||||
Employee.email.like(search_key),
|
||||
Employee.username.like(search_key),
|
||||
Employee.nickname.like(search_key)
|
||||
)
|
||||
)
|
||||
|
||||
if department_id > 0:
|
||||
from api.lib.common_setting.department import DepartmentCRUD
|
||||
department_id_list = DepartmentCRUD.get_department_id_list_by_root(
|
||||
department_id)
|
||||
criterion.append(
|
||||
Employee.department_id.in_(department_id_list)
|
||||
)
|
||||
|
||||
if conditions:
|
||||
query = EmployeeCRUD.parse_condition_list_to_query(conditions).filter(
|
||||
*criterion
|
||||
)
|
||||
else:
|
||||
query = db.session.query(Employee, Department).outerjoin(Department).filter(
|
||||
*criterion
|
||||
)
|
||||
|
||||
if len(order) > 0:
|
||||
query = EmployeeCRUD.format_query_sort(query, order)
|
||||
|
||||
pagination = query.paginate(page=page, per_page=page_size)
|
||||
|
||||
employees = []
|
||||
for r in pagination.items:
|
||||
d = r.Employee.to_dict()
|
||||
d['department_name'] = r.Department.department_name
|
||||
employees.append(d)
|
||||
|
||||
return {
|
||||
'data_list': employees,
|
||||
'page': page,
|
||||
'page_size': page_size,
|
||||
'total': pagination.total,
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def parse_condition_list_to_query(condition_list):
|
||||
query = db.session.query(Employee, Department).outerjoin(Department)
|
||||
|
||||
query = EmployeeCRUD.get_query_by_conditions(query, condition_list)
|
||||
return query
|
||||
|
||||
@staticmethod
|
||||
def get_expr_by_condition(column, operator, value, relation):
|
||||
"""
|
||||
根据conditions返回expr: (and_list, or_list)
|
||||
"""
|
||||
attr = EmployeeCRUD.get_attr_by_column(column)
|
||||
# 根据operator生成条件表达式
|
||||
if operator == OperatorType.EQUAL:
|
||||
expr = [attr == value]
|
||||
elif operator == OperatorType.NOT_EQUAL:
|
||||
expr = [attr != value]
|
||||
elif operator == OperatorType.IN:
|
||||
expr = [attr.like('%{}%'.format(value))]
|
||||
elif operator == OperatorType.NOT_IN:
|
||||
expr = [not_(attr.like('%{}%'.format(value)))]
|
||||
elif operator == OperatorType.GREATER_THAN:
|
||||
expr = [attr > value]
|
||||
elif operator == OperatorType.LESS_THAN:
|
||||
expr = [attr < value]
|
||||
elif operator == OperatorType.IS_EMPTY:
|
||||
if value:
|
||||
abort(400, ErrFormat.query_column_none_keep_value_empty.format(column))
|
||||
expr = [attr.is_(None)]
|
||||
if column not in ["entry_date", "leave_date", "dfc_entry_date", "last_login"]:
|
||||
expr += [attr == '']
|
||||
expr = [or_(*expr)]
|
||||
elif operator == OperatorType.IS_NOT_EMPTY:
|
||||
if value:
|
||||
abort(400, ErrFormat.query_column_none_keep_value_empty.format(column))
|
||||
|
||||
expr = [attr.isnot(None)]
|
||||
if column not in ["last_login"]:
|
||||
expr += [attr != '']
|
||||
expr = [and_(*expr)]
|
||||
else:
|
||||
abort(400, ErrFormat.not_support_operator.format(operator))
|
||||
|
||||
# 根据relation生成复合条件
|
||||
if relation == "&":
|
||||
return expr, []
|
||||
elif relation == "|":
|
||||
return [], expr
|
||||
else:
|
||||
return abort(400, ErrFormat.not_support_relation.format(relation))
|
||||
|
||||
@staticmethod
|
||||
def check_condition(column, operator, value, relation):
|
||||
# 对于condition中column为空的,报错
|
||||
if column is None or operator is None or relation is None:
|
||||
return abort(400, ErrFormat.conditions_field_missing)
|
||||
|
||||
if value and column == "last_login":
|
||||
try:
|
||||
value = datetime.strptime(value, "%Y-%m-%d %H:%M:%S")
|
||||
except Exception as e:
|
||||
abort(400, ErrFormat.datetime_format_error.format(column))
|
||||
|
||||
@staticmethod
|
||||
def get_attr_by_column(column):
|
||||
if 'department' in column:
|
||||
attr = Department.__dict__[column]
|
||||
else:
|
||||
attr = Employee.__dict__[column]
|
||||
return attr
|
||||
|
||||
@staticmethod
|
||||
def get_query_by_conditions(query, conditions):
|
||||
and_list = []
|
||||
or_list = []
|
||||
|
||||
for condition in conditions:
|
||||
operator = condition.get("operator", None)
|
||||
column = condition.get("column", None)
|
||||
relation = condition.get("relation", None)
|
||||
value = condition.get("value", None)
|
||||
|
||||
EmployeeCRUD.check_condition(column, operator, value, relation)
|
||||
a, o = EmployeeCRUD.get_expr_by_condition(
|
||||
column, operator, value, relation)
|
||||
and_list += a
|
||||
or_list += o
|
||||
|
||||
query = query.filter(
|
||||
Employee.deleted == 0,
|
||||
or_(and_(*and_list), *or_list)
|
||||
)
|
||||
|
||||
return query
|
||||
|
||||
@staticmethod
|
||||
def get_employee_list_by(department_id, block_status, search='', order='', page=1, page_size=10):
|
||||
criterion = [
|
||||
Employee.deleted == 0
|
||||
]
|
||||
|
||||
if block_status >= 0:
|
||||
criterion.append(
|
||||
Employee.block == block_status
|
||||
)
|
||||
|
||||
if len(search) > 0:
|
||||
search_key = f"%{search}%"
|
||||
criterion.append(
|
||||
or_(
|
||||
Employee.email.like(search_key),
|
||||
Employee.username.like(search_key),
|
||||
Employee.nickname.like(search_key)
|
||||
)
|
||||
)
|
||||
|
||||
if department_id > 0:
|
||||
from api.lib.common_setting.department import DepartmentCRUD
|
||||
department_id_list = DepartmentCRUD.get_department_id_list_by_root(
|
||||
department_id)
|
||||
criterion.append(
|
||||
Employee.department_id.in_(department_id_list)
|
||||
)
|
||||
|
||||
query = db.session.query(Employee, Department).outerjoin(Department).filter(
|
||||
*criterion
|
||||
)
|
||||
|
||||
if len(order) > 0:
|
||||
query = EmployeeCRUD.format_query_sort(query, order)
|
||||
|
||||
pagination = query.paginate(page=page, per_page=page_size)
|
||||
employees = []
|
||||
for r in pagination.items:
|
||||
d = r.Employee.to_dict()
|
||||
d['department_name'] = r.Department.department_name
|
||||
employees.append(d)
|
||||
|
||||
return {
|
||||
'data_list': employees,
|
||||
'page': page,
|
||||
'page_size': page_size,
|
||||
'total': pagination.total,
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def format_query_sort(query, order):
|
||||
order_list = order.split(',')
|
||||
all_columns = Employee.get_columns()
|
||||
|
||||
for order_column in order_list:
|
||||
if order_column.startswith('-'):
|
||||
target_column = order_column[1:]
|
||||
if target_column not in all_columns:
|
||||
continue
|
||||
query = query.order_by(getattr(Employee, target_column).desc())
|
||||
else:
|
||||
if order_column not in all_columns:
|
||||
continue
|
||||
|
||||
query = query.order_by(getattr(Employee, order_column).asc())
|
||||
|
||||
return query
|
||||
|
||||
@staticmethod
|
||||
def get_employees_by_department_id(department_id, block):
|
||||
criterion = [
|
||||
Employee.deleted == 0,
|
||||
Employee.block == block,
|
||||
]
|
||||
if type(department_id) == list:
|
||||
if len(department_id) == 0:
|
||||
return []
|
||||
else:
|
||||
criterion.append(
|
||||
Employee.department_id.in_(department_id)
|
||||
)
|
||||
else:
|
||||
criterion.append(
|
||||
Employee.department_id == department_id
|
||||
)
|
||||
|
||||
results = Employee.query.filter(
|
||||
*criterion
|
||||
).all()
|
||||
|
||||
return [r.to_dict() for r in results]
|
||||
|
||||
|
||||
def get_user_map(key='uid', acl=None):
|
||||
"""
|
||||
{
|
||||
uid: userinfo
|
||||
}
|
||||
"""
|
||||
if acl is None:
|
||||
acl = ACLManager()
|
||||
data = {user[key]: user for user in acl.get_all_users()}
|
||||
|
||||
return data
|
||||
|
||||
|
||||
acl_user_columns = [
|
||||
'email',
|
||||
'mobile',
|
||||
'nickname',
|
||||
'username',
|
||||
'password',
|
||||
'block',
|
||||
'avatar',
|
||||
]
|
||||
employee_pop_columns = ['password']
|
||||
can_not_edit_columns = ['email']
|
||||
|
||||
|
||||
def format_params(params):
|
||||
for k in ['_key', '_secret']:
|
||||
params.pop(k, None)
|
||||
return params
|
||||
|
||||
|
||||
class CreateEmployee(object):
|
||||
def __init__(self):
|
||||
self.acl = ACLManager()
|
||||
self.useremail_map = {}
|
||||
|
||||
def check_acl_user(self, email):
|
||||
user_info = self.useremail_map.get(email, None)
|
||||
if user_info:
|
||||
return user_info
|
||||
return None
|
||||
|
||||
def add_acl_user(self, **kwargs):
|
||||
user_data = {column: kwargs.get(
|
||||
column, '') for column in acl_user_columns if kwargs.get(column, '')}
|
||||
try:
|
||||
existed = self.check_acl_user(user_data['email'])
|
||||
if not existed:
|
||||
return self.acl.create_user(user_data)
|
||||
return existed
|
||||
except Exception as e:
|
||||
abort(400, ErrFormat.acl_add_user_failed.format(str(e)))
|
||||
|
||||
def create_single(self, **kwargs):
|
||||
EmployeeCRUD.check_email_unique(kwargs['email'])
|
||||
self.useremail_map = self.useremail_map if self.useremail_map else get_user_map(
|
||||
'email', self.acl)
|
||||
user = self.add_acl_user(**kwargs)
|
||||
kwargs['acl_uid'] = user['uid']
|
||||
kwargs['last_login'] = user['last_login']
|
||||
|
||||
for column in employee_pop_columns:
|
||||
kwargs.pop(column)
|
||||
|
||||
return Employee.create(
|
||||
**kwargs
|
||||
)
|
||||
|
||||
def create_single_with_import(self, **kwargs):
|
||||
self.useremail_map = self.useremail_map if self.useremail_map else get_user_map(
|
||||
'email', self.acl)
|
||||
user = self.add_acl_user(**kwargs)
|
||||
kwargs['acl_uid'] = user['uid']
|
||||
kwargs['last_login'] = user['last_login']
|
||||
|
||||
for column in employee_pop_columns:
|
||||
kwargs.pop(column)
|
||||
|
||||
existed = Employee.get_by(
|
||||
first=True, to_dict=False, deleted=0, acl_uid=user['uid']
|
||||
)
|
||||
if existed:
|
||||
return existed
|
||||
|
||||
return Employee.create(
|
||||
**kwargs
|
||||
)
|
||||
|
||||
def get_department_by_name(self, d_name):
|
||||
return Department.get_by(first=True, department_name=d_name)
|
||||
|
||||
def get_end_department_id(self, department_name_list, department_name_map):
|
||||
parent_id = 0
|
||||
|
||||
end_d_id = 0
|
||||
for d_name in department_name_list:
|
||||
tmp_d = self.get_department_by_name(d_name)
|
||||
if not tmp_d:
|
||||
tmp_d = Department.create(
|
||||
department_name=d_name, department_parent_id=parent_id).to_dict()
|
||||
else:
|
||||
if tmp_d['department_parent_id'] != parent_id:
|
||||
department_name_map[d_name] = tmp_d
|
||||
raise Exception(ErrFormat.department_level_relation_error)
|
||||
|
||||
department_name_map[d_name] = tmp_d
|
||||
|
||||
end_d_id = tmp_d['department_id']
|
||||
parent_id = tmp_d['department_id']
|
||||
|
||||
return end_d_id
|
||||
|
||||
def format_department_id(self, employee):
|
||||
"""
|
||||
部门名称转化为ID,不存在则创建
|
||||
"""
|
||||
department_name_map = {}
|
||||
try:
|
||||
department_name = employee.get('department_name', '')
|
||||
if len(department_name) == 0:
|
||||
return employee
|
||||
department_name_list = department_name.split('/')
|
||||
employee['department_id'] = self.get_end_department_id(
|
||||
department_name_list, department_name_map)
|
||||
|
||||
except Exception as e:
|
||||
employee['err'] = str(e)
|
||||
|
||||
return employee
|
||||
|
||||
def batch_create(self, employee_list):
|
||||
err_list = []
|
||||
self.useremail_map = get_user_map('email', self.acl)
|
||||
|
||||
for employee in employee_list:
|
||||
try:
|
||||
# 获取username
|
||||
username = employee.get('username', None)
|
||||
if username is None:
|
||||
employee['username'] = employee['email']
|
||||
|
||||
# 校验通过后获取department_id
|
||||
employee = self.format_department_id(employee)
|
||||
err = employee.get('err', None)
|
||||
if err:
|
||||
raise Exception(err)
|
||||
|
||||
params = format_params(employee)
|
||||
form = EmployeeAddForm(MultiDict(params))
|
||||
if not form.validate():
|
||||
raise Exception(
|
||||
','.join(['{}: {}'.format(filed, ','.join(msg)) for filed, msg in form.errors.items()]))
|
||||
|
||||
data = self.create_single_with_import(**form.data)
|
||||
except Exception as e:
|
||||
err_list.append({
|
||||
'email': employee.get('email', ''),
|
||||
'nickname': employee.get('nickname', ''),
|
||||
'err': str(e),
|
||||
})
|
||||
traceback.print_exc()
|
||||
|
||||
return err_list
|
||||
|
||||
|
||||
class EmployeeAddForm(Form):
|
||||
username = StringField(validators=[
|
||||
validators.DataRequired(message="username不能为空"),
|
||||
validators.Length(max=255),
|
||||
])
|
||||
email = StringField(validators=[
|
||||
validators.DataRequired(message="邮箱不能为空"),
|
||||
validators.Email(message="邮箱格式不正确"),
|
||||
validators.Length(max=255),
|
||||
])
|
||||
password = StringField(validators=[
|
||||
validators.Length(max=255),
|
||||
])
|
||||
position_name = StringField(validators=[])
|
||||
|
||||
nickname = StringField(validators=[
|
||||
validators.DataRequired(message="用户名不能为空"),
|
||||
validators.Length(max=255),
|
||||
])
|
||||
sex = StringField(validators=[])
|
||||
mobile = StringField(validators=[])
|
||||
department_id = IntegerField(validators=[], default=0)
|
||||
direct_supervisor_id = IntegerField(validators=[], default=0)
|
||||
|
||||
|
||||
class EmployeeUpdateByUidForm(Form):
|
||||
nickname = StringField(validators=[
|
||||
validators.DataRequired(message="用户名不能为空"),
|
||||
validators.Length(max=255),
|
||||
])
|
||||
avatar = StringField(validators=[])
|
||||
sex = StringField(validators=[])
|
||||
mobile = StringField(validators=[])
|
51
cmdb-api/api/lib/common_setting/resp_format.py
Normal file
51
cmdb-api/api/lib/common_setting/resp_format.py
Normal file
@@ -0,0 +1,51 @@
|
||||
# -*- coding:utf-8 -*-
|
||||
|
||||
from api.lib.resp_format import CommonErrFormat
|
||||
|
||||
|
||||
class ErrFormat(CommonErrFormat):
|
||||
company_info_is_already_existed = "公司信息已存在!无法创建"
|
||||
|
||||
no_file_part = "没有文件部分"
|
||||
file_is_required = "文件是必须的"
|
||||
|
||||
direct_supervisor_is_not_self = "直属上级不能是自己"
|
||||
parent_department_is_not_self = "上级部门不能是自己"
|
||||
employee_list_is_empty = "员工列表为空"
|
||||
|
||||
column_name_not_support = "不支持的列名"
|
||||
password_is_required = "密码不能为空"
|
||||
employee_acl_rid_is_zero = "员工ACL角色ID不能为0"
|
||||
|
||||
generate_excel_failed = "生成excel失败: {}"
|
||||
rename_columns_failed = "字段转换为中文失败: {}"
|
||||
cannot_block_this_employee_is_other_direct_supervisor = "该员工是其他员工的直属上级, 不能禁用"
|
||||
cannot_block_this_employee_is_department_manager = "该员工是部门负责人, 不能禁用"
|
||||
employee_id_not_found = "员工ID [{}] 不存在"
|
||||
value_is_required = "值是必须的"
|
||||
email_already_exists = "邮箱 [{}] 已存在"
|
||||
query_column_none_keep_value_empty = "查询 {} 空值时请保持value为空"
|
||||
not_support_operator = "不支持的操作符: {}"
|
||||
not_support_relation = "不支持的关系: {}"
|
||||
conditions_field_missing = "conditions内元素字段缺失,请检查!"
|
||||
datetime_format_error = "{} 格式错误,应该为:%Y-%m-%d %H:%M:%S"
|
||||
department_level_relation_error = "部门层级关系不正确"
|
||||
delete_reserved_department_name = "保留部门,无法删除!"
|
||||
department_id_is_required = "部门ID是必须的"
|
||||
department_list_is_required = "部门列表是必须的"
|
||||
cannot_to_be_parent_department = "{} 不能设置为上级部门"
|
||||
department_id_not_found = "部门ID [{}] 不存在"
|
||||
parent_department_id_must_more_than_zero = "上级部门ID必须大于0"
|
||||
department_name_already_exists = "部门名称 [{}] 已存在"
|
||||
new_department_is_none = "新部门是空的"
|
||||
|
||||
acl_edit_user_failed = "ACL 修改用户失败: {}"
|
||||
acl_uid_not_found = "ACL 用户UID [{}] 不存在"
|
||||
acl_add_user_failed = "ACL 添加用户失败: {}"
|
||||
acl_add_role_failed = "ACL 添加角色失败: {}"
|
||||
acl_update_role_failed = "ACL 更新角色失败: {}"
|
||||
acl_get_all_users_failed = "ACL 获取所有用户失败: {}"
|
||||
acl_remove_user_from_role_failed = "ACL 从角色中移除用户失败: {}"
|
||||
acl_add_user_to_role_failed = "ACL 添加用户到角色失败: {}"
|
||||
acl_import_user_failed = "ACL 导入用户[{}]失败: {}"
|
||||
|
16
cmdb-api/api/lib/common_setting/upload_file.py
Normal file
16
cmdb-api/api/lib/common_setting/upload_file.py
Normal file
@@ -0,0 +1,16 @@
|
||||
import uuid
|
||||
|
||||
from api.lib.common_setting.utils import get_cur_time_str
|
||||
|
||||
|
||||
def allowed_file(filename, allowed_extensions):
|
||||
return '.' in filename and \
|
||||
filename.rsplit('.', 1)[1].lower() in allowed_extensions
|
||||
|
||||
|
||||
def generate_new_file_name(name):
|
||||
ext = name.split('.')[-1]
|
||||
prev_name = ''.join(name.split(f".{ext}")[:-1])
|
||||
uid = str(uuid.uuid4())
|
||||
cur_str = get_cur_time_str('_')
|
||||
return f"{prev_name}_{cur_str}_{uid}.{ext}"
|
42
cmdb-api/api/lib/common_setting/utils.py
Normal file
42
cmdb-api/api/lib/common_setting/utils.py
Normal file
@@ -0,0 +1,42 @@
|
||||
# -*- coding:utf-8 -*-
|
||||
from datetime import datetime
|
||||
|
||||
import pandas as pd
|
||||
from sqlalchemy import text
|
||||
|
||||
from api.extensions import db
|
||||
|
||||
|
||||
def get_df_from_read_sql(query, to_dict=False):
|
||||
bind = query.session.bind
|
||||
query = query.statement.compile(dialect=bind.dialect if bind else None,
|
||||
compile_kwargs={"literal_binds": True}).string
|
||||
a = db.engine
|
||||
df = pd.read_sql(sql=text(query), con=a.connect())
|
||||
|
||||
if to_dict:
|
||||
return df.to_dict('records')
|
||||
return df
|
||||
|
||||
|
||||
def get_cur_time_str(split_flag='-'):
|
||||
f = f"%Y{split_flag}%m{split_flag}%d{split_flag}%H{split_flag}%M{split_flag}%S{split_flag}%f"
|
||||
return datetime.now().strftime(f)[:-3]
|
||||
|
||||
|
||||
class BaseEnum(object):
|
||||
_ALL_ = set()
|
||||
|
||||
@classmethod
|
||||
def is_valid(cls, item):
|
||||
return item in cls.all()
|
||||
|
||||
@classmethod
|
||||
def all(cls):
|
||||
if not cls._ALL_:
|
||||
cls._ALL_ = {
|
||||
getattr(cls, attr)
|
||||
for attr in dir(cls)
|
||||
if not attr.startswith("_") and not callable(getattr(cls, attr))
|
||||
}
|
||||
return cls._ALL_
|
Reference in New Issue
Block a user