Download apps/client/services/client_resolve_service.py from jun2024/fc: direct link, hf CLI and curl.
- Browser
- Download file 3.65 kB
-
https://huggingface.co/spaces/jun2024/fc/resolve/main/apps/client/services/client_resolve_service.py
- Command line
-
hf download hf://spaces/jun2024/fc/apps/client/services/client_resolve_service.py
-
curl -L -o client_resolve_service.py https://huggingface.co/spaces/jun2024/fc/resolve/main/apps/client/services/client_resolve_service.py
3.65 kB
| """当事人 get_or_create 解析服务(用于 JSON 导入)。""" | |
| from __future__ import annotations | |
| import logging | |
| from typing import TYPE_CHECKING, Any | |
| from django.utils.translation import gettext_lazy as _ | |
| from apps.client.models import Client, ClientIdentityDoc | |
| from apps.client.services.importer.validator import ClientJsonImportValidator | |
| from apps.core.exceptions import ValidationException | |
| if TYPE_CHECKING: | |
| pass | |
| logger = logging.getLogger("apps.client") | |
| _CLIENT_FIELDS: tuple[str, ...] = ( | |
| "name", | |
| "phone", | |
| "address", | |
| "client_type", | |
| "id_number", | |
| "legal_representative", | |
| "legal_representative_id_number", | |
| "is_our_client", | |
| ) | |
| class ClientResolveService: | |
| """按 id_number get_or_create Client,维护会话内缓存避免重复创建。""" | |
| def __init__(self) -> None: | |
| self._cache: dict[str, Client] = {} | |
| self._validator = ClientJsonImportValidator() | |
| def resolve(self, data: dict[str, Any]) -> Client: | |
| id_number: str | None = data.get("id_number") or None | |
| # 有 id_number 时先查缓存再查库 | |
| if id_number: | |
| if id_number in self._cache: | |
| return self._cache[id_number] | |
| existing = Client.objects.filter(id_number=id_number).first() | |
| if existing: | |
| self._cache[id_number] = existing | |
| logger.info("复用已有当事人", extra={"client_id": existing.pk, "id_number": id_number}) | |
| return existing | |
| # 校验 | |
| try: | |
| self._validator.validate(data) | |
| except ValidationException as exc: | |
| raise ValidationException( | |
| message=_("当事人数据验证失败: %(name)s") % {"name": data.get("name", "")}, | |
| code="INVALID_CLIENT_DATA", | |
| errors=exc.errors, | |
| ) from exc | |
| client_data = {f: data[f] for f in _CLIENT_FIELDS if f in data} | |
| client_data.setdefault("is_our_client", False) | |
| # 空字符串 id_number 转 None,避免 unique 冲突 | |
| if not client_data.get("id_number"): | |
| client_data["id_number"] = None | |
| client = Client.objects.create(**client_data) | |
| if id_number: | |
| self._cache[id_number] = client | |
| logger.info("创建新当事人", extra={"client_id": client.pk, "client_name": client.name}) | |
| return client | |
| def resolve_with_attachments(self, data: dict[str, Any]) -> Client: | |
| """resolve Client 并还原 identity_docs 和 property_clues(含附件)。""" | |
| from apps.client.models import PropertyClue, PropertyClueAttachment | |
| client = self.resolve(data) | |
| for doc in data.get("identity_docs") or []: | |
| if doc.get("file_path"): | |
| ClientIdentityDoc.objects.get_or_create( | |
| client=client, | |
| file_path=doc["file_path"], | |
| defaults={"doc_type": doc.get("doc_type", "id_card_front")}, | |
| ) | |
| for clue in data.get("property_clues") or []: | |
| pc, _created = PropertyClue.objects.get_or_create( | |
| client=client, | |
| clue_type=clue.get("clue_type", "other"), | |
| defaults={"content": clue.get("content", "")}, | |
| ) | |
| for att in clue.get("attachments") or []: | |
| if att.get("file_path"): | |
| PropertyClueAttachment.objects.get_or_create( | |
| property_clue=pc, | |
| file_path=att["file_path"], | |
| defaults={"file_name": att.get("file_name", "")}, | |
| ) | |
| return client | |