diff --git a/datacenterlight/views.py b/datacenterlight/views.py index 1c770b3a..709d1c44 100644 --- a/datacenterlight/views.py +++ b/datacenterlight/views.py @@ -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, diff --git a/hosting/models.py b/hosting/models.py index b51d8616..5cc3d0fd 100644 --- a/hosting/models.py +++ b/hosting/models.py @@ -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): """ diff --git a/hosting/views.py b/hosting/views.py index 637a112b..c2470707 100644 --- a/hosting/views.py +++ b/hosting/views.py @@ -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,