fachuan / apps /documents /services /folder_template /command_service.py
jun2024's picture
Upload 2241 files
f8b03c1 verified
Raw History Blame Contribute Delete
6.6 kB
"""Business logic services."""
from __future__ import annotations
from dataclasses import dataclass
from typing import Any
from django.db import transaction
from django.utils.translation import gettext_lazy as _
from apps.core.exceptions import NotFoundError, ValidationException
from apps.documents.models import FolderTemplate
from .repo import FolderTemplateRepo
from .structure_rules import FolderTemplateStructureRules
from .validation_service import FolderTemplateValidationService
@dataclass(frozen=True)
class FolderTemplateCommandService:
repo: FolderTemplateRepo
validation_service: FolderTemplateValidationService
structure_rules: FolderTemplateStructureRules
@transaction.atomic
def create_template( # type: ignore[override]
self,
*,
name: str,
case_type: str,
case_stage: str,
structure: dict[str, Any],
is_default: bool = False,
is_active: bool = True,
**kwargs,
) -> FolderTemplate:
is_valid, error_msg = self.validation_service.validate_structure(structure)
if not is_valid:
raise ValidationException(
message=error_msg,
code="INVALID_STRUCTURE",
errors={"structure": error_msg},
)
is_valid, errors = self.structure_rules.validate_structure_ids(structure)
if not is_valid:
raise ValidationException(
message=_("文件夹结构验证失败"),
code="INVALID_STRUCTURE",
errors={"validation_errors": errors},
)
from apps.documents.models import FolderTemplateType
return self.repo.create(
name=name,
template_type=kwargs.pop("template_type", FolderTemplateType.CASE),
case_types=kwargs.pop("case_types", [case_type] if case_type else []),
case_stages=kwargs.pop("case_stages", [case_stage] if case_stage else []),
contract_types=kwargs.pop("contract_types", []),
structure=structure,
is_default=is_default,
is_active=is_active,
**kwargs,
)
@transaction.atomic
def update_structure(self, *, template_id: int, structure: dict[str, Any]) -> FolderTemplate:
try:
template = self.repo.get_by_id(template_id)
except FolderTemplate.DoesNotExist:
raise NotFoundError(
message=_("文件夹模板不存在"),
code="FOLDER_TEMPLATE_NOT_FOUND",
errors={"template_id": f"ID 为 {template_id} 的模板不存在"},
) from None
is_valid, error_msg = self.validation_service.validate_structure(structure)
if not is_valid:
raise ValidationException(
message=error_msg,
code="INVALID_STRUCTURE",
errors={"structure": error_msg},
)
is_valid, errors = self.structure_rules.validate_structure_ids(structure, template_id)
if not is_valid:
raise ValidationException(
message=_("文件夹结构验证失败"),
code="INVALID_STRUCTURE",
errors={"validation_errors": errors},
)
template.structure = structure
template.save(update_fields=["structure", "updated_at"])
self._clear_folder_template_cache()
return template
def _clear_folder_template_cache(self) -> None:
"""清除文件夹模板缓存"""
from apps.core.infrastructure import CacheKeys, CacheTimeout, bump_cache_version
bump_cache_version(CacheKeys.documents_matching_version_folder_templates(), timeout=CacheTimeout.get_day())
@transaction.atomic
def delete_template(self, *, template_id: int) -> bool:
try:
template = self.repo.get_by_id(template_id)
except FolderTemplate.DoesNotExist:
raise NotFoundError(
message=_("文件夹模板不存在"),
code="FOLDER_TEMPLATE_NOT_FOUND",
errors={"template_id": f"ID 为 {template_id} 的模板不存在"},
) from None
template.is_active = False
template.save(update_fields=["is_active", "updated_at"])
self._clear_folder_template_cache()
return True
def create_template_from_dict(self, *, data: dict[str, Any]) -> FolderTemplate:
name = data.get("name", "")
case_type = data.get("case_type", "")
case_stage = data.get("case_stage", "")
structure = data.get("structure", {})
is_default = bool(data.get("is_default", False))
is_active = bool(data.get("is_active", True))
extra: dict[str, Any] = {}
for field in ["template_type", "case_types", "case_stages", "contract_types"]:
if field in data and data[field] is not None:
extra[field] = data[field]
return self.create_template(
name=name,
case_type=case_type,
case_stage=case_stage,
structure=structure,
is_default=is_default,
is_active=is_active,
**extra,
)
def update_template_from_dict(self, *, template_id: int, data: dict[str, Any]) -> FolderTemplate:
template = self.get_template_or_404(template_id)
new_structure = data.get("structure")
if new_structure is not None:
template = self.update_structure(template_id=template_id, structure=new_structure)
else:
template = template
update_fields: list[Any] = []
for field in [
"name",
"is_default",
"is_active",
"case_types",
"case_stages",
"contract_types",
"template_type",
]:
if field in data and data[field] is not None:
setattr(template, field, data[field])
update_fields.append(field)
if update_fields:
template.save(update_fields=update_fields + ["updated_at"])
self._clear_folder_template_cache()
return template
def get_template_or_404(self, template_id: int) -> FolderTemplate:
try:
return self.repo.get_by_id(template_id)
except FolderTemplate.DoesNotExist:
raise NotFoundError(
message=_("文件夹模板不存在"),
code="FOLDER_TEMPLATE_NOT_FOUND",
errors={"template_id": f"ID 为 {template_id} 的模板不存在"},
) from None