Files
shanxia2.0/backend/app/crud/relation_sync.py
T

58 lines
2.4 KiB
Python

"""按业务键同步系统关联,保留关联 ID,并复用已停用关联。"""
from datetime import datetime
from app.core.utils import generate_uuid
def sync_relations(db, model, tenant_no, owner, key_fields, desired_keys, actor, unique_history=False):
desired = list(dict.fromkeys(desired_keys))
rows = db.query(model).filter(
model.tenant_no == tenant_no,
*(getattr(model, field) == value for field, value in owner.items()),
).with_for_update().all()
grouped = {}
for row in rows:
grouped.setdefault(tuple(getattr(row, f) for f in key_fields), []).append(row)
desired_set = set(desired)
# 历史重复关系需专项修复;不能为规避唯一键而物理删除或静默替换原记录。
for key, matches in grouped.items():
active = [r for r in matches if r.del_flag == 0]
if len(active) > 1 or (unique_history and active and key not in desired_set and len(matches) > 1):
raise ValueError("存在重复的历史关联,请先核查后再调整该关联")
now = datetime.now()
for key, matches in grouped.items():
if key not in desired_set:
for row in matches:
if row.del_flag == 0:
row.del_flag = 1
row.update_by = actor
row.update_time = now
for key in desired:
matches = grouped.get(key, [])
active = next((r for r in matches if r.del_flag == 0), None)
if active is not None:
continue
if matches:
row = sorted(matches, key=lambda r: r.id)[0]
row.del_flag = 0
row.update_by = actor
row.update_time = now
else:
db.add(model(
id=generate_uuid(), tenant_no=tenant_no, **owner,
**dict(zip(key_fields, key)), order_num=0,
create_by=actor, create_dept_id='', create_time=now,
update_by=actor, update_time=now, del_flag=0,
))
def assert_relation_targets(db, model, tenant_no, ids, label):
targets = {value for value in ids or [] if value}
if not targets:
return
found = {row.id for row in db.query(model).filter(
model.id.in_(targets), model.tenant_no == tenant_no, model.del_flag == 0,
).all()}
if targets != found:
raise ValueError(f'{label}不存在、已删除或不属于当前租户')