Fetching any Upcoming Invoice with a Discount fails
Biszu opened this issue · comments
Describe the bug
Fetching an upcoming invoice for a subscription with an applied Discount fails due to AttributeError
This is similar to #1973
Software versions
- dj-stripe version: 2.8.3
- Python version: 3.12
- Django version: 5.0.3
- Stripe API version: 2020-08-27
Steps To Reproduce
- Create a new subscription with a Discount.
- Try to get an upcoming invoice for the new subscription:
Invoice.upcoming(customer=c)
Can you reproduce the issue with the latest version of master?
Yes
Expected Behavior
Upcoming invoice details are fetched successfully.
Actual Behavior
Request fails due to AttributeError: 'str' object has no attribute 'get'
Stacktrace:
In [6]: Invoice.upcoming(customer=c)
[p-3304] [INFO] message='Request to Stripe api' method=get path=https://api.stripe.com/v1/invoices/upcoming?customer=cus_Pa0*****
[p-3304] [INFO] message='Stripe API response' path=https://api.stripe.com/v1/invoices/upcoming?customer=cus_Pa0*****
response_code=200
DoesNotExist Traceback (most recent call last)
File ~/Documents/*****/.venv/lib/python3.12/site-packages/djstripe/models/base.py:673, in StripeModel._create_from_stripe_object(cls, data, current_ids, pending_relations, save, stripe_account, api_key)
671 else:
672 # Raise error on purpose to resume the _create_from_stripe_object flow
--> 673 raise cls.DoesNotExist
675 except cls.DoesNotExist:
676 # try to create iff instance doesn't already exist in the DB
677 # TODO dictionary unpacking will not work if cls has any ManyToManyField
DoesNotExist:
During handling of the above exception, another exception occurred:
AttributeError Traceback (most recent call last)
Cell In[6], line 1
----> 1 Invoice.upcoming(customer=c)
File ~/Documents/*****/.venv/lib/python3.12/site-packages/djstripe/models/billing.py:797, in BaseInvoice.upcoming(cls, api_key, customer, subscription, subscription_plan, **kwargs)
794 # Workaround for "id" being missing (upcoming invoices don't persist).
795 upcoming_stripe_invoice["id"] = "upcoming"
--> 797 return UpcomingInvoice._create_from_stripe_object(
798 upcoming_stripe_invoice,
799 save=False,
800 api_key=api_key,
801 )
File ~/Documents/*****/.venv/lib/python3.12/site-packages/djstripe/models/base.py:687, in StripeModel._create_from_stripe_object(cls, data, current_ids, pending_relations, save, stripe_account, api_key)
684 if save:
685 instance.save()
--> 687 instance._attach_objects_post_save_hook(
688 cls, data, api_key=api_key, pending_relations=pending_relations
689 )
691 return instance
File ~/Documents/*****/.venv/lib/python3.12/site-packages/djstripe/models/billing.py:991, in UpcomingInvoice._attach_objects_post_save_hook(self, cls, data, api_key, pending_relations)
984 def _attach_objects_post_save_hook(
985 self,
986 cls,
(...)
989 pending_relations=None,
990 ):
--> 991 super()._attach_objects_post_save_hook(
992 cls, data, api_key=api_key, pending_relations=pending_relations
993 )
995 self._default_tax_rates = cls._stripe_object_to_default_tax_rates(
996 target_cls=TaxRate, data=data, api_key=api_key
997 )
999 total_tax_amounts = []
File ~/Documents/*****/.venv/lib/python3.12/site-packages/djstripe/models/billing.py:835, in BaseInvoice._attach_objects_post_save_hook(self, cls, data, api_key, pending_relations)
833 # sync every discount
834 for discount in self.discounts:
--> 835 Discount.sync_from_stripe_data(discount, api_key=api_key)
File ~/Documents/*****/.venv/lib/python3.12/site-packages/djstripe/models/base.py:1043, in StripeModel.sync_from_stripe_data(cls, data, api_key, stripe_version)
1033 """
1034 Syncs this object from the stripe data provided.
1035
(...)
1040 :rtype: cls
1041 """
1042 current_ids = set()
-> 1043 data_id = data.get("id")
1044 stripe_account = getattr(data, "stripe_account", None)
1046 if data_id:
1047 # stop nested objects from trying to retrieve this object before
1048 # initial sync is complete
AttributeError: 'str' object has no attribute 'get'
I fixed this by doing Invoice.upcoming(customer=c, expand=('discounts',))