from typing import Self from django.db import models from django.utils.translation import gettext_lazy as _ from core.apps.contracts.models.contracts import ContractModel from core.apps.contracts.choices.contracts import ContractOwnerStatus from core.utils.base_model import UUIDPrimaryKeyBaseModel from core.apps.contracts.validators.owners import ( ContractOwnerValidator, LegalEntityValidator, IndividualValidator, name_validator, bin_code_validator, phone_validator, person_code_validator, full_name_validator, iin_code_validator, ) class LegalEntityModel(UUIDPrimaryKeyBaseModel): name = models.CharField( _("Name"), validators=[ name_validator, ], max_length=255, null=False, blank=False, ) role = models.CharField( _("Role"), null=False, blank=False ) bin_code = models.CharField( _("BIN code"), validators=[ bin_code_validator, ], max_length=14, null=True, blank=True, ) identifier = models.CharField( _("Identifier"), max_length=255, null=True, blank=True ) phone = models.CharField( _("Phone"), validators=[ phone_validator ], max_length=25, null=False, blank=False ) def __str__(self): return self.name @classmethod def _create_fake(cls): return cls.objects.create( name="mock", ) @property def entity_code(self) -> str: if self.bin_code is not None: return f"BIN code: {self.bin_code}" else: return f"Identifier: {self.identifier}" def clean(self) -> None: super().clean() validator = LegalEntityValidator(self) validator() class Meta: # type: ignore db_table = "legal_entities" verbose_name = _("Legal Entity") verbose_name_plural = _("Legal Entities") class IndividualModel(UUIDPrimaryKeyBaseModel): full_name = models.CharField( _("name"), validators=[ full_name_validator, ], max_length=512, null=False, blank=False ) iin_code = models.CharField( _("IIN code"), max_length=14, validators=[ iin_code_validator, ], null=True, blank=True, unique=True ) person_code = models.CharField( _("Person Code (if no IIN code)"), validators=[ person_code_validator, ], max_length=64, null=True, blank=True, unique=True ) phone = models.CharField( _("Phone"), validators=[ phone_validator, ], null=False, blank=False ) use_face_id = models.BooleanField( _("Use FaceID"), null=False, blank=False, default=False ) def __str__(self): return self.full_name @classmethod def _create_fake(cls): return cls.objects.create( name="mock", ) @property def individual_code(self) -> str: if self.iin_code is not None: return f"IIN Code: {self.iin_code}" else: return f"Person Code: {self.person_code}" def clean(self): super().clean() validator = IndividualValidator(self) validator() class Meta: # type: ignore db_table = "individuals" verbose_name = _("Individual") verbose_name_plural = _("Individuals") indexes = [ models.Index( fields=["full_name"], name="individuals_fullname_inx" ), models.Index( fields=["iin_code"], name="individuals_iin_inx" ), models.Index( fields=["person_code"], name="individuals_code_inx" ), models.Index( fields=["phone"], name="individuals_phone_inx" ), ] class ContractOwnerModel(UUIDPrimaryKeyBaseModel): legal_entity = models.OneToOneField( LegalEntityModel, related_name="owner", verbose_name=_("Legal Entity"), on_delete=models.PROTECT, null=True, blank=True ) individual = models.OneToOneField( IndividualModel, related_name="owner", verbose_name=_("Individual"), on_delete=models.PROTECT, null=True, blank=True, ) status = models.CharField( _("Owner Status"), max_length=255, choices=ContractOwnerStatus, default=ContractOwnerStatus.PENDING, null=False, blank=True, ) contract = models.ForeignKey( ContractModel, verbose_name=_("Contract"), related_name="owners", on_delete=models.PROTECT, null=False, blank=False ) def clean(self) -> None: super().clean() validator = ContractOwnerValidator(self) validator() def __str__(self) -> str: return str(self.legal_entity or self.individual) @property def owner_name(self) -> str: if self.legal_entity is not None: return str(self.legal_entity) else: return str(self.individual) @property def owner_identity(self) -> str: if self.legal_entity is not None: return _("Legal Entity") else: return _("Individual") @classmethod def _create_fake(cls, mock_individual: bool = True) -> Self: kwargs: dict[str, IndividualModel | LegalEntityModel] = dict() if mock_individual: kwargs["individual"] = IndividualModel._create_fake() # type: ignore else: kwargs["legal_entity"] = LegalEntityModel._create_fake() # type: ignore return cls.objects.create( **kwargs ) class Meta: # type: ignore db_table = "contract_owners" verbose_name = _("Contract Owner") verbose_name_plural = _("Contract Owners") constraints = [ models.UniqueConstraint( fields=["individual", "contract"], name="unique_individual_contract" ), models.UniqueConstraint( fields=["legal_entity", "contract"], name="unique_legal_entity_contract" ), ]