fc / apps /client /services /client_resolve_service.py
jun2024's picture
Upload 2241 files
b4f2238 verified
Raw History Blame Contribute Delete
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