Skip to content

Commit a6132c6

Browse files
committed
feat: Add Segment events for CheckoutIntent state transitions
Track state changes in CheckoutIntent lifecycle by emitting appropriate Segment analytics events on transitions
1 parent 5091aa0 commit a6132c6

File tree

4 files changed

+396
-0
lines changed

4 files changed

+396
-0
lines changed

enterprise_access/apps/customer_billing/apps.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,6 @@
66
class CustomerBillingConfig(AppConfig):
77
default_auto_field = 'django.db.models.BigAutoField'
88
name = 'enterprise_access.apps.customer_billing'
9+
10+
def ready(self):
11+
import enterprise_access.apps.customer_billing.signals # noqa

enterprise_access/apps/customer_billing/constants.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,12 @@ class CheckoutIntentState(StrEnum):
7373
ERRORED_PROVISIONING = 'errored_provisioning'
7474
EXPIRED = 'expired'
7575

76+
class CheckoutIntentSegmentEvents:
77+
"""
78+
Segment events for CheckoutIntent lifecycle tracking.
79+
"""
80+
LIFECYCLE_EVENT = 'edx.server.enterprise-access.checkout-intent.lifecycle.event'
81+
7682

7783
ALLOWED_CHECKOUT_INTENT_STATE_TRANSITIONS = {
7884
CheckoutIntentState.CREATED: [
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
from django.db.models.signals import post_save, pre_save
2+
from django.dispatch import receiver
3+
4+
from enterprise_access.apps.api.serializers import CheckoutIntentReadOnlySerializer
5+
from enterprise_access.apps.customer_billing.constants import (
6+
CheckoutIntentSegmentEvents,
7+
)
8+
from enterprise_access.apps.customer_billing.models import CheckoutIntent
9+
from enterprise_access.apps.track.segment import track_event
10+
11+
12+
@receiver(pre_save, sender=CheckoutIntent)
13+
def capture_previous_state(sender, instance, **kwargs):
14+
"""Capture the previous state before saving."""
15+
if instance.pk: # Only for updates, not creation
16+
try:
17+
instance._previous_state = CheckoutIntent.objects.get(pk=instance.pk).state
18+
except CheckoutIntent.DoesNotExist:
19+
instance._previous_state = None
20+
else:
21+
instance._previous_state = None
22+
23+
24+
@receiver(post_save, sender=CheckoutIntent)
25+
def track_checkout_intent_changes(sender, instance, created, **kwargs):
26+
"""Automatically track events after save."""
27+
previous_state = None if created else getattr(instance, '_previous_state', None)
28+
29+
# Only track if it's a creation or if the state actually changed
30+
if created or (previous_state is not None and previous_state != instance.state):
31+
properties = CheckoutIntentReadOnlySerializer(instance).data
32+
properties["previous_state"] = previous_state
33+
properties["new_state"] = instance.state
34+
35+
track_event(
36+
lms_user_id=str(instance.user.id),
37+
event_name=CheckoutIntentSegmentEvents.LIFECYCLE_EVENT,
38+
properties=properties,
39+
)

0 commit comments

Comments
 (0)