from app.api.v1.module_rule.rule_category.crud import RuleCategoryCRUD from app.core.base_schema import AuthSchema from app.core.exceptions import CustomException from .crud import RuleCRUD from .schema import RuleCreateSchema, RuleOutSchema, RuleQueryParam, RuleUpdateSchema class RuleService: """规则列表服务""" def __init__(self, auth: AuthSchema) -> None: self.auth = auth async def detail(self, id: int) -> RuleOutSchema: rule = await RuleCRUD(self.auth).get_or_404(id=id) return self._to_out_schema(rule) async def page( self, page_no: int, page_size: int, search: RuleQueryParam | None = None, order_by: list[dict[str, str]] | None = None, ) -> dict: offset = (page_no - 1) * page_size page_result = await RuleCRUD(self.auth).page( offset=offset, limit=page_size, order_by=order_by or [{"id": "desc"}], search=vars(search) if search else None, out_schema=RuleOutSchema, ) for item in page_result.items: item["category_name"] = item.get("category_name_snapshot") return page_result async def get_list( self, search: RuleQueryParam | None = None, order_by: list[dict] | None = None, ) -> list[RuleOutSchema]: rule_list = await RuleCRUD(self.auth).get_list(search=vars(search) if search else None, order_by=order_by or [{"id": "desc"}]) return [self._to_out_schema(rule) for rule in rule_list] async def create(self, data: RuleCreateSchema) -> RuleOutSchema: await self._validate_unique_name(name=data.name) category_name_snapshot = await self._get_category_name_snapshot(category_id=data.category_id) rule = await RuleCRUD(self.auth).create(data={**data.model_dump(), "category_name_snapshot": category_name_snapshot}) return self._to_out_schema(rule) async def update(self, id: int, data: RuleUpdateSchema) -> RuleOutSchema: await RuleCRUD(self.auth).get_or_404(id=id, msg="更新失败,该规则不存在") await self._validate_unique_name(name=data.name, exclude_id=id) category_name_snapshot = await self._get_category_name_snapshot(category_id=data.category_id) rule = await RuleCRUD(self.auth).update(id=id, data={**data.model_dump(), "category_name_snapshot": category_name_snapshot}) return self._to_out_schema(rule) async def delete(self, ids: list[int]) -> None: if len(ids) < 1: raise CustomException(msg="删除失败,删除对象不能为空") rules = await RuleCRUD(self.auth).get_list(search={"id": ("in", ids)}) rule_map = {rule.id: rule for rule in rules} for rule_id in ids: if rule_id not in rule_map: raise CustomException(msg="删除失败,该规则不存在") await RuleCRUD(self.auth).delete(ids=ids) def _to_out_schema(self, rule) -> RuleOutSchema: rule_out = RuleOutSchema.model_validate(rule) rule_out.category_name = rule_out.category_name_snapshot return rule_out async def _validate_unique_name(self, name: str, exclude_id: int | None = None) -> None: rule = await RuleCRUD(self.auth).get(name=name) if rule and rule.id != exclude_id: raise CustomException(msg="规则名称已存在") async def _get_category_name_snapshot(self, category_id: int | None) -> str | None: if category_id is None: return None category = await RuleCategoryCRUD(self.auth).get(id=category_id) if not category: raise CustomException(msg="规则分类不存在") return category.name