Handle getting the correct user_card_detail

Fixes

Traceback (most recent call last):
  File "<console>", line 2, in <module>
  File "/home/app/pyvenv/lib/python3.5/site-packages/django/db/models/manager.py", line 122, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/home/app/pyvenv/lib/python3.5/site-packages/django/db/models/query.py", line 391, in get
    (self.model._meta.object_name, num)
hosting.models.MultipleObjectsReturned: get() returned more than one UserCardDetail -- it returned 2!
This commit is contained in:
PCoder 2025-05-16 16:05:50 +05:30
commit 60ddfa78b0
3 changed files with 93 additions and 7 deletions

View file

@ -613,7 +613,7 @@ class OrderConfirmationView(DetailView, FormView):
# TODO check when we go through this case (to me, it seems useless)
card_id = self.request.session.get('card_id')
logger.debug("NO id_payment_method, using card: %s" % card_id)
card_detail = UserCardDetail.objects.get(id=card_id)
card_detail = UserCardDetail.get_ucd_from_card_id(card_id=card_id)
context['cc_last4'] = card_detail.last4
context['cc_brand'] = card_detail.brand
context['cc_exp_year'] = card_detail.exp_year
@ -852,7 +852,7 @@ class OrderConfirmationView(DetailView, FormView):
return show_error(msg, self.request)
elif 'card_id' in request.session:
card_id = request.session.get('card_id')
user_card_detail = UserCardDetail.objects.get(id=card_id)
user_card_detail = UserCardDetail.get_ucd_from_card_id(card_id=card_id)
card_details_dict = {
'last4': user_card_detail.last4,
'brand': user_card_detail.brand,
@ -1206,7 +1206,7 @@ def set_user_card(card_id, stripe_api_cus_id, custom_user,
card_details_response):
if card_id:
logger.debug("card_id %s was in request" % card_id)
user_card_detail = UserCardDetail.objects.get(id=card_id)
user_card_detail = UserCardDetail.get_ucd_from_card_id(card_id=card_id)
card_details_dict = {
'last4': user_card_detail.last4,
'brand': user_card_detail.brand,

View file

@ -700,7 +700,7 @@ class UserCardDetail(AssignPermissionsMixin, models.Model):
@staticmethod
def save_default_card_local(stripe_api_cus_id, card_id):
stripe_cust = StripeCustomer.objects.get(stripe_id=stripe_api_cus_id)
user_card_detail = UserCardDetail.objects.get(
user_card_detail = UserCardDetail.get_ucd_from_stripe_cust_n_card_id(
stripe_customer=stripe_cust, card_id=card_id
)
for card in stripe_cust.usercarddetail_set.all():
@ -709,6 +709,92 @@ class UserCardDetail(AssignPermissionsMixin, models.Model):
user_card_detail.preferred = True
user_card_detail.save()
@staticmethod
def get_ucd_from_card_id(card_id):
try:
user_card_details = UserCardDetail.objects.filter(
card_id=card_id
).order_by('-id')
if user_card_details.count() > 1:
# Log a warning about the duplicate entries
logger.warning(
f"Multiple UserCardDetail objects found for card_id={card_id}. "
f"Found {user_card_details.count()} objects. Using the latest one."
)
# Use the first object found
user_card_detail = user_card_details.first()
elif user_card_details.count() == 1:
# Exactly one object found, proceed as intended
user_card_detail = user_card_details.first()
else:
# No object found for the given customer and card_id.
# Depending on expected behavior, you might want to raise an error or handle this case.
# If the original get() call happened here, it would raise DoesNotExist.
logger.error(
f"No UserCardDetail found for card_id={card_id}."
)
raise UserCardDetail.DoesNotExist(f"No UserCardDetail found for card {card_id}")
if user_card_details.count() > 1:
# Log a warning about the duplicate entries
logger.warning(
f"Multiple UserCardDetail objects found for card_id={card_id}. "
f"Found {user_card_details.count()} objects. Using the first one."
)
# Use the first object found
user_card_detail = user_card_details.first()
elif user_card_details.count() == 1:
# Exactly one object found, proceed as intended
user_card_detail = user_card_details.first()
else:
# No object found for the given customer and card_id.
# Depending on expected behavior, you might want to raise an error or handle this case.
# If the original get() call happened here, it would raise DoesNotExist.
logger.error(
f"No UserCardDetail found for card_id={card_id}."
)
raise UserCardDetail.DoesNotExist(f"No UserCardDetail found for card {card_id}")
except Exception as e:
# Catch other potential exceptions during the filter/get process if necessary
logger.error(f"An unexpected error occurred while fetching UserCardDetail: {e}")
raise
return user_card_detail
@staticmethod
def get_ucd_from_stripe_cust_n_card_id(stripe_cust, card_id):
try:
user_card_details = UserCardDetail.objects.filter(
stripe_customer=stripe_cust, card_id=card_id
).order_by('-id')
if user_card_details.count() > 1:
# Log a warning about the duplicate entries
logger.warning(
f"Multiple UserCardDetail objects found for stripe_customer_id={stripe_cust.id} and card_id={card_id}. "
f"Found {user_card_details.count()} objects. Using the first one."
)
# Use the first object found
user_card_detail = user_card_details.first()
elif user_card_details.count() == 1:
# Exactly one object found, proceed as intended
user_card_detail = user_card_details.first()
else:
# No object found for the given customer and card_id.
# Depending on expected behavior, you might want to raise an error or handle this case.
# If the original get() call happened here, it would raise DoesNotExist.
logger.error(
f"No UserCardDetail found for stripe_customer_id={stripe_cust.id} and card_id={card_id}."
)
raise UserCardDetail.DoesNotExist(f"No UserCardDetail found for customer {stripe_cust.id}, card {card_id}")
except Exception as e:
# Catch other potential exceptions during the filter/get process if necessary
logger.error(f"An unexpected error occurred while fetching UserCardDetail: {e}")
raise
return user_card_detail
@staticmethod
def get_user_card_details(stripe_customer, card_details):
"""

View file

@ -810,7 +810,7 @@ class PaymentVMView(LoginRequiredMixin, FormView):
card_id = form.cleaned_data.get('card')
customer = owner.stripecustomer
try:
user_card_detail = UserCardDetail.objects.get(id=card_id)
user_card_detail = UserCardDetail.get_ucd_from_card_id(card_id=card_id)
if not request.user.has_perm(
'view_usercarddetail', user_card_detail
):
@ -1014,7 +1014,7 @@ class OrdersHostingDetailView(LoginRequiredMixin, DetailView, FormView):
context['cc_exp_month'] = card_details_response['exp_month']
else:
card_id = self.request.session.get('card_id')
card_detail = UserCardDetail.objects.get(id=card_id)
card_detail = UserCardDetail.get_ucd_from_card_id(card_id=card_id)
context['cc_last4'] = card_detail.last4
context['cc_brand'] = card_detail.brand
context['cc_exp_year'] = card_detail.exp_year
@ -1128,7 +1128,7 @@ class OrdersHostingDetailView(LoginRequiredMixin, DetailView, FormView):
return JsonResponse(response)
else:
card_id = request.session.get('card_id')
user_card_detail = UserCardDetail.objects.get(id=card_id)
user_card_detail = UserCardDetail.get_ucd_from_card_id(card_id=card_id)
card_details_dict = {
'last4': user_card_detail.last4,
'brand': user_card_detail.brand,