@@ -39,7 +41,13 @@ function TransporterTable({ transporters, arrayFieldMethods, readOnly }: Transpo
{transporter.order} |
{transporter.epaSiteId} |
{transporter.name} |
- {transporter.canEsign ? 'yes' : 'no'} |
+
+ {transporter.signed ? (
+
+ ) : (
+
+ )}
+ |
{readOnly ? (
<>>
diff --git a/client/src/features/manifest/ManifestDetails.tsx b/client/src/features/manifest/ManifestDetails.tsx
index b6257c401..6e8f24ce0 100644
--- a/client/src/features/manifest/ManifestDetails.tsx
+++ b/client/src/features/manifest/ManifestDetails.tsx
@@ -7,7 +7,7 @@ import { useParams } from 'react-router-dom';
import { Manifest } from 'types/Manifest';
function ManifestDetails() {
- const { mtn, action } = useParams();
+ const { mtn, action, siteId } = useParams();
useTitle(`${mtn}`);
const [manifestData, loading, error] = useHtAPI(`trak/manifest/${mtn}`);
@@ -21,7 +21,7 @@ function ManifestDetails() {
return loading ? (
) : manifestData ? (
-
+
) : (
<>>
);
diff --git a/client/src/types/Handler/handler.ts b/client/src/types/Handler/handler.ts
index d57d52cda..27b9cabbc 100644
--- a/client/src/types/Handler/handler.ts
+++ b/client/src/types/Handler/handler.ts
@@ -50,13 +50,25 @@ export interface Handler {
gisPrimary?: boolean;
}
+/**
+ * The Signature that appears on paper versions of the manifest
+ */
+export interface PaperSignature {
+ printedName: string;
+ signatureDate: string;
+}
+
/**
* The ManifestHandler extends to Handler schema and adds manifest specific data
*/
export interface ManifestHandler extends Handler {
- // paperSignatureInfo: PaperSignature
+ paperSignatureInfo?: PaperSignature;
electronicSignaturesInfo?: Array;
siteType?: 'Generator' | 'Broken' | 'Transporter' | 'Tsdf';
+ /**
+ * Property on by back end to signify whether the handler has signed
+ */
+ signed?: boolean;
}
/**
diff --git a/server/apps/trak/models/address_model.py b/server/apps/trak/models/address_model.py
index da1f05cfa..029025545 100644
--- a/server/apps/trak/models/address_model.py
+++ b/server/apps/trak/models/address_model.py
@@ -1,8 +1,10 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
+from apps.trak.models.base_model import TrakBaseModel
-class Address(models.Model):
+
+class Address(TrakBaseModel):
"""
Used to capture RCRAInfo address instances (mail, site).
"""
@@ -122,9 +124,3 @@ def __str__(self):
if self.street_number:
return f"{self.street_number} {self.address1}"
return f" {self.address1}"
-
- 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/base_model.py b/server/apps/trak/models/base_model.py
index b63e126f5..e753ae3ce 100644
--- a/server/apps/trak/models/base_model.py
+++ b/server/apps/trak/models/base_model.py
@@ -3,12 +3,34 @@
from django.db import models
-class TrakManager(models.Manager, metaclass=ABCMeta):
+class TrakBaseManager(models.Manager, metaclass=ABCMeta):
"""
Abstract class that defines an interface for our model managers
"""
+ 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})>"
+
@abstractmethod
def save(self, **kwargs) -> models.QuerySet:
"""Save instance and its related models to the database"""
return self.create(**kwargs)
+
+
+class TrakBaseModel(models.Model):
+ """Base class for all apps.trak models"""
+
+ def __str__(self):
+ return f"{self.__class__.__name__}"
+
+ 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:
+ abstract = True
diff --git a/server/apps/trak/models/contact_model.py b/server/apps/trak/models/contact_model.py
index 9c80bc868..f6a7dbc63 100644
--- a/server/apps/trak/models/contact_model.py
+++ b/server/apps/trak/models/contact_model.py
@@ -4,7 +4,7 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
-from apps.trak.models.base_model import TrakManager
+from apps.trak.models.base_model import TrakBaseManager, TrakBaseModel
class EpaPhoneNumber(models.CharField):
@@ -41,7 +41,7 @@ def __str__(self):
return f"{self.number}"
-class ContactManager(TrakManager):
+class ContactManager(TrakBaseManager):
"""
Inter-model related functionality for Contact Model
"""
@@ -61,7 +61,7 @@ def save(self, **contact_data) -> models.QuerySet:
return super().save(**contact_data)
-class Contact(models.Model):
+class Contact(TrakBaseModel):
"""
RCRAInfo contact including personnel information such as name, email, company,
includes a phone related field.
@@ -108,9 +108,3 @@ def __str__(self):
return f"{first.capitalize()} {middle.capitalize()} {last.capitalize()}"
except AttributeError:
return f"contact {self.pk}: {self.first_name} {self.middle_initial} {self.last_name}"
-
- 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/handler_model.py b/server/apps/trak/models/handler_model.py
index 68b1824ac..a9d2ae474 100644
--- a/server/apps/trak/models/handler_model.py
+++ b/server/apps/trak/models/handler_model.py
@@ -5,14 +5,14 @@
from django.db import models
from .address_model import Address
-from .base_model import TrakManager
+from .base_model import TrakBaseManager, TrakBaseModel
from .contact_model import Contact, EpaPhone
from .signature_model import ESignature, PaperSignature
logger = logging.getLogger(__name__)
-class HandlerManager(TrakManager):
+class HandlerManager(TrakBaseManager):
"""
Inter-model related functionality for Handler Model
"""
@@ -50,12 +50,6 @@ def save(self, **handler_data):
except KeyError as exc:
logger.warning(f"error while creating handler {exc}")
- 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})>"
-
def get_emergency_phone(self) -> Union[EpaPhone, None]:
"""Check if emergency phone is present and create an EpaPhone row"""
try:
@@ -78,7 +72,7 @@ def get_address(self, key) -> Address:
raise ValidationError(exc)
-class Handler(models.Model):
+class Handler(TrakBaseModel):
"""
RCRAInfo Handler model definition for entities on the uniform hazardous waste manifests
"""
@@ -105,12 +99,12 @@ class Handler(models.Model):
max_length=200,
)
site_address = models.ForeignKey(
- Address,
+ "Address",
on_delete=models.CASCADE,
related_name="site_address",
)
mail_address = models.ForeignKey(
- Address,
+ "Address",
on_delete=models.CASCADE,
related_name="mail_address",
)
@@ -123,12 +117,12 @@ class Handler(models.Model):
blank=True,
)
contact = models.ForeignKey(
- Contact,
+ "Contact",
on_delete=models.CASCADE,
verbose_name="Contact Information",
)
emergency_phone = models.ForeignKey(
- EpaPhone,
+ "EpaPhone",
on_delete=models.CASCADE,
null=True,
blank=True,
@@ -160,14 +154,8 @@ class Handler(models.Model):
def __str__(self):
return f"{self.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})>"
-
-class ManifestHandlerManager(TrakManager):
+class ManifestHandlerManager(TrakBaseManager):
"""
Inter-model related functionality for ManifestHandler Model
"""
@@ -183,12 +171,15 @@ def save(self, **handler_data) -> models.QuerySet:
try:
if Handler.objects.filter(epa_id=handler_data["handler"]["epa_id"]).exists():
handler = Handler.objects.get(epa_id=handler_data["handler"]["epa_id"])
+ handler_data.pop("handler")
logger.debug(f"using existing Handler {handler}")
else:
- handler = Handler.objects.save(**handler_data["handler"])
+ handler = Handler.objects.save(**handler_data.pop("handler"))
logger.debug(f"Handler created {handler}")
- manifest_handler = ManifestHandler.objects.create(
- handler=handler, paper_signature=paper_signature
+ manifest_handler = self.model.objects.create(
+ handler=handler,
+ paper_signature=paper_signature,
+ **handler_data,
)
logger.debug(f"ManifestHandler created {manifest_handler}")
for e_signature_data in e_signatures:
@@ -204,7 +195,7 @@ def save(self, **handler_data) -> models.QuerySet:
raise exc
-class ManifestHandler(models.Model):
+class ManifestHandler(TrakBaseModel):
"""
ManifestHandler which contains a reference to hazardous waste
handler and data specific to that handler on the given manifest.
@@ -225,11 +216,12 @@ class ManifestHandler(models.Model):
help_text="The signature associated with hazardous waste custody exchange",
)
+ @property
+ def signed(self) -> bool:
+ """Returns True if one of the signature types is present"""
+ e_signature_exists = ESignature.objects.filter(manifest_handler=self).exists()
+ paper_signature_exists = self.paper_signature is not None
+ return paper_signature_exists or e_signature_exists
+
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 f378418ba..326405ebc 100644
--- a/server/apps/trak/models/manifest_model.py
+++ b/server/apps/trak/models/manifest_model.py
@@ -8,7 +8,7 @@
from django.utils.translation import gettext_lazy as _
from apps.trak.models import ManifestHandler
-from apps.trak.models.base_model import TrakManager
+from apps.trak.models.base_model import TrakBaseManager, TrakBaseModel
from .transporter_model import Transporter
from .waste_model import WasteLine
@@ -37,7 +37,7 @@ def validate_mtn(value):
)
-class ManifestManager(TrakManager):
+class ManifestManager(TrakBaseManager):
"""
Inter-model related functionality for Manifest Model
"""
@@ -76,7 +76,7 @@ def save(self, **manifest_data: Dict):
return manifest
-class Manifest(models.Model):
+class Manifest(TrakBaseModel):
"""
Model definition the e-Manifest Uniform Hazardous Waste Manifest
"""
@@ -278,7 +278,7 @@ def __str__(self):
return f"{self.mtn}"
-class AdditionalInfo(models.Model):
+class AdditionalInfo(TrakBaseModel):
"""
Entity containing Additional Information. Relevant to Both Manifest and individual WastesLines.
Shipment rejection related info is stored in this object.
@@ -327,9 +327,3 @@ class Meta:
def __str__(self):
return f"{self.original_mtn or 'Unknown'}"
-
- 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/rcra_profile_model.py b/server/apps/trak/models/rcra_profile_model.py
index 2b52476aa..130167655 100644
--- a/server/apps/trak/models/rcra_profile_model.py
+++ b/server/apps/trak/models/rcra_profile_model.py
@@ -1,8 +1,10 @@
from django.contrib.auth.models import User
from django.db import models
+from apps.trak.models.base_model import TrakBaseModel
-class RcraProfile(models.Model):
+
+class RcraProfile(TrakBaseModel):
"""
Provides the user's RcraProfile information, excluding their RCRAInfo
API key (see ProfileUpdateSerializer). Has a one-to-one relationship with
@@ -38,12 +40,6 @@ class RcraProfile(models.Model):
def __str__(self):
return f"{self.user.username}"
- 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})>"
-
def sync(self):
"""Launch task to sync use profile. ToDo: remove this method"""
from ..tasks import sync_user_sites
diff --git a/server/apps/trak/models/signature_model.py b/server/apps/trak/models/signature_model.py
index bba44585d..f07cd0caf 100644
--- a/server/apps/trak/models/signature_model.py
+++ b/server/apps/trak/models/signature_model.py
@@ -3,12 +3,12 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
-from apps.trak.models.base_model import TrakManager
+from apps.trak.models.base_model import TrakBaseManager, TrakBaseModel
logger = logging.getLogger(__name__)
-class Signer(models.Model):
+class Signer(TrakBaseModel):
"""EPA manifest signer definition"""
class Role(models.TextChoices):
@@ -77,7 +77,7 @@ def __str__(self):
)
-class ESignatureManager(TrakManager):
+class ESignatureManager(TrakBaseManager):
"""
Inter-model related functionality for ESignature Model
"""
@@ -92,7 +92,7 @@ def save(self, **e_signature_data):
return super().save(**e_signature_data)
-class ESignature(models.Model):
+class ESignature(TrakBaseModel):
"""EPA electronic signature"""
objects = ESignatureManager()
@@ -138,17 +138,11 @@ 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"
-class PaperSignature(models.Model):
+class PaperSignature(TrakBaseModel):
"""
Contains printed name of the handler Signee and
Date of Signature for paper manifests.
@@ -162,11 +156,5 @@ class PaperSignature(models.Model):
def __str__(self):
return f"{self.printed_name} ({self.sign_date.strftime('%Y-%m-%d %H:%M:%S')})"
- 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})>"
-
def __hash__(self):
return hash((self.printed_name, self.sign_date))
diff --git a/server/apps/trak/models/site_model.py b/server/apps/trak/models/site_model.py
index 0877752c4..0495228d4 100644
--- a/server/apps/trak/models/site_model.py
+++ b/server/apps/trak/models/site_model.py
@@ -1,10 +1,11 @@
from django.core.validators import MinValueValidator
from django.db import models
+from .base_model import TrakBaseModel
from .handler_model import Handler
-class Site(models.Model):
+class Site(TrakBaseModel):
"""
Haztrak Site model used to control access to Handler object.
@@ -30,9 +31,3 @@ class Site(models.Model):
def __str__(self):
return f"{self.epa_site.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/site_permission_model.py b/server/apps/trak/models/site_permission_model.py
index 88d014f8b..5ad04f24d 100644
--- a/server/apps/trak/models/site_permission_model.py
+++ b/server/apps/trak/models/site_permission_model.py
@@ -1,6 +1,7 @@
from django.core.exceptions import ValidationError
from django.db import models
+from .base_model import TrakBaseModel
from .rcra_profile_model import RcraProfile
from .site_model import Site
@@ -11,7 +12,7 @@
]
-class SitePermission(models.Model):
+class SitePermission(TrakBaseModel):
"""
RCRAInfo Site Permissions per module connected to a user's RcraProfile
and the corresponding Site
@@ -50,13 +51,6 @@ class SitePermission(models.Model):
def __str__(self):
return f"{self.profile.user}: {self.site}"
- 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})>"
-
def clean(self):
if self.site_manager:
fields = ["annual_report", "biennial_report", "e_manifest", "my_rcra_id", "wiets"]
diff --git a/server/apps/trak/models/transporter_model.py b/server/apps/trak/models/transporter_model.py
index 3af746bc8..4c49c18b0 100644
--- a/server/apps/trak/models/transporter_model.py
+++ b/server/apps/trak/models/transporter_model.py
@@ -2,7 +2,7 @@
from django.db import models
-from .handler_model import Handler, ManifestHandler, ManifestHandlerManager
+from .handler_model import ManifestHandler, ManifestHandlerManager
class TransporterManager(ManifestHandlerManager):
@@ -15,9 +15,7 @@ def save(self, **transporter_data: Dict):
Create a Transporter from a manifest instance and handler dict
ToDo: fix this implementation
"""
- handler_data = transporter_data.pop("handler")
- handler = Handler.objects.save(**handler_data)
- return self.create(handler=handler, **transporter_data)
+ return super().save(**transporter_data)
class Transporter(ManifestHandler):
@@ -36,9 +34,3 @@ class Transporter(ManifestHandler):
def __str__(self):
return f"{self.handler.epa_id}: transporter {self.order} on {self.manifest.mtn}"
-
- 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/waste_model.py b/server/apps/trak/models/waste_model.py
index d63fb98ba..dead2f33a 100644
--- a/server/apps/trak/models/waste_model.py
+++ b/server/apps/trak/models/waste_model.py
@@ -1,9 +1,9 @@
from django.db import models
-from apps.trak.models.base_model import TrakManager
+from apps.trak.models.base_model import TrakBaseManager, TrakBaseModel
-class WasteLineManager(TrakManager):
+class WasteLineManager(TrakBaseManager):
"""
Inter-model related functionality for Contact Model
"""
@@ -12,7 +12,7 @@ def save(self, **waste_data) -> models.QuerySet:
return super().save(**waste_data)
-class WasteLine(models.Model):
+class WasteLine(TrakBaseModel):
"""
ToDo: Every place we have as a JSON field likely should be stored in separate table
Model definition for hazardous waste listed on a uniform hazardous waste manifest.
@@ -80,9 +80,3 @@ class WasteLine(models.Model):
def __str__(self):
return f"{self.manifest} line {self.line_number}"
-
- def __repr__(self):
- field_values = ", ".join(
- f"{field.name}={getattr(self, field.name)!r}" for field in self._meta.fields
- )
- return f""
diff --git a/server/apps/trak/serializers/address_ser.py b/server/apps/trak/serializers/address_ser.py
index 471e172ba..33fedd0af 100644
--- a/server/apps/trak/serializers/address_ser.py
+++ b/server/apps/trak/serializers/address_ser.py
@@ -36,6 +36,7 @@ class AddressSerializer(TrakBaseSerializer):
streetNumber = serializers.CharField(
source="street_number",
required=False,
+ allow_blank=True,
)
state = LocalityField(
choices=Address.EpaStates.choices,
diff --git a/server/apps/trak/serializers/handler_ser.py b/server/apps/trak/serializers/handler_ser.py
index 63dd339cc..1bfb710b5 100644
--- a/server/apps/trak/serializers/handler_ser.py
+++ b/server/apps/trak/serializers/handler_ser.py
@@ -66,6 +66,9 @@ class HandlerSerializer(TrakBaseSerializer):
default=False,
)
+ def update(self, instance, validated_data):
+ return self.Meta.model.objects.save(**validated_data)
+
def create(self, validated_data):
return self.Meta.model.objects.save(**validated_data)
@@ -101,6 +104,7 @@ class ManifestHandlerSerializer(HandlerSerializer):
source="paper_signature",
required=False,
)
+ signed = serializers.ReadOnlyField()
def update(self, instance, validated_data: Dict):
return self.Meta.model.objects.update(instance, **validated_data)
@@ -122,6 +126,8 @@ def to_internal_value(self, data: Dict):
if "paperSignatureInfo" in data:
instance["paperSignatureInfo"] = data.pop("paperSignatureInfo")
instance["handler"] = data
+ if "order" in instance["handler"]:
+ instance["order"] = instance["handler"]["order"]
return super().to_internal_value(instance)
class Meta:
@@ -130,4 +136,5 @@ class Meta:
"handler",
"electronicSignaturesInfo",
"paperSignatureInfo",
+ "signed",
]
diff --git a/server/apps/trak/serializers/manifest_ser.py b/server/apps/trak/serializers/manifest_ser.py
index b2167d848..64cd61627 100644
--- a/server/apps/trak/serializers/manifest_ser.py
+++ b/server/apps/trak/serializers/manifest_ser.py
@@ -36,6 +36,7 @@ class AdditionalInfoSerializer(serializers.ModelSerializer):
)
handlingInstructions = serializers.CharField(
allow_null=True,
+ allow_blank=True,
required=False,
source="handling_instructions",
)
diff --git a/server/apps/trak/serializers/transporter_ser.py b/server/apps/trak/serializers/transporter_ser.py
index 7a6ef9ea6..c1c5bee78 100644
--- a/server/apps/trak/serializers/transporter_ser.py
+++ b/server/apps/trak/serializers/transporter_ser.py
@@ -1,37 +1,28 @@
-from apps.trak.models import Transporter
-from apps.trak.serializers.handler_ser import HandlerSerializer
+from rest_framework.exceptions import ValidationError
-from .base_ser import TrakBaseSerializer
+from apps.trak.models import Transporter
+from apps.trak.serializers.handler_ser import ManifestHandlerSerializer
-class TransporterSerializer(TrakBaseSerializer):
+class TransporterSerializer(ManifestHandlerSerializer):
"""
Transporter model serializer for JSON marshalling/unmarshalling
"""
- handler = HandlerSerializer()
-
class Meta:
model = Transporter
fields = [
"handler",
"order",
+ "paperSignatureInfo",
+ "electronicSignaturesInfo",
+ "signed",
]
- def to_representation(self, obj):
- """flatten handler foreign key to transporter representation."""
- representation = super().to_representation(obj)
- profile_representation = representation.pop("handler")
- for key in profile_representation:
- representation[key] = profile_representation[key]
- return representation
-
def to_internal_value(self, data):
"""Move fields related to handler to an internal handler dictionary."""
- handler_internal = {}
- for key in HandlerSerializer.Meta.fields:
- if key in data:
- handler_internal[key] = data.pop(key)
- data["handler"] = handler_internal
- internal = super().to_internal_value(data)
- return internal
+ try:
+ internal = super().to_internal_value(data)
+ return internal
+ except ValidationError as exc:
+ raise exc
diff --git a/server/apps/trak/services/site_service.py b/server/apps/trak/services/site_service.py
index ed89fc6a2..ed3d0ce3b 100644
--- a/server/apps/trak/services/site_service.py
+++ b/server/apps/trak/services/site_service.py
@@ -39,7 +39,7 @@ def sync_rcra_manifest(self, *, site_id: str = None) -> Dict[str, List[str]]:
)
# ToDo: uncomment this after we have manifest development fixtures
# limit the number of manifest to sync at a time
- tracking_numbers = tracking_numbers[0:10]
+ tracking_numbers = tracking_numbers[0:5]
logger.info(f"Pulling {tracking_numbers} from RCRAInfo")
results: Dict[str, List[str]] = manifest_service.pull_manifests(
tracking_numbers=tracking_numbers
diff --git a/server/apps/trak/tests/conftest.py b/server/apps/trak/tests/conftest.py
index 54c3b2c20..fb92b562f 100644
--- a/server/apps/trak/tests/conftest.py
+++ b/server/apps/trak/tests/conftest.py
@@ -224,12 +224,16 @@ def create_e_signature(
@pytest.fixture
-def manifest_handler_factory(db, handler_factory):
+def manifest_handler_factory(db, handler_factory, paper_signature_factory):
"""Abstract factory for Haztrak ManifestHandler model"""
- def create_manifest_handler(handler: Optional[Handler] = None) -> ManifestHandler:
+ def create_manifest_handler(
+ handler: Optional[Handler] = None,
+ paper_signature: Optional[PaperSignature] = None,
+ ) -> ManifestHandler:
return ManifestHandler.objects.create(
handler=handler or handler_factory(),
+ paper_signature=paper_signature or paper_signature_factory(),
)
return create_manifest_handler
diff --git a/server/apps/trak/tests/models/test_handler.py b/server/apps/trak/tests/models/test_handler.py
index 1dd624496..d3374df58 100644
--- a/server/apps/trak/tests/models/test_handler.py
+++ b/server/apps/trak/tests/models/test_handler.py
@@ -12,3 +12,29 @@ def test_manager_creates_new_handler(self, handler_serializer) -> None:
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)
+
+ def test_signed_both_signatures_exists(self, manifest_handler_factory, e_signature_factory):
+ manifest_handler = manifest_handler_factory()
+ e_signature_factory(manifest_handler=manifest_handler)
+ assert manifest_handler.signed is True
+
+ def test_signed_only_paper(self, manifest_handler_factory):
+ manifest_handler = manifest_handler_factory()
+ assert manifest_handler.signed is True
+
+ def test_signed_only_electronic(self, handler_factory, e_signature_factory):
+ manifest_handler = ManifestHandler(
+ handler=handler_factory(),
+ paper_signature=None,
+ )
+ manifest_handler.save()
+ e_signature_factory(manifest_handler=manifest_handler)
+ assert manifest_handler.signed is True
+
+ def test_signed_with_no_signatures(self, handler_factory):
+ manifest_handler = ManifestHandler(
+ handler=handler_factory(),
+ paper_signature=None,
+ )
+ manifest_handler.save()
+ assert manifest_handler.signed is False
diff --git a/server/pyproject.toml b/server/pyproject.toml
index 215a7f1b2..040dc5f55 100644
--- a/server/pyproject.toml
+++ b/server/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "haztrak"
-version = "0.2.0"
+version = "0.3.0"
description = "An open-source web app illustrating how waste management software can interface with RCRAInfo to track hazardous waste"
readme = "README.md"
authors = [
|