From 5661931412a296e78c03000664ac4b4d64e3c849 Mon Sep 17 00:00:00 2001 From: David Paul Graham <43794491+dpgraham4401@users.noreply.github.com> Date: Mon, 13 Mar 2023 18:32:01 -0400 Subject: [PATCH] 372 manager class refactor (#400) * replace create_x Manager methods with 'save(**kwargs)' interface method add e_signature_factory fixture * move Serializer create method logic to ModelManagers * misc fixes, fixture datetime naive warnings, rename module for consistency --- .idea/scopes/server.xml | 4 +- server/apps/trak/models/__init__.py | 2 +- server/apps/trak/models/address_model.py | 146 +++++++++--------- server/apps/trak/models/base_model.py | 14 ++ server/apps/trak/models/contact_model.py | 12 +- server/apps/trak/models/handler_model.py | 36 ++--- server/apps/trak/models/manifest_model.py | 39 +++-- server/apps/trak/models/signature_model.py | 24 +-- server/apps/trak/models/transporter_model.py | 15 +- server/apps/trak/models/waste_model.py | 13 ++ server/apps/trak/serializers/address_ser.py | 9 +- .../serializers/{trak_ser.py => base_ser.py} | 0 server/apps/trak/serializers/contact_ser.py | 3 +- server/apps/trak/serializers/handler_ser.py | 21 +-- server/apps/trak/serializers/manifest_ser.py | 21 +-- .../apps/trak/serializers/rcra_profile_ser.py | 3 +- server/apps/trak/serializers/signature_ser.py | 19 +-- server/apps/trak/serializers/sites_ser.py | 3 +- .../apps/trak/serializers/transporter_ser.py | 3 +- .../apps/trak/serializers/waste_line_ser.py | 3 +- server/apps/trak/services/handler_service.py | 2 +- server/apps/trak/tests/conftest.py | 55 +++++-- server/apps/trak/tests/models/test_handler.py | 2 +- .../serializers/test_handler_serializer.py | 3 - 24 files changed, 249 insertions(+), 203 deletions(-) create mode 100644 server/apps/trak/models/base_model.py rename server/apps/trak/serializers/{trak_ser.py => base_ser.py} (100%) diff --git a/.idea/scopes/server.xml b/.idea/scopes/server.xml index e72ff9237..4d8f26535 100644 --- a/.idea/scopes/server.xml +++ b/.idea/scopes/server.xml @@ -1,3 +1,3 @@ - - + + \ No newline at end of file diff --git a/server/apps/trak/models/__init__.py b/server/apps/trak/models/__init__.py index d3cdb9833..014ec125b 100644 --- a/server/apps/trak/models/__init__.py +++ b/server/apps/trak/models/__init__.py @@ -1,7 +1,7 @@ """ Model definitions for the trak domain """ -from .address_model import Address, EpaCountries, EpaStates +from .address_model import Address from .contact_model import Contact, EpaPhone from .handler_model import Handler, ManifestHandler from .manifest_model import Manifest diff --git a/server/apps/trak/models/address_model.py b/server/apps/trak/models/address_model.py index 24e57eec4..da1f05cfa 100644 --- a/server/apps/trak/models/address_model.py +++ b/server/apps/trak/models/address_model.py @@ -2,85 +2,83 @@ from django.utils.translation import gettext_lazy as _ -class EpaCountries(models.TextChoices): - US = "US", _("United States") - MX = "MX", _("Mexico") - CA = "CA", _("Canada") - - -class EpaStates(models.TextChoices): - AK = "AK", _("Alaska") - AL = "AL", _("Alabama") - AP = "AP", _("Armed Forces Pacific") - AR = "AR", _("Arkansas") - AZ = "AZ", _("Arizona") - CA = "CA", _("California") - CO = "CO", _("Colorado") - CT = "CT", _("Connecticut") - DC = "DC", _("Washington DC") - DE = "DE", _("Delaware") - FL = "FL", _("Florida") - GA = "GA", _("Georgia") - GU = "GU", _("Guam") - HI = "HI", _("Hawaii") - IA = "IA", _("Iowa") - ID = "ID", _("Idaho") - IL = "IL", _("Illinois") - IN = "IN", _("Indiana") - KS = "KS", _("Kansas") - KY = "KY", _("Kentucky") - LA = "LA", _("Louisiana") - MA = "MA", _("Massachusetts") - MD = "MD", _("Maryland") - ME = "ME", _("Maine") - MI = "MI", _("Michigan") - MN = "MN", _("Minnesota") - MO = "MO", _("Missouri") - MS = "MS", _("Mississippi") - MT = "MT", _("Montana") - NC = "NC", _("North Carolina") - ND = "ND", _("North Dakota") - NE = "NE", _("Nebraska") - NH = "NH", _("New Hampshire") - NJ = "NJ", _("New Jersey") - NM = "NM", _("New Mexico") - NV = "NV", _("Nevada") - NY = "NY", _("New York") - OH = "OH", _("Ohio") - OK = "OK", _("Oklahoma") - OR = "OR", _("Oregon") - PA = "PA", _("Pennsylvania") - PR = "PR", _("Puerto Rico") - RI = "RI", _("Rhode Island") - SC = "SC", _("South Carolina") - SD = "SD", _("South Dakota") - TN = "TN", _("Tennessee") - TX = "TX", _("Texas") - UT = "UT", _("Utah") - VA = "VA", _("Virginia") - VI = "VI", _("Virgin Islands") - VT = "VT", _("Vermont") - WA = "WA", _("Washington") - WI = "WI", _("Wisconsin") - WV = "WV", _("West Virginia") - WY = "WY", _("Wyoming") - XA = "XA", _("REGION 01 PURVIEW") - XB = "XB", _("REGION 02 PURVIEW") - XC = "XC", _("REGION 03 PURVIEW") - XD = "XD", _("REGION 04 PURVIEW") - XE = "XE", _("REGION 05 PURVIEW") - XF = "XF", _("REGION 06 PURVIEW") - XG = "XG", _("REGION 07 PURVIEW") - XH = "XH", _("REGION 08 PURVIEW") - XI = "XI", _("REGION 09 PURVIEW") - XJ = "XJ", _("REGION 10 PURVIEW") - - class Address(models.Model): """ Used to capture RCRAInfo address instances (mail, site). """ + class EpaCountries(models.TextChoices): + US = "US", _("United States") + MX = "MX", _("Mexico") + CA = "CA", _("Canada") + + class EpaStates(models.TextChoices): + AK = "AK", _("Alaska") + AL = "AL", _("Alabama") + AP = "AP", _("Armed Forces Pacific") + AR = "AR", _("Arkansas") + AZ = "AZ", _("Arizona") + CA = "CA", _("California") + CO = "CO", _("Colorado") + CT = "CT", _("Connecticut") + DC = "DC", _("Washington DC") + DE = "DE", _("Delaware") + FL = "FL", _("Florida") + GA = "GA", _("Georgia") + GU = "GU", _("Guam") + HI = "HI", _("Hawaii") + IA = "IA", _("Iowa") + ID = "ID", _("Idaho") + IL = "IL", _("Illinois") + IN = "IN", _("Indiana") + KS = "KS", _("Kansas") + KY = "KY", _("Kentucky") + LA = "LA", _("Louisiana") + MA = "MA", _("Massachusetts") + MD = "MD", _("Maryland") + ME = "ME", _("Maine") + MI = "MI", _("Michigan") + MN = "MN", _("Minnesota") + MO = "MO", _("Missouri") + MS = "MS", _("Mississippi") + MT = "MT", _("Montana") + NC = "NC", _("North Carolina") + ND = "ND", _("North Dakota") + NE = "NE", _("Nebraska") + NH = "NH", _("New Hampshire") + NJ = "NJ", _("New Jersey") + NM = "NM", _("New Mexico") + NV = "NV", _("Nevada") + NY = "NY", _("New York") + OH = "OH", _("Ohio") + OK = "OK", _("Oklahoma") + OR = "OR", _("Oregon") + PA = "PA", _("Pennsylvania") + PR = "PR", _("Puerto Rico") + RI = "RI", _("Rhode Island") + SC = "SC", _("South Carolina") + SD = "SD", _("South Dakota") + TN = "TN", _("Tennessee") + TX = "TX", _("Texas") + UT = "UT", _("Utah") + VA = "VA", _("Virginia") + VI = "VI", _("Virgin Islands") + VT = "VT", _("Vermont") + WA = "WA", _("Washington") + WI = "WI", _("Wisconsin") + WV = "WV", _("West Virginia") + WY = "WY", _("Wyoming") + XA = "XA", _("REGION 01 PURVIEW") + XB = "XB", _("REGION 02 PURVIEW") + XC = "XC", _("REGION 03 PURVIEW") + XD = "XD", _("REGION 04 PURVIEW") + XE = "XE", _("REGION 05 PURVIEW") + XF = "XF", _("REGION 06 PURVIEW") + XG = "XG", _("REGION 07 PURVIEW") + XH = "XH", _("REGION 08 PURVIEW") + XI = "XI", _("REGION 09 PURVIEW") + XJ = "XJ", _("REGION 10 PURVIEW") + street_number = models.CharField( max_length=12, null=True, diff --git a/server/apps/trak/models/base_model.py b/server/apps/trak/models/base_model.py new file mode 100644 index 000000000..b63e126f5 --- /dev/null +++ b/server/apps/trak/models/base_model.py @@ -0,0 +1,14 @@ +from abc import ABCMeta, abstractmethod + +from django.db import models + + +class TrakManager(models.Manager, metaclass=ABCMeta): + """ + Abstract class that defines an interface for our model managers + """ + + @abstractmethod + def save(self, **kwargs) -> models.QuerySet: + """Save instance and its related models to the database""" + return self.create(**kwargs) diff --git a/server/apps/trak/models/contact_model.py b/server/apps/trak/models/contact_model.py index 617b8fe1b..9c80bc868 100644 --- a/server/apps/trak/models/contact_model.py +++ b/server/apps/trak/models/contact_model.py @@ -4,6 +4,8 @@ from django.db import models from django.utils.translation import gettext_lazy as _ +from apps.trak.models.base_model import TrakManager + class EpaPhoneNumber(models.CharField): """ @@ -39,26 +41,24 @@ def __str__(self): return f"{self.number}" -class ContactManager(models.Manager): +class ContactManager(TrakManager): """ Inter-model related functionality for Contact Model """ - def create(self, contact=None, **contact_data): + def save(self, **contact_data) -> models.QuerySet: """ Create Contact instance in database, create related phone instance if applicable, and return the new instance. """ - if isinstance(contact, Contact): - return contact if "phone" in contact_data: phone_data = contact_data.pop("phone") if isinstance(phone_data, EpaPhone): phone = phone_data else: phone = EpaPhone.objects.create(**phone_data) - return super().create(**contact_data, phone=phone) - return super().create(**contact_data) + return self.create(**contact_data, phone=phone) + return super().save(**contact_data) class Contact(models.Model): diff --git a/server/apps/trak/models/handler_model.py b/server/apps/trak/models/handler_model.py index 40cd48438..68b1824ac 100644 --- a/server/apps/trak/models/handler_model.py +++ b/server/apps/trak/models/handler_model.py @@ -5,13 +5,14 @@ from django.db import models from .address_model import Address +from .base_model import TrakManager from .contact_model import Contact, EpaPhone from .signature_model import ESignature, PaperSignature logger = logging.getLogger(__name__) -class HandlerManager(models.Manager): +class HandlerManager(TrakManager): """ Inter-model related functionality for Handler Model """ @@ -20,7 +21,7 @@ def __init__(self): self.handler_data = None super().__init__() - def create_handler(self, **handler_data): + def save(self, **handler_data): """ Create a handler and its related fields @@ -32,14 +33,14 @@ def create_handler(self, **handler_data): """ try: epa_id = handler_data.get("epa_id") - if Handler.objects.filter(epa_id=epa_id).exists(): + if self.model.objects.filter(epa_id=epa_id).exists(): return Handler.objects.get(epa_id=epa_id) self.handler_data = handler_data - new_contact = Contact.objects.create(self.handler_data.pop("contact")) + new_contact = Contact.objects.save(**self.handler_data.pop("contact")) emergency_phone = self.get_emergency_phone() site_address = self.get_address("site_address") mail_address = self.get_address("mail_address") - return super().create( + return super().save( site_address=site_address, mail_address=mail_address, emergency_phone=emergency_phone, @@ -166,23 +167,12 @@ def __repr__(self): return f"<{self.__class__.__name__}({field_values})>" -class ManifestHandlerManager(models.Manager): +class ManifestHandlerManager(TrakManager): """ Inter-model related functionality for ManifestHandler Model """ - def __init__(self): - self.manifest_handler_data = None - super().__init__() - - @staticmethod - def create_manifest_handler(**handler_data): - """ - Create a Manifest handler and its related fields - - Keyword Args: - handler (dict): handler data in (ordered)dict format - """ + def save(self, **handler_data) -> models.QuerySet: e_signatures = [] paper_signature = None if "e_signatures" in handler_data: @@ -195,14 +185,14 @@ def create_manifest_handler(**handler_data): handler = Handler.objects.get(epa_id=handler_data["handler"]["epa_id"]) logger.debug(f"using existing Handler {handler}") else: - handler = Handler.objects.create_handler(**handler_data["handler"]) + handler = Handler.objects.save(**handler_data["handler"]) logger.debug(f"Handler created {handler}") manifest_handler = ManifestHandler.objects.create( handler=handler, paper_signature=paper_signature ) logger.debug(f"ManifestHandler created {manifest_handler}") for e_signature_data in e_signatures: - e_sig = ESignature.objects.create_e_signature( + e_sig = ESignature.objects.save( manifest_handler=manifest_handler, **e_signature_data ) logger.debug(f"ESignature created {e_sig}") @@ -237,3 +227,9 @@ class ManifestHandler(models.Model): def __str__(self): return f"ManifestHandler: {self.handler.epa_id}" + + def __repr__(self): + field_values = ", ".join( + f"{field.name}={getattr(self, field.name)!r}" for field in self._meta.fields + ) + return f"<{self.__class__.__name__}({field_values})>" diff --git a/server/apps/trak/models/manifest_model.py b/server/apps/trak/models/manifest_model.py index 4864f6fe2..f378418ba 100644 --- a/server/apps/trak/models/manifest_model.py +++ b/server/apps/trak/models/manifest_model.py @@ -1,5 +1,6 @@ import logging import re +from typing import Dict from django.core.exceptions import ValidationError from django.db import models @@ -7,6 +8,10 @@ from django.utils.translation import gettext_lazy as _ from apps.trak.models import ManifestHandler +from apps.trak.models.base_model import TrakManager + +from .transporter_model import Transporter +from .waste_model import WasteLine logger = logging.getLogger(__name__) @@ -32,29 +37,43 @@ def validate_mtn(value): ) -class ManifestManager(models.Manager): +class ManifestManager(TrakManager): """ Inter-model related functionality for Manifest Model """ - @staticmethod - def create_manifest(manifest_data): + def save(self, **manifest_data: Dict): """Create a manifest with its related models instances""" + waste_data = [] + trans_data = [] additional_info = None + manifest_generator = None + manifest_tsd = None + if "wastes" in manifest_data: + waste_data = manifest_data.pop("wastes") + if "transporters" in manifest_data: + trans_data = manifest_data.pop("transporters") # Create manifest handlers (generator and TSD) and all related models - tsd_data = manifest_data.pop("tsd") - gen_data = manifest_data.pop("generator") - manifest_generator = ManifestHandler.objects.create_manifest_handler(**gen_data) - manifest_tsd = ManifestHandler.objects.create_manifest_handler(**tsd_data) + if "generator" in manifest_data: + manifest_generator = ManifestHandler.objects.save(**manifest_data.pop("generator")) + if "tsd" in manifest_data: + manifest_tsd = ManifestHandler.objects.save(**manifest_data.pop("tsd")) if "additional_info" in manifest_data: additional_info = AdditionalInfo.objects.create(**manifest_data.pop("additional_info")) # Create model instances - return Manifest.objects.create( + manifest = super().save( generator=manifest_generator, tsd=manifest_tsd, additional_info=additional_info, **manifest_data, ) + for waste_line in waste_data: + saved_waste_line = WasteLine.objects.save(manifest=manifest, **waste_line) + logger.debug(f"WasteLine saved {saved_waste_line.pk}") + for transporter in trans_data: + saved_transporter = Transporter.objects.save(manifest=manifest, **transporter) + logger.debug(f"WasteLine saved {saved_transporter.pk}") + return manifest class Manifest(models.Model): @@ -62,6 +81,8 @@ class Manifest(models.Model): Model definition the e-Manifest Uniform Hazardous Waste Manifest """ + objects = ManifestManager() + class LockReason(models.TextChoices): ASYNC_SIGN = "ACS", _("AsyncSign") CHANGE_BILLER = "ECB", _("EpaChangeBiller") @@ -89,8 +110,6 @@ class Status(models.TextChoices): UNDER_CORRECTION = "UnderCorrection", _("Under Correction") VALIDATION_FAILED = "MtnValidationFailed", _("MTN Validation Failed") - objects = ManifestManager() - created_date = models.DateTimeField( null=True, auto_now=True, diff --git a/server/apps/trak/models/signature_model.py b/server/apps/trak/models/signature_model.py index 64397bbe6..bba44585d 100644 --- a/server/apps/trak/models/signature_model.py +++ b/server/apps/trak/models/signature_model.py @@ -1,9 +1,10 @@ import logging -from django.core.exceptions import ValidationError from django.db import models from django.utils.translation import gettext_lazy as _ +from apps.trak.models.base_model import TrakManager + logger = logging.getLogger(__name__) @@ -76,24 +77,19 @@ def __str__(self): ) -class ESignatureManager(models.Manager): +class ESignatureManager(TrakManager): """ Inter-model related functionality for ESignature Model """ - def create_e_signature(self, **e_signature_data): + def save(self, **e_signature_data): """ Create Contact instance in database, create related phone instance if applicable, and return the new instance. """ - try: - if "signer" in e_signature_data: - signer_data = e_signature_data.pop("signer") - e_signature_data["signer"] = Signer.objects.create(**signer_data) - return super().create(**e_signature_data) - except ValidationError as exc: - logger.error(exc) - raise exc + if "signer" in e_signature_data: + e_signature_data["signer"] = Signer.objects.create(**e_signature_data.pop("signer")) + return super().save(**e_signature_data) class ESignature(models.Model): @@ -142,6 +138,12 @@ def __str__(self): ) return f"e-signature on {self.sign_date}" + def __repr__(self): + field_values = ", ".join( + f"{field.name}={getattr(self, field.name)!r}" for field in self._meta.fields + ) + return f"<{self.__class__.__name__}({field_values})>" + class Meta: verbose_name = "e-Signature" diff --git a/server/apps/trak/models/transporter_model.py b/server/apps/trak/models/transporter_model.py index 3009308ab..3af746bc8 100644 --- a/server/apps/trak/models/transporter_model.py +++ b/server/apps/trak/models/transporter_model.py @@ -3,7 +3,6 @@ from django.db import models from .handler_model import Handler, ManifestHandler, ManifestHandlerManager -from .manifest_model import Manifest class TransporterManager(ManifestHandlerManager): @@ -11,18 +10,14 @@ class TransporterManager(ManifestHandlerManager): Inter-model related functionality for Transporter Model """ - @staticmethod - def create_transporter(manifest: Manifest, **data: Dict): + def save(self, **transporter_data: Dict): """ Create a Transporter from a manifest instance and handler dict - - ToDo: See ManifestHandlerManager method, there's overlap that can be refactored - as a bigger item, look at our custom model managers, see where we can apply a better - design to take advantage of polymorphism and inheritance + ToDo: fix this implementation """ - handler_data = data.pop("handler") - new_handler = Handler.objects.create_handler(**handler_data) - return Transporter.objects.create(handler=new_handler, manifest=manifest, **data) + handler_data = transporter_data.pop("handler") + handler = Handler.objects.save(**handler_data) + return self.create(handler=handler, **transporter_data) class Transporter(ManifestHandler): diff --git a/server/apps/trak/models/waste_model.py b/server/apps/trak/models/waste_model.py index 2422f45a9..d63fb98ba 100644 --- a/server/apps/trak/models/waste_model.py +++ b/server/apps/trak/models/waste_model.py @@ -1,5 +1,16 @@ from django.db import models +from apps.trak.models.base_model import TrakManager + + +class WasteLineManager(TrakManager): + """ + Inter-model related functionality for Contact Model + """ + + def save(self, **waste_data) -> models.QuerySet: + return super().save(**waste_data) + class WasteLine(models.Model): """ @@ -7,6 +18,8 @@ class WasteLine(models.Model): Model definition for hazardous waste listed on a uniform hazardous waste manifest. """ + objects = WasteLineManager() + manifest = models.ForeignKey( "Manifest", related_name="wastes", diff --git a/server/apps/trak/serializers/address_ser.py b/server/apps/trak/serializers/address_ser.py index 067a5ca1d..471e172ba 100644 --- a/server/apps/trak/serializers/address_ser.py +++ b/server/apps/trak/serializers/address_ser.py @@ -3,10 +3,9 @@ from rest_framework import serializers from rest_framework.exceptions import ValidationError -# ToDo (convert to enums and remove this import) -from apps.trak.models import Address, EpaCountries, EpaStates +from apps.trak.models import Address -from .trak_ser import TrakBaseSerializer +from .base_ser import TrakBaseSerializer @extend_schema_field(OpenApiTypes.OBJECT) @@ -39,11 +38,11 @@ class AddressSerializer(TrakBaseSerializer): required=False, ) state = LocalityField( - choices=EpaStates.choices, + choices=Address.EpaStates.choices, required=False, ) country = LocalityField( - choices=EpaCountries.choices, + choices=Address.EpaCountries.choices, required=False, ) diff --git a/server/apps/trak/serializers/trak_ser.py b/server/apps/trak/serializers/base_ser.py similarity index 100% rename from server/apps/trak/serializers/trak_ser.py rename to server/apps/trak/serializers/base_ser.py diff --git a/server/apps/trak/serializers/contact_ser.py b/server/apps/trak/serializers/contact_ser.py index 49280e964..6e7382b7f 100644 --- a/server/apps/trak/serializers/contact_ser.py +++ b/server/apps/trak/serializers/contact_ser.py @@ -1,7 +1,8 @@ from rest_framework import serializers from apps.trak.models import Contact -from apps.trak.serializers.trak_ser import TrakBaseSerializer + +from .base_ser import TrakBaseSerializer class EpaPhoneSerializer(TrakBaseSerializer): diff --git a/server/apps/trak/serializers/handler_ser.py b/server/apps/trak/serializers/handler_ser.py index 9447483ea..63dd339cc 100644 --- a/server/apps/trak/serializers/handler_ser.py +++ b/server/apps/trak/serializers/handler_ser.py @@ -1,13 +1,13 @@ -from typing import Dict, List +from typing import Dict from rest_framework import serializers -from apps.trak.models import ESignature, Handler, ManifestHandler +from apps.trak.models import Handler, ManifestHandler from apps.trak.serializers import AddressSerializer +from .base_ser import TrakBaseSerializer from .contact_ser import ContactSerializer, EpaPhoneSerializer from .signature_ser import ESignatureSerializer, PaperSignatureSerializer -from .trak_ser import TrakBaseSerializer class HandlerSerializer(TrakBaseSerializer): @@ -67,7 +67,7 @@ class HandlerSerializer(TrakBaseSerializer): ) def create(self, validated_data): - return Handler.objects.create_handler(**validated_data) + return self.Meta.model.objects.save(**validated_data) class Meta: model = Handler @@ -102,16 +102,11 @@ class ManifestHandlerSerializer(HandlerSerializer): required=False, ) + def update(self, instance, validated_data: Dict): + return self.Meta.model.objects.update(instance, **validated_data) + def create(self, validated_data: Dict): - e_signatures_data = [] - if "e_signatures" in validated_data: - e_signatures_data: List = validated_data.pop("e_signatures") - manifest_handler = ManifestHandler.objects.create_manifest_handler(**validated_data) - for e_signature_data in e_signatures_data: - ESignature.objects.create_e_signature( - manifest_handler=manifest_handler, **e_signature_data - ) - return manifest_handler + return self.Meta.model.objects.save(**validated_data) def to_representation(self, instance): representation = super().to_representation(instance) diff --git a/server/apps/trak/serializers/manifest_ser.py b/server/apps/trak/serializers/manifest_ser.py index bfa70b1ba..b2167d848 100644 --- a/server/apps/trak/serializers/manifest_ser.py +++ b/server/apps/trak/serializers/manifest_ser.py @@ -1,12 +1,13 @@ import logging +from typing import Dict from rest_framework import serializers -from apps.trak.models import Manifest, Transporter, WasteLine +from apps.trak.models import Manifest from apps.trak.serializers.handler_ser import ManifestHandlerSerializer -from apps.trak.serializers.trak_ser import TrakBaseSerializer from ..models.manifest_model import AdditionalInfo +from .base_ser import TrakBaseSerializer from .transporter_ser import TransporterSerializer from .waste_line_ser import WasteLineSerializer @@ -204,17 +205,11 @@ class ManifestSerializer(TrakBaseSerializer): allow_null=True, ) - def create(self, validated_data) -> Manifest: - waste_data = validated_data.pop("wastes") - trans_data = validated_data.pop("transporters") - manifest = Manifest.objects.create_manifest(validated_data) - logger.debug(f"ManifestSerializer created manifest {manifest}") - for waste_line in waste_data: - WasteLine.objects.create(manifest=manifest, **waste_line) - for transporter in trans_data: - transporter["manifest"] = manifest - Transporter.objects.create_transporter(**transporter) - return manifest + def update(self, instance, validated_data: Dict) -> Manifest: + return self.Meta.model.objects.save(**validated_data) + + def create(self, validated_data: Dict) -> Manifest: + return self.Meta.model.objects.save(**validated_data) # https://www.django-rest-framework.org/api-guide/serializers/#overriding-serialization-and-deserialization-behavior def to_representation(self, instance) -> str: diff --git a/server/apps/trak/serializers/rcra_profile_ser.py b/server/apps/trak/serializers/rcra_profile_ser.py index 4012d4a64..a77ac84b0 100644 --- a/server/apps/trak/serializers/rcra_profile_ser.py +++ b/server/apps/trak/serializers/rcra_profile_ser.py @@ -3,7 +3,8 @@ from rest_framework.serializers import ModelSerializer from apps.trak.models import RcraProfile, SitePermission -from apps.trak.serializers.trak_ser import TrakBaseSerializer + +from .base_ser import TrakBaseSerializer class SitePermissionSerializer(TrakBaseSerializer): diff --git a/server/apps/trak/serializers/signature_ser.py b/server/apps/trak/serializers/signature_ser.py index eb987d2d6..d27687c41 100644 --- a/server/apps/trak/serializers/signature_ser.py +++ b/server/apps/trak/serializers/signature_ser.py @@ -4,7 +4,8 @@ from apps.trak.models import ESignature, PaperSignature, Signer from apps.trak.serializers.contact_ser import EpaPhoneSerializer -from apps.trak.serializers.trak_ser import TrakBaseSerializer + +from .base_ser import TrakBaseSerializer class SignerSerializer(TrakBaseSerializer): @@ -88,16 +89,10 @@ class ESignatureSerializer(TrakBaseSerializer): ) def update(self, instance, validated_data): - super().update(instance, validated_data) + return super().update(instance, validated_data) def create(self, validated_data: Dict): - signer = None - try: - signer_data = validated_data.pop("signer") - signer = Signer.objects.create(**signer_data) - except KeyError: - pass - return ESignature.objects.create(**validated_data, signer=signer) + return self.Meta.model.objects.save(**validated_data) class Meta: model = ESignature @@ -126,11 +121,11 @@ class PaperSignatureSerializer(TrakBaseSerializer): required=False, ) - def update(self, instance, validated_data): - return super().update(instance, validated_data) + def update(self, instance, validated_data: Dict): + return super().update(instance, **validated_data) def create(self, validated_data: Dict): - return super().create(validated_data) + return super().create(**validated_data) class Meta: model = PaperSignature diff --git a/server/apps/trak/serializers/sites_ser.py b/server/apps/trak/serializers/sites_ser.py index 3bfca8faf..78e48aff4 100644 --- a/server/apps/trak/serializers/sites_ser.py +++ b/server/apps/trak/serializers/sites_ser.py @@ -2,7 +2,8 @@ from apps.trak.models import Site from apps.trak.serializers import HandlerSerializer -from apps.trak.serializers.trak_ser import TrakBaseSerializer + +from .base_ser import TrakBaseSerializer class SiteSerializer(TrakBaseSerializer): diff --git a/server/apps/trak/serializers/transporter_ser.py b/server/apps/trak/serializers/transporter_ser.py index d0361f4ad..7a6ef9ea6 100644 --- a/server/apps/trak/serializers/transporter_ser.py +++ b/server/apps/trak/serializers/transporter_ser.py @@ -1,6 +1,7 @@ from apps.trak.models import Transporter from apps.trak.serializers.handler_ser import HandlerSerializer -from apps.trak.serializers.trak_ser import TrakBaseSerializer + +from .base_ser import TrakBaseSerializer class TransporterSerializer(TrakBaseSerializer): diff --git a/server/apps/trak/serializers/waste_line_ser.py b/server/apps/trak/serializers/waste_line_ser.py index b5b914b0b..87201c397 100644 --- a/server/apps/trak/serializers/waste_line_ser.py +++ b/server/apps/trak/serializers/waste_line_ser.py @@ -1,7 +1,8 @@ from rest_framework import serializers from apps.trak.models import WasteLine -from apps.trak.serializers.trak_ser import TrakBaseSerializer + +from .base_ser import TrakBaseSerializer class WasteLineSerializer(TrakBaseSerializer): diff --git a/server/apps/trak/services/handler_service.py b/server/apps/trak/services/handler_service.py index e0fdfd1d1..e84eaf831 100644 --- a/server/apps/trak/services/handler_service.py +++ b/server/apps/trak/services/handler_service.py @@ -74,5 +74,5 @@ def _create_or_update_handler(self, *, handler_data: dict) -> Handler: if Handler.objects.filter(epa_id=epa_id).exists(): handler = Handler.objects.get(epa_id=epa_id) return handler - handler = Handler.objects.create_handler(**handler_data) + handler = Handler.objects.save(**handler_data) return handler diff --git a/server/apps/trak/tests/conftest.py b/server/apps/trak/tests/conftest.py index 070906782..54c3b2c20 100644 --- a/server/apps/trak/tests/conftest.py +++ b/server/apps/trak/tests/conftest.py @@ -1,6 +1,8 @@ import json import os -from datetime import date, datetime +import random +import string +from datetime import date, datetime, timezone from enum import Enum from http import HTTPStatus from typing import Dict, Optional @@ -14,6 +16,7 @@ Address, Contact, EpaPhone, + ESignature, Handler, Manifest, ManifestHandler, @@ -148,7 +151,7 @@ def create_signature( ) -> PaperSignature: return PaperSignature.objects.create( printed_name=printed_name, - sign_date=sign_date or datetime.utcnow(), + sign_date=sign_date or datetime.utcnow().replace(tzinfo=timezone.utc), ) return create_signature @@ -200,6 +203,38 @@ def create_handler( return create_handler +@pytest.fixture +def e_signature_factory(db, signer_factory, manifest_handler_factory): + """Abstract factory for Haztrak ManifestHandler model""" + + def create_e_signature( + signer: Optional[Signer] = None, + manifest_handler: Optional[ManifestHandler] = None, + ) -> ESignature: + return ESignature.objects.create( + signer=signer or signer_factory(), + manifest_handler=manifest_handler or manifest_handler_factory(), + sign_date=datetime.utcnow().replace(tzinfo=timezone.utc), + cromerr_activity_id="".join(random.choices(string.ascii_letters, k=10)), + cromerr_document_id="".join(random.choices(string.ascii_letters, k=10)), + on_behalf=False, + ) + + return create_e_signature + + +@pytest.fixture +def manifest_handler_factory(db, handler_factory): + """Abstract factory for Haztrak ManifestHandler model""" + + def create_manifest_handler(handler: Optional[Handler] = None) -> ManifestHandler: + return ManifestHandler.objects.create( + handler=handler or handler_factory(), + ) + + return create_manifest_handler + + @pytest.fixture def site_factory(db, handler_factory): """Abstract factory for Haztrak Site model""" @@ -269,18 +304,6 @@ def create_permission( return create_permission -@pytest.fixture -def manifest_handler_factory(db, handler_factory): - """Abstract factory for Haztrak ManifestHandler model""" - - def create_manifest_handler(handler: Optional[Handler] = None) -> ManifestHandler: - return ManifestHandler.objects.create( - handler=handler or handler_factory(), - ) - - return create_manifest_handler - - @pytest.fixture def manifest_factory(db, manifest_handler_factory, handler_factory): """Abstract factory for Haztrak Manifest model""" @@ -296,8 +319,8 @@ def create_manifest( tsd = manifest_handler_factory(handler=handler) return Manifest.objects.create( mtn=mtn, - created_date=datetime.now(), - potential_ship_date=date.today(), + created_date=datetime.now().replace(tzinfo=timezone.utc), + potential_ship_date=datetime.now().replace(tzinfo=timezone.utc), generator=generator or manifest_handler_factory(), tsd=tsd or manifest_handler_factory(handler=handler_factory(epa_id="tsd001")), ) diff --git a/server/apps/trak/tests/models/test_handler.py b/server/apps/trak/tests/models/test_handler.py index 0d521d7e6..1dd624496 100644 --- a/server/apps/trak/tests/models/test_handler.py +++ b/server/apps/trak/tests/models/test_handler.py @@ -9,6 +9,6 @@ def test_handler_created(self, db, manifest_handler_factory) -> None: def test_manager_creates_new_handler(self, handler_serializer) -> None: handler_serializer.is_valid() - ManifestHandler.objects.create_manifest_handler(handler=handler_serializer.validated_data) + ManifestHandler.objects.save(handler=handler_serializer.validated_data) new_handler = Handler.objects.get(epa_id=handler_serializer.validated_data["epa_id"]) assert isinstance(new_handler, Handler) diff --git a/server/apps/trak/tests/serializers/test_handler_serializer.py b/server/apps/trak/tests/serializers/test_handler_serializer.py index e70dbaab2..2b4343178 100644 --- a/server/apps/trak/tests/serializers/test_handler_serializer.py +++ b/server/apps/trak/tests/serializers/test_handler_serializer.py @@ -3,9 +3,6 @@ class TestManifestHandlerSerializer: - def test_new_fixture(self, haztrak_json): - print(haztrak_json.MANIFEST.value) - def test_m_handler_serializes(self, haztrak_json) -> None: manifest_handler_serializer = ManifestHandlerSerializer(data=haztrak_json.HANDLER.value) assert manifest_handler_serializer.is_valid()