"""业务表单参照只返回必要字段,不借下拉权限开放整个资料接口。""" from sqlalchemy import select from app.core.exceptions import BadRequestError, ForbiddenError from app.models import ( Business, BusinessRole, CalcTemplateDefinition, Customer, CustomerRatingGrade, Personnel, Product, Shipment, ) from app.services.authorization_service import calculate OPTIONS = { "managers": (Personnel, ("id", "personnel_name", "business_role_id", "status"), ( "base:personnel:view", "base:personnel:create", "base:personnel:update", )), "rating_grades": (CustomerRatingGrade, ("id", "grade_name", "min_score", "max_score", "sort_order", "remark"), ( "base:customers:view", "base:customers:rating", "business:ratings:view", )), "personnel": (Personnel, ("id", "personnel_name", "business_role_id", "status"), ( "base:personnel:view", "base:customers:view", "base:customers:create", "base:customers:update", "base:customers:ownership", "business:businesses:view", "business:businesses:create", "business:businesses:update", "business:businesses:ownership", "payroll:prepare", "adjustments:create", "payroll:view", "reports:personal:view", "reports:department:view", "reports:business:view", "reports:payments:view", )), "customers": (Customer, ("id", "company_name", "customer_type"), ( "base:customers:view", "business:businesses:view", "business:businesses:create", "business:businesses:update", "reports:business:view", )), "products": (Product, ("id", "product_name", "spec_model", "unit"), ( "base:products:view", "business:businesses:create", "business:businesses:update", "business:shipments:create", "business:shipments:update", )), "businesses": (Business, ("id", "business_no", "status"), ( "business:businesses:view", "business:shipments:view", "business:shipments:create", "business:shipments:update", "business:receipts:view", "business:receipts:create", "business:receipts:update", )), "shipments": (Shipment, ("id", "shipment_no", "business_id", "ship_date"), ( "business:shipments:view", "business:receipts:view", "business:receipts:create", "business:receipts:update", )), "business_roles": (BusinessRole, ("id", "role_code", "role_name", "status"), ( "base:personnel:view", "base:personnel:create", "base:personnel:update", "system:business_roles:view", "system:params:view", "reports:personal:view", "reports:department:view", "reports:business:view", "reports:payments:view", )), } def payroll_options(session, actor, business_id): """核算资料所需的人员及发货明细,不开放人员薪酬或联系方式。""" from app.core.exceptions import NotFoundError from app.models import ShipmentItem from app.services.authorization_service import require_permission require_permission(session, actor, "payroll:view") if session.get(Business, business_id) is None: raise NotFoundError("业务不存在") heads = list(session.scalars(select(Shipment).where(Shipment.business_id == business_id).order_by(Shipment.id).limit(201))) if len(heads) > 200: raise BadRequestError("单笔业务超过 200 张发货单,请分批核对资料") people = [dict(row) for row in session.execute(select(Personnel.id, Personnel.personnel_name).order_by(Personnel.id).limit(201)).mappings()] if len(people) > 200: raise BadRequestError("核算人员超过单次范围,请按实际归属分批处理") lines = session.execute(select(ShipmentItem.id, ShipmentItem.shipment_id, ShipmentItem.product_name, ShipmentItem.amount).where(ShipmentItem.shipment_id.in_([h.id for h in heads]))).mappings() by_head = {head.id: head for head in heads} return {"personnel": people, "shipments": [ {"id": row["id"], "shipment_no": by_head[row["shipment_id"]].shipment_no, "ship_date": str(by_head[row["shipment_id"]].ship_date), "product_name": row["product_name"], "amount": str(row["amount"])} for row in lines ]} def options(session, actor, resource, *, business_id=None, search=None): definition = OPTIONS.get(resource) if definition is None: raise BadRequestError("不支持的参照类型") model, fields, callers = definition if not set(calculate(session, actor)["permissions"]) & set(callers): raise ForbiddenError("没有使用此参照数据的业务权限") statement = select(*(getattr(model, f) for f in fields)) if resource == "managers": statement = ( statement.join(BusinessRole, BusinessRole.id == Personnel.business_role_id) .join(CalcTemplateDefinition, CalcTemplateDefinition.template_code == BusinessRole.calc_template) .where( Personnel.status == 1, BusinessRole.status == 1, CalcTemplateDefinition.formula_type == "manager_share", ) ) if business_id is not None and model == Shipment: statement = statement.where(Shipment.business_id == business_id) if search: name = getattr(model, fields[1]) escaped = search.replace("\\", "\\\\").replace("%", "\\%").replace("_", "\\_") statement = statement.where(name.like(f"%{escaped}%", escape="\\")) order = (model.sort_order, model.id) if model == CustomerRatingGrade else (model.id,) rows = session.execute(statement.order_by(*order).limit(200)).mappings() return [dict(row) for row in rows]