add: contract create serializer, TODO: fix errors with owners create and test
This commit is contained in:
@@ -1,8 +1,21 @@
|
||||
from rest_framework import serializers
|
||||
from rest_framework import serializers # type: ignore
|
||||
from rest_framework.generics import ValidationError # type: ignore
|
||||
from django.utils.translation import gettext as _
|
||||
from django.db import transaction
|
||||
|
||||
from core.apps.contracts.models import ContractModel
|
||||
|
||||
from core.apps.contracts.serializers.attached_files import (
|
||||
CreateContractAttachedFileSerializer
|
||||
)
|
||||
from core.apps.contracts.serializers.owners import (
|
||||
CreateContractOwnerSerializer,
|
||||
)
|
||||
|
||||
|
||||
###########################################################
|
||||
# Base Serializers
|
||||
###########################################################
|
||||
class BaseContractSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = ContractModel
|
||||
@@ -14,6 +27,9 @@ class BaseContractSerializer(serializers.ModelSerializer):
|
||||
)
|
||||
|
||||
|
||||
###########################################################
|
||||
# List Serializers
|
||||
###########################################################
|
||||
class ListContractSerializer(BaseContractSerializer):
|
||||
class Meta(BaseContractSerializer.Meta):
|
||||
fields = (
|
||||
@@ -25,18 +41,114 @@ class ListContractSerializer(BaseContractSerializer):
|
||||
)
|
||||
|
||||
|
||||
###########################################################
|
||||
# Detail/Retrieve Serializers
|
||||
###########################################################
|
||||
class RetrieveContractSerializer(BaseContractSerializer):
|
||||
class Meta(BaseContractSerializer.Meta): ...
|
||||
|
||||
|
||||
class CreateContractSerializer(BaseContractSerializer):
|
||||
class Meta(BaseContractSerializer.Meta): ...
|
||||
|
||||
|
||||
###########################################################
|
||||
# Update Serializers
|
||||
###########################################################
|
||||
class UpdateContractSerializer(BaseContractSerializer):
|
||||
class Meta(BaseContractSerializer.Meta): ...
|
||||
|
||||
|
||||
###########################################################
|
||||
# Delete/Destroy Serializers
|
||||
###########################################################
|
||||
class DestroyContractSerializer(BaseContractSerializer):
|
||||
class Meta(BaseContractSerializer.Meta):
|
||||
fields = ["id"]
|
||||
|
||||
|
||||
###########################################################
|
||||
# Create Serializers
|
||||
###########################################################
|
||||
class CreateOwnersForContractSerializer(CreateContractOwnerSerializer):
|
||||
class Meta(CreateContractOwnerSerializer.Meta):
|
||||
read_only_fields = (
|
||||
*CreateContractOwnerSerializer.Meta.read_only_fields,
|
||||
"contract",
|
||||
)
|
||||
|
||||
def create(self, validated_data: dict[str, object]) -> Meta.model:
|
||||
contract = self.context.get("contract")
|
||||
contract_id = self.context.get("contract_id")
|
||||
|
||||
context_data: dict[str, object] = {}
|
||||
|
||||
if contract is None and contract_id is None:
|
||||
raise ValidationError(_("Either contract or contract_id should be given in context."))
|
||||
|
||||
if contract is not None:
|
||||
context_data["contract"] = contract
|
||||
else:
|
||||
context_data["contract_id"] = contract_id
|
||||
|
||||
return super().create(
|
||||
validated_data | context_data
|
||||
)
|
||||
|
||||
|
||||
class CreateContractAttachedFileForContractSerializer(CreateContractAttachedFileSerializer):
|
||||
class Meta(CreateContractAttachedFileSerializer.Meta): ...
|
||||
|
||||
def create(self, validated_data: dict[str, object]) -> Meta.model:
|
||||
contract = self.context.get("contract")
|
||||
contract_id = self.context.get("contract_id")
|
||||
|
||||
context_data: dict[str, object] = {}
|
||||
|
||||
if contract is None and contract_id is None:
|
||||
raise ValidationError(_("Either contract or contract_id should be given in context."))
|
||||
|
||||
if contract is not None:
|
||||
context_data["contract"] = contract
|
||||
else:
|
||||
context_data["contract_id"] = contract_id
|
||||
|
||||
return super().create( # type: ignore
|
||||
validated_data | context_data
|
||||
)
|
||||
|
||||
|
||||
class CreateContractSerializer(BaseContractSerializer):
|
||||
owners = CreateOwnersForContractSerializer(many=True)
|
||||
attached_files = CreateContractAttachedFileForContractSerializer(
|
||||
many=True, default=list, required=False
|
||||
)
|
||||
|
||||
class Meta(BaseContractSerializer.Meta):
|
||||
pass
|
||||
|
||||
def validate_owners(self, owners: list[dict[str, object]]) -> list[dict[str, object]]:
|
||||
if not owners:
|
||||
raise ValidationError("Contract should have minimum one owner.")
|
||||
return owners
|
||||
|
||||
def create(self, validated_data: dict[str, object]) -> Meta.model:
|
||||
attached_files_data = validated_data.pop("attached_files", None)
|
||||
owners_data = validated_data.pop("owners", None)
|
||||
|
||||
with transaction.atomic():
|
||||
contract = self.Meta.model()
|
||||
contract.save()
|
||||
|
||||
owners = CreateOwnersForContractSerializer(
|
||||
data=owners_data, many=True, context=self.context | {"contract": contract}
|
||||
)
|
||||
owners.is_valid(raise_exception=True)
|
||||
owners.save() # type: ignore
|
||||
|
||||
if attached_files_data:
|
||||
attached_files = CreateContractAttachedFileForContractSerializer(
|
||||
data=attached_files_data, many=True, context=self.context | {"contract": contract}
|
||||
)
|
||||
attached_files.is_valid(raise_exception=True)
|
||||
attached_files.save() # type: ignore
|
||||
|
||||
return contract
|
||||
|
||||
|
||||
|
||||
@@ -1,22 +1,19 @@
|
||||
from rest_framework import serializers
|
||||
from rest_framework import serializers # type: ignore
|
||||
from rest_framework.exceptions import ValidationError # type: ignore
|
||||
|
||||
from core.apps.contracts.models import (
|
||||
ContractOwnerModel,
|
||||
LegalEntityModel,
|
||||
IndividualModel,
|
||||
)
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from django.db import transaction
|
||||
|
||||
# from core.apps.contracts.serializers.attached_files import (
|
||||
# BaseContractAttachedFileSerializer,
|
||||
# )
|
||||
# from core.apps.contracts.serializers.file_contents import (
|
||||
# BaseContractFileContentSerializer
|
||||
# )
|
||||
|
||||
|
||||
#! TODO fix: BaseContractOwnerSerializer (.create/.update) fix
|
||||
###########################################################
|
||||
# Base Serializers
|
||||
###########################################################
|
||||
class BaseIndividualSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = IndividualModel
|
||||
@@ -25,26 +22,7 @@ class BaseIndividualSerializer(serializers.ModelSerializer):
|
||||
"id",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
)
|
||||
extra_kwargs = {
|
||||
"iin_code": {
|
||||
"required": False
|
||||
},
|
||||
"person_code": {
|
||||
"required": False
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
class ListIndividualSerializer(BaseIndividualSerializer):
|
||||
class Meta(BaseIndividualSerializer.Meta):
|
||||
fields = (
|
||||
"id",
|
||||
"full_name",
|
||||
"phone",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
"owner",
|
||||
)
|
||||
|
||||
|
||||
@@ -56,26 +34,7 @@ class BaseLegalEntitySerializer(serializers.ModelSerializer):
|
||||
"id",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
)
|
||||
extra_kwargs = {
|
||||
"bin_code": {
|
||||
"required": False
|
||||
},
|
||||
"identifier": {
|
||||
"required": False
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
class ListLegalEntitySerializer(BaseLegalEntitySerializer):
|
||||
class Meta(BaseLegalEntitySerializer.Meta):
|
||||
fields = (
|
||||
"id",
|
||||
"name",
|
||||
"phone",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
"owner",
|
||||
)
|
||||
|
||||
|
||||
@@ -92,62 +51,35 @@ class BaseContractOwnerSerializer(serializers.ModelSerializer):
|
||||
"updated_at",
|
||||
)
|
||||
extra_kwargs = {
|
||||
"legal_entity": {
|
||||
"required": False
|
||||
},
|
||||
"individual": {
|
||||
"required": False
|
||||
}
|
||||
'legal_entity': {'required': False, 'allow_null': True},
|
||||
'individual': {'required': False, 'allow_null': True},
|
||||
}
|
||||
|
||||
def create(self, validated_data):
|
||||
legal_entity_data = validated_data.pop("legal_entity", None)
|
||||
individual_data = validated_data.pop("individual", None)
|
||||
|
||||
with transaction.atomic():
|
||||
if legal_entity_data is not None:
|
||||
legal_entity_serializer = BaseLegalEntitySerializer(data=legal_entity_data)
|
||||
legal_entity_serializer.is_valid(raise_exception=True)
|
||||
validated_data["legal_entity"] = legal_entity_serializer.save()
|
||||
###########################################################
|
||||
# List Serializers
|
||||
###########################################################
|
||||
class ListIndividualSerializer(BaseIndividualSerializer):
|
||||
class Meta(BaseIndividualSerializer.Meta):
|
||||
fields = (
|
||||
"id",
|
||||
"full_name",
|
||||
"phone",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
)
|
||||
|
||||
if individual_data is not None:
|
||||
individual_serializer = BaseIndividualSerializer(data=individual_data)
|
||||
individual_serializer.is_valid(raise_exception=True)
|
||||
validated_data["individual"] = individual_serializer.save()
|
||||
|
||||
contract_owner = ContractOwnerModel.objects.create(**validated_data)
|
||||
return contract_owner
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
legal_entity_data = validated_data.pop("legal_entity", None)
|
||||
individual_data = validated_data.pop("individual", None)
|
||||
class ListLegalEntitySerializer(BaseLegalEntitySerializer):
|
||||
class Meta(BaseLegalEntitySerializer.Meta):
|
||||
fields = (
|
||||
"id",
|
||||
"name",
|
||||
"phone",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
)
|
||||
|
||||
with transaction.atomic():
|
||||
if legal_entity_data is not None:
|
||||
if instance.legal_entity:
|
||||
for attr, value in legal_entity_data.items():
|
||||
setattr(instance.legal_entity, attr, value)
|
||||
instance.legal_entity.save()
|
||||
else:
|
||||
legal_entity = LegalEntityModel.objects.create(**legal_entity_data)
|
||||
instance.legal_entity = legal_entity
|
||||
|
||||
if individual_data is not None:
|
||||
if instance.individual:
|
||||
for attr, value in individual_data.items():
|
||||
setattr(instance.individual, attr, value)
|
||||
instance.individual.save()
|
||||
else:
|
||||
individual = IndividualModel.objects.create(**individual_data)
|
||||
instance.individual = individual
|
||||
|
||||
# Update ContractOwnerModel fields
|
||||
for attr, value in validated_data.items():
|
||||
setattr(instance, attr, value)
|
||||
instance.save()
|
||||
|
||||
return instance
|
||||
|
||||
|
||||
class ListContractOwnerSerializer(BaseContractOwnerSerializer):
|
||||
legal_entity = ListLegalEntitySerializer(read_only=True)
|
||||
@@ -156,19 +88,125 @@ class ListContractOwnerSerializer(BaseContractOwnerSerializer):
|
||||
class Meta(BaseContractOwnerSerializer.Meta): ...
|
||||
|
||||
|
||||
###########################################################
|
||||
# Detail/Retrieve Serializers
|
||||
###########################################################
|
||||
class RetrieveContractOwnerSerializer(BaseContractOwnerSerializer):
|
||||
class Meta(BaseContractOwnerSerializer.Meta): ...
|
||||
|
||||
|
||||
class CreateContractOwnerSerializer(BaseContractOwnerSerializer):
|
||||
class Meta(BaseContractOwnerSerializer.Meta): ...
|
||||
###########################################################
|
||||
# Update Serializers
|
||||
###########################################################
|
||||
class UpdateIndividualSeriailzer(BaseIndividualSerializer):
|
||||
class Meta(BaseIndividualSerializer.Meta): ...
|
||||
|
||||
|
||||
class UpdateLegalEntitySerializer(BaseLegalEntitySerializer):
|
||||
class Meta(BaseLegalEntitySerializer.Meta): ...
|
||||
|
||||
|
||||
class UpdateContractOwnerSerializer(BaseContractOwnerSerializer):
|
||||
individual = UpdateIndividualSeriailzer(required=False, partial=True)
|
||||
legal_entity = UpdateLegalEntitySerializer(required=False, partial=True)
|
||||
|
||||
class Meta(BaseContractOwnerSerializer.Meta): ...
|
||||
|
||||
def update(self, instance: Meta.model, validated_data: dict[str, object]):
|
||||
individual_data = validated_data.pop("individual", None)
|
||||
legal_entity_data = validated_data.pop("legal_entity", None)
|
||||
|
||||
if instance.individual is not None:
|
||||
if individual_data is not None:
|
||||
individual_serializer = UpdateIndividualSeriailzer(
|
||||
instance=instance.individual,
|
||||
data=individual_data,
|
||||
partial=True,
|
||||
)
|
||||
individual_serializer.is_valid(raise_exception=True)
|
||||
individual_serializer.save() # type: ignore
|
||||
|
||||
elif instance.legal_entity is not None:
|
||||
if legal_entity_data is not None:
|
||||
legal_entity_serializer = UpdateLegalEntitySerializer(
|
||||
instance=instance.legal_entity,
|
||||
data=legal_entity_data,
|
||||
partial=True
|
||||
)
|
||||
legal_entity_serializer.is_valid(raise_exception=True)
|
||||
legal_entity_serializer.save() # type: ignore
|
||||
|
||||
return super().update(instance, validated_data) # type: ignore
|
||||
|
||||
|
||||
###########################################################
|
||||
# Delete/Destroy Serializers
|
||||
###########################################################
|
||||
class DestroyContractOwnerSerializer(BaseContractOwnerSerializer):
|
||||
class Meta(BaseContractOwnerSerializer.Meta):
|
||||
fields = ["id"]
|
||||
|
||||
|
||||
|
||||
###########################################################
|
||||
# Create Serializers
|
||||
###########################################################
|
||||
class CreateIndividualSerializer(BaseIndividualSerializer):
|
||||
class Meta(BaseIndividualSerializer.Meta): ...
|
||||
|
||||
|
||||
class CreateLegalEntitySerializer(BaseLegalEntitySerializer):
|
||||
class Meta(BaseLegalEntitySerializer.Meta): ...
|
||||
|
||||
|
||||
class CreateContractOwnerSerializer(BaseContractOwnerSerializer): #! TODO: problem: individual or legal entity can not be null
|
||||
individual = CreateIndividualSerializer(required=False, allow_null=True, default=None)
|
||||
legal_entity = CreateLegalEntitySerializer(required=False, allow_null=True, default=None)
|
||||
|
||||
class Meta(BaseContractOwnerSerializer.Meta):
|
||||
read_only_fields = (
|
||||
*BaseContractOwnerSerializer.Meta.read_only_fields,
|
||||
"status"
|
||||
)
|
||||
|
||||
def create(self, validated_data: dict[str, object]) -> Meta.model:
|
||||
individual_data = validated_data.pop("individual", None)
|
||||
legal_entity_data = validated_data.pop("legal_entity", None)
|
||||
|
||||
with transaction.atomic():
|
||||
if individual_data is not None:
|
||||
individual_serializer = CreateIndividualSerializer(data=individual_data)
|
||||
individual_serializer.is_valid(raise_exception=True)
|
||||
validated_data["individual"] = individual_serializer.save() # type: ignore
|
||||
|
||||
if legal_entity_data is not None:
|
||||
legal_entity_serializer = CreateLegalEntitySerializer(data=legal_entity_data)
|
||||
legal_entity_serializer.is_valid(raise_exception=True)
|
||||
validated_data["legal_entity"] = legal_entity_serializer.save() # type: ignore
|
||||
|
||||
owner = self.Meta.model(**validated_data)
|
||||
owner.save()
|
||||
return owner
|
||||
|
||||
def to_internal_value(self, data: dict[str, object]) -> dict[str, object]:
|
||||
data = data.copy()
|
||||
|
||||
if "legal_entity" in data and data["legal_entity"] in [None, ""]:
|
||||
data["legal_entity"] = None
|
||||
|
||||
if "individual" in data and data["individual"] in [None, ""]:
|
||||
data["individual"] = None
|
||||
|
||||
return super().to_internal_value(data) # type: ignore
|
||||
|
||||
def validate(self, attrs: dict[str, object]):
|
||||
legal = attrs.get("legal_entity")
|
||||
individual = attrs.get("individual")
|
||||
|
||||
# Optional: enforce at least one must be provided
|
||||
if not legal and not individual:
|
||||
raise serializers.ValidationError(
|
||||
"Either legal_entity or individual must be provided."
|
||||
)
|
||||
|
||||
return attrs
|
||||
|
||||
Reference in New Issue
Block a user