按 2026-11-02 需求补齐计划交付后端能力: - 角色授权:权限目录化,接口统一准入校验,未登记默认拒绝; 管理员判断改为按数据库角色重新判定,防止权限码持有者绕过 - 系统监控:单进程采集资源、请求与异常指标,分钟级聚合, 阈值配置化;敏感配置增加 repr 保护,Redis 密码 URL 转义 - 试用期计提:按回款日判定并写入快照,年度结清与调整单联动; 人员模型补试用期、离职日期与工资版本历史字段 - 计提模板:公式骨架受控,页面维护名称与参数绑定 - T+ 采集:自动化配置表与进度查询 内置角色禁停用保护对齐模块注释;核算规则版本提为常量并 补充批量核算失败堆栈日志。 影响范围:后端全部模块、数据库迁移 V22-V28 验证:uv run ruff check 通过;922 个单元测试全部通过; 集成测试因本机 MySQL 数据卷被其他容器锁定暂未运行
67 lines
2.5 KiB
Python
67 lines
2.5 KiB
Python
"""计提公式模板数据访问。
|
|
|
|
本层只 flush 不 commit —— 事务边界由 services 层控制。
|
|
"""
|
|
|
|
from sqlalchemy import func, select
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.models import BusinessRole, CalcTemplateDefinition
|
|
|
|
|
|
def get_by_id(session: Session, template_id: int, *, for_update: bool = False) -> CalcTemplateDefinition | None:
|
|
"""按主键查询;删除校验走行锁。"""
|
|
if for_update:
|
|
stmt = select(CalcTemplateDefinition).where(CalcTemplateDefinition.id == template_id).with_for_update()
|
|
return session.execute(stmt).scalar_one_or_none()
|
|
return session.get(CalcTemplateDefinition, template_id)
|
|
|
|
|
|
def get_by_code(session: Session, template_code: str) -> CalcTemplateDefinition | None:
|
|
"""按编码查询模板。编码是岗位绑定与参数解析的锚点。"""
|
|
stmt = select(CalcTemplateDefinition).where(CalcTemplateDefinition.template_code == template_code)
|
|
return session.execute(stmt).scalar_one_or_none()
|
|
|
|
|
|
def list_all(session: Session) -> list[CalcTemplateDefinition]:
|
|
"""全部模板(含停用,供管理列表展示引用状态)。"""
|
|
stmt = select(CalcTemplateDefinition).order_by(
|
|
CalcTemplateDefinition.sort_order, CalcTemplateDefinition.id
|
|
)
|
|
return list(session.execute(stmt).scalars())
|
|
|
|
|
|
def list_active(session: Session) -> list[CalcTemplateDefinition]:
|
|
"""启用模板,供岗位表单下拉。"""
|
|
stmt = (
|
|
select(CalcTemplateDefinition)
|
|
.where(CalcTemplateDefinition.status == 1)
|
|
.order_by(CalcTemplateDefinition.sort_order, CalcTemplateDefinition.id)
|
|
)
|
|
return list(session.execute(stmt).scalars())
|
|
|
|
|
|
def count_roles_by_codes(session: Session, codes: list[str]) -> dict[str, int]:
|
|
"""批量统计各模板被岗位引用的数量,用于删除保护与列表展示。"""
|
|
if not codes:
|
|
return {}
|
|
rows = session.execute(
|
|
select(BusinessRole.calc_template, func.count(BusinessRole.id))
|
|
.where(BusinessRole.calc_template.in_(codes))
|
|
.group_by(BusinessRole.calc_template)
|
|
).all()
|
|
return {code: int(count) for code, count in rows}
|
|
|
|
|
|
def create(session: Session, template: CalcTemplateDefinition) -> CalcTemplateDefinition:
|
|
"""新增模板。只 flush 以取得自增 id。"""
|
|
session.add(template)
|
|
session.flush()
|
|
return template
|
|
|
|
|
|
def delete(session: Session, template: CalcTemplateDefinition) -> None:
|
|
"""删除模板。调用方须先完成保护规则校验。"""
|
|
session.delete(template)
|
|
session.flush()
|