refactor: P4c 批次1 服务层改造(notice/param/link/level)
【服务层新范式批量铺开】4 个 uniform 模块: - service:get_x_page(params)->dict、add/update/status(data)->None、 delete(ids)->int、get_info 委托 Repository(新建 repository.py) - 业务失败 raise BizError;router 取参包 R - level 的 Excel import/export 暂保留 R 返回(后续统一改造) 【工具】codemod 函数级转换(try/except 退格移除、R.failed→BizError、 R.ok→return data)+ black 格式化 + 未用导入清理 【教训】清理脚本 startswith 前缀误删含多名字的 import 行(models_to_list, model_to_dict 同行)导致 F821,已按 F821 精确补回 【验收】应用启动;4 服务分页查询运行时正常;12 passed;flake8 零告警 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude
parent
63afa4e629
commit
3f55f62f0d
@@ -71,24 +71,25 @@ import time
|
||||
import logging
|
||||
|
||||
from datetime import datetime, timezone
|
||||
from flask import request
|
||||
from sqlalchemy import and_
|
||||
from openpyxl.reader.excel import load_workbook
|
||||
from openpyxl.workbook import Workbook
|
||||
from sqlalchemy import and_
|
||||
|
||||
import utils
|
||||
|
||||
from src.common.constants.common import PAGE_SIZE
|
||||
from src.modules.system.level.schema import LevelForm, LevelStatusForm
|
||||
from src.modules.system.level.models import Level
|
||||
from src.modules.system.level.repository import LevelRepository
|
||||
from src.core import response as R
|
||||
from src.core.database import db
|
||||
from src.core.exceptions import BizError
|
||||
from src.modules.upload import service as upload
|
||||
from config import FLASK_TEMP_PATH, FLASK_UPLOAD_DIR
|
||||
from src.core.database import db
|
||||
from src.core import response as R
|
||||
from src.common.utils import regular
|
||||
from src.common.utils.case_converter import convert_camel_to_snake
|
||||
from src.common.utils.model_utils import models_to_list, model_to_dict
|
||||
from src.common.utils.request import parse_request_body, parse_id_list, like_contains
|
||||
from src.common.utils.request import parse_id_list, like_contains
|
||||
from src.common.utils.rich_text import get_file_url
|
||||
from src.common.utils.file import mkdir
|
||||
from src.core.security import get_username
|
||||
@@ -101,7 +102,8 @@ logger = logging.getLogger(__name__)
|
||||
# 职级分页查询
|
||||
# ============================================================
|
||||
|
||||
def get_level_page():
|
||||
|
||||
def get_level_page(params: dict) -> dict:
|
||||
"""
|
||||
查询职级分页数据
|
||||
|
||||
@@ -122,31 +124,26 @@ def get_level_page():
|
||||
"pages": 总页数
|
||||
}
|
||||
"""
|
||||
try:
|
||||
# 获取分页参数
|
||||
page_no = int(request.args.get('pageNo', 1))
|
||||
page_size = int(request.args.get('pageSize', PAGE_SIZE))
|
||||
# 获取分页参数
|
||||
page_no = int(params.get("pageNo", 1))
|
||||
page_size = int(params.get("pageSize", PAGE_SIZE))
|
||||
|
||||
# 应用筛选条件
|
||||
query = _apply_filters()
|
||||
# 应用筛选条件
|
||||
query = _apply_filters(params)
|
||||
|
||||
# 记录总数
|
||||
total = query.count()
|
||||
# 计算总页数
|
||||
pages = (total + page_size - 1) // page_size if total > 0 else 0
|
||||
# 记录总数
|
||||
total = query.count()
|
||||
# 计算总页数
|
||||
pages = (total + page_size - 1) // page_size if total > 0 else 0
|
||||
|
||||
# 分页查询
|
||||
level_list = query.limit(page_size).offset((page_no - 1) * page_size).all()
|
||||
# 构建返回数据
|
||||
page_data = _build_page_data(level_list, total, page_size, page_no, pages)
|
||||
return R.ok(data=page_data)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"查询职级分页数据异常: {str(e)}")
|
||||
return R.failed(msg="查询失败,请稍后重试")
|
||||
# 分页查询
|
||||
level_list = query.limit(page_size).offset((page_no - 1) * page_size).all()
|
||||
# 构建返回数据
|
||||
page_data = _build_page_data(level_list, total, page_size, page_no, pages)
|
||||
return page_data
|
||||
|
||||
|
||||
def _apply_filters():
|
||||
def _apply_filters(params: dict):
|
||||
"""
|
||||
应用查询筛选条件
|
||||
|
||||
@@ -163,12 +160,12 @@ def _apply_filters():
|
||||
query = Level.query.filter(Level.is_delete == 0)
|
||||
|
||||
# 职级名称模糊筛选
|
||||
name = request.args.get('name')
|
||||
name = params.get("name")
|
||||
if name:
|
||||
query = query.filter(Level.name.like(like_contains(name), escape='\\'))
|
||||
query = query.filter(Level.name.like(like_contains(name), escape="\\"))
|
||||
|
||||
# 职级状态精确筛选
|
||||
status = request.args.get('status')
|
||||
status = params.get("status")
|
||||
if status:
|
||||
query = query.filter(Level.status == status)
|
||||
|
||||
@@ -193,19 +190,14 @@ def _build_page_data(level_list, total, page_size, page_no, pages):
|
||||
# 将模型对象列表转换为字典列表
|
||||
records = models_to_list(level_list)
|
||||
|
||||
return {
|
||||
'records': records,
|
||||
'total': total,
|
||||
'size': page_size,
|
||||
'current': page_no,
|
||||
'pages': pages
|
||||
}
|
||||
return {"records": records, "total": total, "size": page_size, "current": page_no, "pages": pages}
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 职级详情查询
|
||||
# ============================================================
|
||||
|
||||
|
||||
def get_level_detail(level_id):
|
||||
"""
|
||||
根据ID查询职级详情(返回字典格式)
|
||||
@@ -236,6 +228,7 @@ def get_level_detail(level_id):
|
||||
# 职级信息查询(根据ID)- 核心查询方法
|
||||
# ============================================================
|
||||
|
||||
|
||||
def get_info(level_id: int):
|
||||
"""
|
||||
根据ID查询职级信息(返回模型对象)
|
||||
@@ -261,26 +254,10 @@ def get_info(level_id: int):
|
||||
if level:
|
||||
print(level.name)
|
||||
"""
|
||||
# 参数有效性验证
|
||||
if not level_id or level_id <= 0:
|
||||
return None
|
||||
|
||||
try:
|
||||
# 查询未删除的职级
|
||||
level = Level.query.filter(
|
||||
and_(Level.id == level_id, Level.is_delete == 0)
|
||||
).first()
|
||||
return level
|
||||
except Exception as e:
|
||||
logger.error(f"查询职级信息异常,ID: {level_id}, 错误: {str(e)}")
|
||||
return None
|
||||
return LevelRepository.get_by_id(level_id)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 职级添加
|
||||
# ============================================================
|
||||
|
||||
def add_level():
|
||||
def add_level(data: dict) -> None:
|
||||
"""
|
||||
添加职级
|
||||
|
||||
@@ -292,35 +269,24 @@ def add_level():
|
||||
Returns:
|
||||
R: 操作结果
|
||||
"""
|
||||
try:
|
||||
# 获取参数
|
||||
json_data, error = parse_request_body()
|
||||
if error:
|
||||
return R.failed(msg=error)
|
||||
|
||||
# 表单验证
|
||||
form = LevelForm(data=json_data)
|
||||
if not form.validate():
|
||||
err_msg = regular.get_err(form)
|
||||
return R.failed(msg=err_msg)
|
||||
# 表单验证
|
||||
form = LevelForm(data=data)
|
||||
if not form.validate():
|
||||
raise BizError(regular.get_err(form))
|
||||
|
||||
# 创建职级
|
||||
level = Level(**form.data)
|
||||
level.create_user = get_username()
|
||||
level.save()
|
||||
|
||||
return R.ok(msg="添加成功")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"添加职级异常: {str(e)}")
|
||||
return R.failed(msg="添加失败,请稍后重试")
|
||||
# 创建职级
|
||||
level = Level(**form.data)
|
||||
level.create_user = get_username()
|
||||
level.save()
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 职级更新
|
||||
# ============================================================
|
||||
|
||||
def update_level():
|
||||
|
||||
def update_level(data: dict) -> None:
|
||||
"""
|
||||
更新职级
|
||||
|
||||
@@ -333,52 +299,42 @@ def update_level():
|
||||
Returns:
|
||||
R: 操作结果
|
||||
"""
|
||||
try:
|
||||
# 获取参数
|
||||
json_data, error = parse_request_body()
|
||||
if error:
|
||||
return R.failed(msg=error)
|
||||
|
||||
# 表单验证
|
||||
form = LevelForm(data=json_data)
|
||||
if not form.validate():
|
||||
return R.failed(msg=regular.get_err(form))
|
||||
# 表单验证
|
||||
form = LevelForm(data=data)
|
||||
if not form.validate():
|
||||
raise BizError(regular.get_err(form))
|
||||
|
||||
# 获取职级ID
|
||||
level_id = form.data.get('id')
|
||||
if not level_id or int(level_id) <= 0:
|
||||
return R.failed("职级ID无效")
|
||||
level_id = int(level_id)
|
||||
# 获取职级ID
|
||||
level_id = form.data.get("id")
|
||||
if not level_id or int(level_id) <= 0:
|
||||
raise BizError("职级ID无效")
|
||||
level_id = int(level_id)
|
||||
|
||||
# 复用 get_info 方法验证职级是否存在
|
||||
level = get_info(level_id)
|
||||
if not level:
|
||||
return R.failed("职级不存在")
|
||||
# 复用 get_info 方法验证职级是否存在
|
||||
level = get_info(level_id)
|
||||
if not level:
|
||||
raise BizError("职级不存在")
|
||||
|
||||
# 更新职级信息(移除ID,避免更新主键)
|
||||
form_data = convert_camel_to_snake(form.data.copy())
|
||||
form_data.pop('id', None)
|
||||
# 更新职级信息(移除ID,避免更新主键)
|
||||
form_data = convert_camel_to_snake(form.data.copy())
|
||||
form_data.pop("id", None)
|
||||
|
||||
form_data['update_time'] = datetime.now(tz=timezone.utc)
|
||||
form_data['update_user'] = get_username()
|
||||
form_data["update_time"] = datetime.now(tz=timezone.utc)
|
||||
form_data["update_user"] = get_username()
|
||||
|
||||
result = Level.query.filter_by(id=level_id).update(form_data)
|
||||
result = Level.query.filter_by(id=level_id).update(form_data)
|
||||
|
||||
if not result:
|
||||
return R.failed("更新失败")
|
||||
|
||||
return R.ok(msg="更新成功")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"更新职级异常: {str(e)}")
|
||||
return R.failed(msg="更新职级失败,请稍后重试")
|
||||
if not result:
|
||||
raise BizError("更新失败")
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 职级删除
|
||||
# ============================================================
|
||||
|
||||
def delete_levels(level_ids):
|
||||
|
||||
def delete_levels(level_ids: str) -> int:
|
||||
"""
|
||||
删除职级(批量删除)
|
||||
|
||||
@@ -391,14 +347,18 @@ def delete_levels(level_ids):
|
||||
Returns:
|
||||
R: 操作结果
|
||||
"""
|
||||
return Level.batch_delete_r(level_ids)
|
||||
level_ids_list = parse_id_list(level_ids)
|
||||
if not level_ids_list:
|
||||
raise BizError("无效的记录ID")
|
||||
return Level.batch_delete(level_ids_list)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 职级状态设置
|
||||
# ============================================================
|
||||
|
||||
def update_level_status():
|
||||
|
||||
def update_level_status(data: dict) -> None:
|
||||
"""
|
||||
设置职级状态
|
||||
|
||||
@@ -407,44 +367,33 @@ def update_level_status():
|
||||
Returns:
|
||||
R: 操作结果
|
||||
"""
|
||||
try:
|
||||
# 获取参数
|
||||
json_data, error = parse_request_body()
|
||||
if error:
|
||||
return R.failed(msg=error)
|
||||
|
||||
# 表单验证
|
||||
form = LevelStatusForm(data=json_data)
|
||||
if not form.validate():
|
||||
err_msg = regular.get_err(form)
|
||||
return R.failed(msg=err_msg)
|
||||
# 表单验证
|
||||
form = LevelStatusForm(data=data)
|
||||
if not form.validate():
|
||||
raise BizError(regular.get_err(form))
|
||||
|
||||
level_id = int(form.data['id'])
|
||||
status = int(form.data['status'])
|
||||
level_id = int(form.data["id"])
|
||||
status = int(form.data["status"])
|
||||
|
||||
# 复用 get_info 方法验证职级是否存在
|
||||
level = get_info(level_id)
|
||||
if not level:
|
||||
return R.failed("职级不存在")
|
||||
# 复用 get_info 方法验证职级是否存在
|
||||
level = get_info(level_id)
|
||||
if not level:
|
||||
raise BizError("职级不存在")
|
||||
|
||||
# 更新状态
|
||||
update_data = {"status": status, "update_time": datetime.now(tz=timezone.utc), "update_user": get_username()}
|
||||
result = Level.query.filter_by(id=level_id).update(update_data)
|
||||
# 更新状态
|
||||
update_data = {"status": status, "update_time": datetime.now(tz=timezone.utc), "update_user": get_username()}
|
||||
result = Level.query.filter_by(id=level_id).update(update_data)
|
||||
|
||||
if not result:
|
||||
return R.failed("设置失败")
|
||||
|
||||
return R.ok(msg="设置成功")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"设置职级状态异常: {str(e)}")
|
||||
return R.failed(msg="设置职级状态失败,请稍后重试")
|
||||
if not result:
|
||||
raise BizError("设置失败")
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Excel导入
|
||||
# ============================================================
|
||||
|
||||
|
||||
def import_levels():
|
||||
"""
|
||||
导入Excel文件批量导入职级
|
||||
@@ -462,7 +411,7 @@ def import_levels():
|
||||
try:
|
||||
# 上传并读取Excel文件
|
||||
file = upload.upload_file(".xls|.xlsx")
|
||||
path = file['filePath']
|
||||
path = file["filePath"]
|
||||
|
||||
wb = load_workbook(path)
|
||||
ws = wb.worksheets[0]
|
||||
@@ -502,8 +451,8 @@ def import_levels():
|
||||
finally:
|
||||
# 清理导入产生的临时Excel文件
|
||||
try:
|
||||
if 'path' in dir() and path:
|
||||
abs_path = os.path.join(FLASK_UPLOAD_DIR, path.lstrip('/'))
|
||||
if "path" in dir() and path:
|
||||
abs_path = os.path.join(FLASK_UPLOAD_DIR, path.lstrip("/"))
|
||||
if os.path.isfile(abs_path):
|
||||
os.remove(abs_path)
|
||||
except Exception:
|
||||
@@ -514,6 +463,7 @@ def import_levels():
|
||||
# Excel导出
|
||||
# ============================================================
|
||||
|
||||
|
||||
def export_levels():
|
||||
"""
|
||||
导出职级数据到Excel文件
|
||||
@@ -533,17 +483,17 @@ def export_levels():
|
||||
wb = Workbook()
|
||||
ws = wb.worksheets[0]
|
||||
# 写入表头
|
||||
ws.append(['职级ID', '职级名称', '职级排序', '职级状态', '创建时间', '更新时间'])
|
||||
ws.append(["职级ID", "职级名称", "职级排序", "职级状态", "创建时间", "更新时间"])
|
||||
|
||||
# 写入数据
|
||||
for data in level_list:
|
||||
ws.append(list(data.values()))
|
||||
|
||||
# 保存文件
|
||||
save_path = FLASK_TEMP_PATH + "/" + time.strftime('%Y%m%d')
|
||||
save_path = FLASK_TEMP_PATH + "/" + time.strftime("%Y%m%d")
|
||||
mkdir(save_path)
|
||||
|
||||
file_name = time.strftime('%Y%m%d%H%M%S') + '%05d' % random.randint(0, 100) + ".xlsx"
|
||||
file_name = time.strftime("%Y%m%d%H%M%S") + "%05d" % random.randint(0, 100) + ".xlsx"
|
||||
file_path = save_path + "/" + file_name
|
||||
|
||||
wb.save(file_path)
|
||||
@@ -562,6 +512,7 @@ def export_levels():
|
||||
# 职级列表获取(无分页)
|
||||
# ============================================================
|
||||
|
||||
|
||||
def get_level_list():
|
||||
"""
|
||||
获取所有启用的职级列表(无分页)
|
||||
@@ -574,9 +525,7 @@ def get_level_list():
|
||||
"""
|
||||
try:
|
||||
# 查询所有启用的职级
|
||||
level_list = Level.query.filter(
|
||||
and_(Level.is_delete == 0, Level.status == 1)
|
||||
).order_by(Level.sort.asc()).all()
|
||||
level_list = Level.query.filter(and_(Level.is_delete == 0, Level.status == 1)).order_by(Level.sort.asc()).all()
|
||||
|
||||
# 转换为字典列表
|
||||
result = []
|
||||
|
||||
Reference in New Issue
Block a user