PayrollManagementSystem/backend/app/repositories/param_repository.py
liuwenxin 1b3509b20f feat(system): 计提参数按业务日期时点化取值服务
- param_repository.resolve_values:窗口函数一条 SQL 取全量快照(同日多次变更取 effective_date DESC, id DESC 首条)
- param_service.ParamSnapshot:冻结快照 + 覆盖链(角色 > 产品类别 > 默认行)+ 注册表默认值兜底;fraction/integer/boolean/text 类型化取值
- 12 项单元用例:覆盖链优先级、兜底、同日取最新、冻结不可变

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-12 16:27:56 +08:00

47 lines
1.7 KiB
Python

"""计提参数数据访问。
本层只 flush 不 commit —— 事务边界由 services 层控制。
时点化解析查询(窗口函数版)留存 db/queries/计提参数.sql。
"""
from datetime import date
from sqlalchemy import func, select
from sqlalchemy.orm import Session
from app.models import ParamDefinition, ParamValue
# ==================== 读取 ====================
def resolve_values(session: Session, biz_date: date) -> list[tuple[str, str, str]]:
"""时点化解析:每个 (param_id, dimension_value) 取生效日期 <= 业务日期的最新条目。
排序 (effective_date DESC, id DESC) 保证同日多次变更取最新一条
(不设日期唯一键,同日修正是合法留痕)。仅返回启用状态的参数定义。
返回 (param_code, dimension_value, value_text),供 ParamSnapshot 构造。
"""
row_number = (
func.row_number()
.over(
partition_by=(ParamValue.param_id, ParamValue.dimension_value),
order_by=(ParamValue.effective_date.desc(), ParamValue.id.desc()),
)
.label("rn")
)
subq = (
select(
ParamDefinition.param_code.label("param_code"),
ParamValue.dimension_value.label("dimension_value"),
ParamValue.value_text.label("value_text"),
row_number,
)
.join(ParamDefinition, ParamDefinition.id == ParamValue.param_id)
.where(ParamValue.effective_date <= biz_date, ParamDefinition.status == 1)
.subquery()
)
stmt = select(subq.c.param_code, subq.c.dimension_value, subq.c.value_text).where(
subq.c.rn == 1
)
return [(row.param_code, row.dimension_value, row.value_text) for row in session.execute(stmt)]