PayrollManagementSystem/backend/app/services/personnel_roles.py
liuwenxin 1e53792ad6 feat(T+): 完成数据贯通与自动接入闭环
打通 T+ 快照、业务、发货、回款和核算准备链路,保留来源差异并提供待补状态。
新增业务自动接入任务、跨平台读取服务托管、权限复核、来源关联和前端核对页面。
补充迁移、隔离集成测试、浏览器模拟验收及角色授权边界修复。
2026-11-05 18:47:13 +08:00

48 lines
1.8 KiB
Python

"""从已冻结的任职依据取岗位,回补历史工资不改当前人员档案。"""
from sqlalchemy import select
from app.core.exceptions import BadRequestError
from app.models import PayrollInput
def role_on(person, day):
if not person:
return None
month = str(day)[:7]
for period in person.get("role_history", []):
if period["start_month"] <= month <= period["end_month"]:
return period["role_code"]
return person.get("role_code")
def input_role(values, personnel_id, day):
people = values.get("facts", {}).get("personnel", {})
codes = {
role_on(people[source_id], day)
for source_id, target_id in values.get("maps", {}).get("personnel", {}).items()
if target_id == personnel_id and source_id in people
}
if len(codes) > 1:
raise BadRequestError("同一人员的历史岗位依据冲突,请先核实任职资料")
return next(iter(codes), None)
def frozen_roles(session, rows, day):
"""按入结台账引用的资料版本解析任职,冲突时拒绝猜测。"""
inputs = {}
for row in rows:
snapshot = row.snapshot_json or {}
if snapshot.get("engine") == "FIFO" and snapshot.get("input_id"):
inputs.setdefault(snapshot["input_id"], set()).add(row.personnel_id)
result = {}
for record in session.scalars(select(PayrollInput).where(PayrollInput.id.in_(inputs))):
for pid in inputs[record.id]:
role = input_role(record.data_json, pid, day)
if role is None:
raise BadRequestError("月结人员的历史岗位依据缺失,请先核实任职资料")
if pid in result and result[pid] != role:
raise BadRequestError("同一人员的历史岗位依据冲突,请先核实任职资料")
result[pid] = role
return result