def upcoming(
        cls,
        api_key=djstripe_settings.STRIPE_SECRET_KEY,
        customer=None,
        subscription=None,
        subscription_plan=None,
        **kwargs,
    ) -> Optional["UpcomingInvoice"]:
        """
        Gets the upcoming preview invoice (singular) for a customer.

        At any time, you can preview the upcoming
        invoice for a customer. This will show you all the charges that are
        pending, including subscription renewal charges, invoice item charges,
        etc. It will also show you any discount that is applicable to the
        customer. (Source: https://stripe.com/docs/api#upcoming_invoice)

        .. important:: Note that when you are viewing an upcoming invoice,
            you are simply viewing a preview.

        :param customer: The identifier of the customer whose upcoming invoice \
        you'd like to retrieve.
        :type customer: Customer or string (customer ID)
        :param coupon: The code of the coupon to apply.
        :type coupon: str
        :param subscription: The identifier of the subscription to retrieve an \
        invoice for.
        :type subscription: Subscription or string (subscription ID)
        :param subscription_plan: If set, the invoice returned will preview \
        updating the subscription given to this plan, or creating a new \
        subscription to this plan if no subscription is given.
        :type subscription_plan: Plan or string (plan ID)
        """

        # Convert Customer to id
        if customer is not None and isinstance(customer, StripeModel):
            customer = customer.id

        # Convert Subscription to id
        if subscription is not None and isinstance(subscription, StripeModel):
            subscription = subscription.id

        # Convert Plan to id
        if subscription_plan is not None and isinstance(subscription_plan, StripeModel):
            subscription_plan = subscription_plan.id

        try:
            upcoming_stripe_invoice = cls.stripe_class.upcoming(
                api_key=api_key,
                customer=customer,
                subscription=subscription,
                subscription_plan=subscription_plan,
                stripe_version=djstripe_settings.STRIPE_API_VERSION,
                **kwargs,
            )
        except InvalidRequestError as exc:
            if str(exc) != "Nothing to invoice for customer":
                raise
            return None

        # Workaround for "id" being missing (upcoming invoices don't persist).
        upcoming_stripe_invoice["id"] = "upcoming"

        return UpcomingInvoice._create_from_stripe_object(
            upcoming_stripe_invoice,
            save=False,
            api_key=api_key,
        )

        Gets the upcoming preview invoice (singular) for a customer.

        At any time, you can preview the upcoming
        invoice for a customer. This will show you all the charges that are
        pending, including subscription renewal charges, invoice item charges,
        etc. It will also show you any discount that is applicable to the
        customer. (Source: https://stripe.com/docs/api#upcoming_invoice)

        .. important:: Note that when you are viewing an upcoming invoice,
            you are simply viewing a preview.

        :param customer: The identifier of the customer whose upcoming invoice         you'd like to retrieve.
        :type customer: Customer or string (customer ID)
        :param coupon: The code of the coupon to apply.
        :type coupon: str
        :param subscription: The identifier of the subscription to retrieve an         invoice for.
        :type subscription: Subscription or string (subscription ID)
        :param subscription_plan: If set, the invoice returned will preview         updating the subscription given to this plan, or creating a new         subscription to this plan if no subscription is given.
        :type subscription_plan: Plan or string (plan ID)
        
djstripe/models/billing.py