Coverage for benefits / enrollment_littlepay / models.py: 96%
37 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-01 15:39 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-01 15:39 +0000
1import logging
3from django.core.exceptions import ValidationError
4from django.db import models
6from benefits.core.models import EnrollmentGroup, Environment, SecretNameField, TransitProcessorConfig
7from benefits.secrets import get_secret_by_name
9logger = logging.getLogger(__name__)
12class LittlepayConfig(TransitProcessorConfig):
13 """Configuration for connecting to Littlepay, an entity that applies transit agency fare rules to rider transactions."""
15 audience = models.TextField(
16 help_text="This agency's audience value used to access the TransitProcessor's API.", default="", blank=True
17 )
18 client_id = models.TextField(
19 help_text="This agency's client_id value used to access the TransitProcessor's API.", default="", blank=True
20 )
21 client_secret_name = SecretNameField(
22 help_text="The name of the secret containing this agency's client_secret value used to access the TransitProcessor's API.", # noqa: E501
23 default="",
24 blank=True,
25 )
27 @property
28 def api_base_url(self):
29 if self.environment == Environment.TEST.value:
30 return get_secret_by_name("littlepay-qa-api-base-url")
31 elif self.environment == Environment.PROD.value:
32 return get_secret_by_name("littlepay-prod-api-base-url")
33 else:
34 raise ValueError(f"Unexpected value for environment: {self.environment}")
36 @property
37 def client_secret(self):
38 secret_field = self._meta.get_field("client_secret_name")
39 return secret_field.secret_value(self)
41 def clean(self):
42 field_errors = {}
44 if self.pk and self.transitagency_set and any([agency.active for agency in self.transitagency_set.all()]):
45 message = "This field is required when this configuration is referenced by an active transit agency."
46 needed = dict(audience=self.audience, client_id=self.client_id, client_secret_name=self.client_secret_name)
47 field_errors.update({k: ValidationError(message) for k, v in needed.items() if not v})
49 if self.environment not in ["test", "prod"]: 49 ↛ 50line 49 didn't jump to line 50 because the condition on line 49 was never true
50 field_errors.update(
51 {"environment": ValidationError("Valid environment values for Littlepay are Testing and Production.")}
52 )
54 if field_errors:
55 raise ValidationError(field_errors)
58class LittlepayGroup(EnrollmentGroup):
59 group_id = models.UUIDField(default=None, blank=True, help_text="The ID of the Littlepay group for user enrollment.")
61 @staticmethod
62 def by_id(id):
63 """Get a LittlepayGroup instance by its ID."""
64 logger.debug(f"Get {LittlepayGroup.__name__} by id: {id}")
65 return LittlepayGroup.objects.get(id=id)