"""Models for the canonical organizations directory.""" import uuid from django.db import models from django.db.models import Q from django.utils.translation import gettext_lazy as _ from organizations.name_normalization import normalize_organization_name class Organization(models.Model): """Canonical organization without source-specific relations.""" uid = models.UUIDField( _("UID"), primary_key=True, default=uuid.uuid4, editable=False, ) name = models.CharField( _("наименование"), max_length=1024, db_index=True, help_text=_("Наименование организации или ИП"), ) inn = models.CharField( _("ИНН"), max_length=12, blank=True, db_index=True, help_text=_("ИНН ЮЛ или ИП"), ) kpp = models.CharField( _("КПП"), max_length=9, blank=True, db_index=True, help_text=_("КПП только для юридических лиц"), ) ogrn = models.CharField( _("ОГРН"), max_length=13, blank=True, db_index=True, help_text=_("ОГРН только для юридических лиц"), ) ogrip = models.CharField( _("ОГРИП"), max_length=15, blank=True, db_index=True, help_text=_("ОГРИП только для индивидуальных предпринимателей"), ) class Meta: db_table = "organizations_organization" verbose_name = _("организация") verbose_name_plural = _("организации") ordering = ["name"] indexes = [ models.Index(fields=["inn", "kpp"]), models.Index(fields=["inn", "ogrn"]), models.Index(fields=["inn", "ogrip"]), ] constraints = [ models.UniqueConstraint( fields=["inn", "kpp"], condition=~Q(inn="") & ~Q(kpp=""), name="unique_org_inn_kpp_not_blank", ), models.UniqueConstraint( fields=["inn"], condition=~Q(inn="") & Q(kpp="") & Q(ogrip=""), name="unique_org_inn_without_kpp", ), models.UniqueConstraint( fields=["ogrip"], condition=~Q(ogrip=""), name="unique_organizations_ogrip_not_blank", ), models.CheckConstraint( check=Q(ogrip="") | (Q(kpp="") & Q(ogrn="")), name="check_entrepreneur_has_no_kpp_ogrn", ), ] def __str__(self) -> str: identifier = self.inn or self.ogrn or self.ogrip if identifier: return f"{self.name} ({identifier})" return self.name @property def normalized_name(self) -> str: return normalize_organization_name(self.name) class OrganizationDataSnapshot(models.Model): """Precomputed API v2 data payload for one canonical organization.""" organization = models.OneToOneField( Organization, on_delete=models.CASCADE, primary_key=True, related_name="data_snapshot", verbose_name=_("организация"), ) data = models.JSONField( _("данные источников"), default=dict, help_text=_("Готовый JSON data для API v2"), ) registries = models.JSONField( _("реестры"), default=list, help_text=_("Готовый JSON registries для API v2"), ) updated_at = models.DateTimeField( _("дата обновления"), auto_now=True, db_index=True, ) class Meta: db_table = "organizations_data_snapshot" verbose_name = _("снапшот данных организации") verbose_name_plural = _("снапшоты данных организаций") def __str__(self) -> str: return f"Snapshot for {self.organization_id}"