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

34 lines
1.7 KiB
Python

"""批量补充空分类,不覆盖已有分类或冻结资料。"""
from sqlalchemy import select, update
from app.core.exceptions import BadRequestError
from app.models import BusinessItem, Customer, PayrollInput, Product
from app.services.audit_service import AuditRecord, audit
def fill_missing_product_items(session, product_ids, category):
"""补齐未封存业务的空分类,保留既有分类及历史核算依据。"""
frozen = select(PayrollInput.id).where(PayrollInput.business_id == BusinessItem.business_id).exists()
session.execute(update(BusinessItem).where(
BusinessItem.product_id.in_(product_ids), BusinessItem.product_category.is_(None), ~frozen,
).values(product_category=category))
def fill_missing(session, model, payload, actor, meta=None):
field = Customer.customer_type if model is Customer else Product.product_category
module = "客户管理" if model is Customer else "产品管理"
with audit(session, operator=actor, meta=meta, record=AuditRecord(
module=module, action="批量补充分类", summary=f"批量补充 {len(payload.ids)} 条档案分类",
request_data=payload.model_dump(mode="json"),
)):
rows = list(session.scalars(select(model).where(model.id.in_(payload.ids)).order_by(model.id).with_for_update()))
if len(rows) != len(payload.ids) or any(getattr(row, field.key) is not None for row in rows):
raise BadRequestError("所选档案不存在或分类已变化,请刷新后重新选择")
for row in rows:
setattr(row, field.key, payload.category)
if model is Product:
fill_missing_product_items(session, payload.ids, payload.category)
session.commit()
return {"updated": len(rows)}