"""计提公式模板数据访问。 本层只 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()