def get(self, request, **kwargs):
        """

        :param request:
        :return:
        """
        try:
            invoice = stripe.Invoice.retrieve(str(kwargs['invoice_id']))
        except (APIConnectionError, InvalidRequestError, CardError) as err:
            message = stripe_errors_handler(err)
            self.logger.error(message)
            return Response(message, status=status.HTTP_400_BAD_REQUEST)
        else:
            mapped_invoice = get_invoices_list_response([invoice],
                                                        request.user.email)[0]
            stripe_invoice_id = str(mapped_invoice['id'])
            invoice_obj = self.get_object(stripe_invoice_id)
            if invoice_obj.exists():
                serial_number = invoice_obj.first().serial_number
            else:
                invoice_obj = Invoice.objects.create(
                    stripe_id=stripe_invoice_id)
                invoice_obj.serial_number = serial_number = invoice_obj.generate_invoice_number(
                )
                invoice_obj.save()
            extra_data = UserDataSerializer(request.user).data
            extra_data['invoice_number'] = serial_number
            return Response(dict(mapped_invoice, **extra_data),
                            status=status.HTTP_200_OK)
    def create(self, validated_data):
        """Method rewrote to customize the creation of a user and handling stripe exceptions

        :param validated_data: request(dict) already validated
        :except: message of invalid request error when hitting stripe api
        :return: user object created
        """
        del validated_data['terms_conditions']
        plan_id = validated_data.pop('plan_id')
        card_token = validated_data.pop('card_token')
        is_corporate_account = bool(validated_data.pop('is_corporate_account'))

        try:
            customer = stripe.Customer.create(description='Customer for ' +
                                              validated_data['email'],
                                              source=card_token,
                                              email=validated_data['email'],
                                              plan=plan_id)
        except (APIConnectionError, InvalidRequestError, CardError) as err:
            message = stripe_errors_handler(err)
            self.logger.error(message)
            raise serializers.ValidationError(message)
        else:
            validated_data[
                'tax_receipts_as'] = 2 if is_corporate_account else 1
            user = create_user_hashing_password(**validated_data)
            if not user:
                raise serializers.ValidationError(
                    'There was an Integrity Error creating a user')
            CustomerStripe.objects.create(user=user, customer_id=customer.id)
            return user
    def update_subscription_plan(self, customer, plan_id):
        """

        :param customer:
        :param plan_id:
        :return:
        """
        subscription_id = str(customer.subscriptions.data[0].id)
        try:
            subscription = stripe.Subscription.retrieve(subscription_id)
        except (APIConnectionError, InvalidRequestError, CardError) as err:
            message = stripe_errors_handler(err)
            self.logger.error(message)
            return message
        else:
            subscription.plan = plan_id
            try:
                subscription.save()
            except (APIConnectionError, InvalidRequestError, CardError) as err:
                message = stripe_errors_handler(err)
                self.logger.error(message)
                return message
            else:
                return subscription
    def update_payment_method(self, customer, card_token):
        """

        :param customer:
        :param card_token:
        :return:
        """
        customer.source = card_token
        try:
            customer.save()
        except (APIConnectionError, InvalidRequestError, CardError) as err:
            message = stripe_errors_handler(err)
            self.logger.error(message)
            return message
        else:
            return customer
    def get(self, request):
        """Method to list all plans stored in stripe handling exceptions

        :param request: To use in a future query params filtering
        :except: Api connection error from stripe
        :return: List of plans
        """
        try:
            plans = stripe.Plan.list()
        except (APIConnectionError, InvalidRequestError, CardError) as err:
            message = stripe_errors_handler(err)
            self.logger.error(message)
            return Response(message, status=status.HTTP_400_BAD_REQUEST)
        else:
            mapped_plans = get_plans_list_response(plans)
            if request.user.is_authenticated():
                customer = get_customer_in_stripe(request.user)
                if isinstance(customer, str):
                    return Response(customer, status=status.HTTP_404_NOT_FOUND)
                else:
                    currency = customer.subscriptions.data[0]['plan'].currency
                    filtered_plans = filtering_plan_by_currency(
                        mapped_plans, str(currency))
                    no_free_plans = reject_free_plans(filtered_plans)
                    return Response(no_free_plans, status=status.HTTP_200_OK)
            country_id = request.GET.get('country', None)
            free_plans = filter_free_plans(mapped_plans)
            if country_id:
                try:
                    country_id = int(country_id)
                except ValueError:
                    pass
                else:
                    if country_id == 2:
                        currency = 'usd'
                    elif country_id == 1:
                        currency = 'cad'
                    else:
                        currency = ''
                    response = filtering_plan_by_currency(free_plans, currency)
                    return Response(response, status=status.HTTP_200_OK)
            return Response(free_plans, status=status.HTTP_200_OK)
def get_customer_in_stripe(instance):
    """

    :param instance:
    :return:
    """
    customer_stripe = CustomerStripe.objects.filter(user=instance.id)
    if customer_stripe.exists():
        try:
            customer = stripe.Customer.retrieve(
                customer_stripe.first().customer_id)
        except (APIConnectionError, InvalidRequestError, CardError) as err:
            error = stripe_errors_handler(err)
            logger = logging.getLogger(__name__)
            logger.error(error)
        else:
            return customer
    else:
        error = "There is no stripe customer available for this user"
    return error