Skip to content

Commit 0a216aa

Browse files
authored
fix: fix migrations and add new test
1 parent 56702ba commit 0a216aa

File tree

4 files changed

+94
-26
lines changed

4 files changed

+94
-26
lines changed

enterprise_access/apps/api/v1/tests/test_stripe_event_summary_views.py

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ def setUp(self):
110110
expires_at=timezone.now() + timedelta(hours=1),
111111
)
112112

113-
# Create twp StripeEventData objects, will each create StripeEventSummary on create
113+
# Create two StripeEventData objects, will each create StripeEventSummary on create
114114
self.stripe_event_data = StripeEventData.objects.create(
115115
event_id='evt_test_invoice',
116116
event_type='invoice.paid',
@@ -178,3 +178,82 @@ def test_get_stripe_event_summary_by_subscription_uuid_no_auth(self):
178178
response = self.client.get(url)
179179
# trying to fetch a subscription plan for an enterprise customer they are not associated with
180180
assert response.status_code == 403
181+
182+
183+
class StripeEventUpcomingInvoiceAmountDueTests(APITest):
184+
"""
185+
Tests for first_upcoming_invoice_amount_due endpoint.
186+
"""
187+
188+
def setUp(self):
189+
super().setUp()
190+
self.user = UserFactory()
191+
self.enterprise_uuid = str(uuid.uuid4())
192+
self.stripe_customer_id = 'cus_test_123'
193+
self.subscription_plan_uuid = str(uuid.uuid4())
194+
195+
self.checkout_intent = CheckoutIntent.objects.create(
196+
user=self.user,
197+
enterprise_uuid=self.enterprise_uuid,
198+
enterprise_name='Test Enterprise',
199+
enterprise_slug='test-enterprise',
200+
stripe_customer_id=self.stripe_customer_id,
201+
state=CheckoutIntentState.PAID,
202+
quantity=10,
203+
expires_at=timezone.now() + timedelta(hours=1),
204+
)
205+
206+
subscription_event_data = {
207+
'id': 'evt_test_sub_created',
208+
'type': 'customer.subscription.created',
209+
'data': {
210+
'object': {
211+
'object': 'subscription',
212+
'id': 'sub_test_789',
213+
'status': 'active',
214+
'items': {
215+
'data': [
216+
{
217+
'object': 'subscription_item',
218+
'current_period_start': 1609459200, # 2021-01-01 00:00:00 UTC
219+
'current_period_end': 1640995200, # 2022-01-01 00:00:00 UTC
220+
}
221+
]
222+
},
223+
}
224+
},
225+
'metadata': {
226+
'checkout_intent_id': self.checkout_intent.id,
227+
'enterprise_customer_name': 'Test Enterprise',
228+
'enterprise_customer_slug': 'test-enterprise',
229+
}
230+
}
231+
232+
# Creating a StripeEventData record triggers a create of related StripeEventSummary
233+
self.stripe_event_data = StripeEventData.objects.create(
234+
event_id='evt_test_subscription',
235+
event_type='customer.subscription.created',
236+
checkout_intent=self.checkout_intent,
237+
data=subscription_event_data,
238+
)
239+
240+
test_summary = StripeEventSummary.objects.filter(event_id='evt_test_subscription').first()
241+
test_summary.upcoming_invoice_amount_due = 200
242+
test_summary.subscription_plan_uuid = self.subscription_plan_uuid
243+
test_summary.save(update_fields=['upcoming_invoice_amount_due', 'subscription_plan_uuid'])
244+
245+
def test_get_first_upcoming_invoice_amount_due(self):
246+
self.set_jwt_cookie([{
247+
'system_wide_role': SYSTEM_ENTERPRISE_ADMIN_ROLE,
248+
'context': self.enterprise_uuid, # implicit access to this enterprise
249+
}])
250+
251+
query_params = {
252+
'subscription_plan_uuid': self.subscription_plan_uuid,
253+
}
254+
255+
url = reverse('api:v1:stripe-event-summary-first-upcoming-invoice-amount-due')
256+
url += f"?{urlencode(query_params)}"
257+
response = self.client.get(url)
258+
assert response.status_code == 200
259+
assert response.data == {'upcoming_invoice_amount_due': 200}

enterprise_access/apps/api/v1/views/customer_billing.py

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -386,19 +386,16 @@ def create_checkout_portal_session(self, request, pk=None):
386386
'## Allowed State Transitions\n'
387387
'```\n'
388388
'created → paid\n'
389-
'created → expired\n'
389+
'created → errored_stripe_checkout\n'
390390
'paid → fulfilled\n'
391-
'paid → errored_backoffice\n'
392-
'paid → errored_fulfillment_stalled\n'
393391
'paid → errored_provisioning\n'
394-
'errored_provisioningfulfilled\n'
395-
'expiredcreated\n'
392+
'errored_stripe_checkoutpaid\n'
393+
'errored_provisioningpaid\n'
396394
'```\n'
397395
'## Integration Points\n'
398396
'- **Stripe Webhook**: Transitions from `created` to `paid` after successful payment\n'
399397
'- **Fulfillment Service**: Transitions from `paid` to `fulfilled` after provisioning\n'
400-
'- **Backoffice Integration**: Transitions to `errored_backoffice` on Salesforce failures\n'
401-
'- **Error Recovery**: Allows retry from `errored_provisioning` to `fulfilled`\n\n'
398+
'- **Error Recovery**: Allows retry from error states back to `paid`\n\n'
402399
),
403400
parameters=[
404401
OpenApiParameter(
@@ -532,8 +529,14 @@ def list(self, request, *args, **kwargs):
532529
methods=['get'],
533530
url_path='first-invoice-upcoming-amount-due',
534531
)
535-
def first_invoice_upcoming_amount_due(self, request, *args, **kwargs):
536-
summary = self.get_queryset().filter(event_type='customer.subscription.created').first()
532+
def first_upcoming_invoice_amount_due(self, request, *args, **kwargs):
533+
subscription_plan_uuid = self.request.query_params.get('subscription_plan_uuid')
534+
summary = StripeEventSummary.objects.filter(
535+
event_type='customer.subscription.created',
536+
subscription_plan_uuid=subscription_plan_uuid,
537+
).first()
538+
if not (subscription_plan_uuid and summary):
539+
return Response({})
537540
return Response({
538541
'upcoming_invoice_amount_due': summary.upcoming_invoice_amount_due,
539-
}, content_type='application/json')
542+
})

enterprise_access/apps/customer_billing/migrations/0018_merge_20251105_0545.py

Lines changed: 0 additions & 14 deletions
This file was deleted.

enterprise_access/apps/customer_billing/migrations/0017_upcoming_invoice_amount_due.py renamed to enterprise_access/apps/customer_billing/migrations/0019_upcoming_invoice_amount_due.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
class Migration(migrations.Migration):
77

88
dependencies = [
9-
('customer_billing', '0016_alter_checkoutintent_uuid_and_more'),
9+
('customer_billing', '0018_update_checkout_intent_error_states'),
1010
]
1111

1212
operations = [

0 commit comments

Comments
 (0)