mirror of
https://github.com/zulip/zulip.git
synced 2025-11-10 00:46:03 +00:00
billing: Fix the type annotation of Customer.stripe_customer_id.
This also fixes a bug in void_all_open_invoices function. If a realm with a local Customer object but without an associated stripe.Customer is passed to void_all_open_invoices, then the function will end up voiding the last 10 invoices created by billing system instead of voiding no invoices at all. This is because stripe.Invoice.list(customer=None) return last 10 invoices across all customers. But this bug won't cauuse any issue in production since void_all_open_invoices can be only invoked from /support page. And we show the option to void invoices in support page only if the realm has a paid plan. And it's not really possible for a realm to have a paid plan without having an associated stripe_customer_id. Plus I went through the void events in stripe stream since the PR to add void invoices was merged and there does not seems to be any suspicious events.
This commit is contained in:
@@ -319,6 +319,7 @@ def do_replace_payment_source(
|
|||||||
) -> stripe.Customer:
|
) -> stripe.Customer:
|
||||||
customer = get_customer_by_realm(user.realm)
|
customer = get_customer_by_realm(user.realm)
|
||||||
assert customer is not None # for mypy
|
assert customer is not None # for mypy
|
||||||
|
assert customer.stripe_customer_id is not None # for mypy
|
||||||
|
|
||||||
stripe_customer = stripe_get_customer(customer.stripe_customer_id)
|
stripe_customer = stripe_get_customer(customer.stripe_customer_id)
|
||||||
stripe_customer.source = stripe_token
|
stripe_customer.source = stripe_token
|
||||||
@@ -533,6 +534,8 @@ def process_initial_upgrade(
|
|||||||
) -> None:
|
) -> None:
|
||||||
realm = user.realm
|
realm = user.realm
|
||||||
customer = update_or_create_stripe_customer(user, stripe_token=stripe_token)
|
customer = update_or_create_stripe_customer(user, stripe_token=stripe_token)
|
||||||
|
assert customer.stripe_customer_id is not None # for mypy
|
||||||
|
|
||||||
charge_automatically = stripe_token is not None
|
charge_automatically = stripe_token is not None
|
||||||
free_trial = is_free_trial_offer_enabled()
|
free_trial = is_free_trial_offer_enabled()
|
||||||
|
|
||||||
@@ -710,6 +713,11 @@ def update_license_ledger_if_needed(realm: Realm, event_time: datetime) -> None:
|
|||||||
def invoice_plan(plan: CustomerPlan, event_time: datetime) -> None:
|
def invoice_plan(plan: CustomerPlan, event_time: datetime) -> None:
|
||||||
if plan.invoicing_status == CustomerPlan.STARTED:
|
if plan.invoicing_status == CustomerPlan.STARTED:
|
||||||
raise NotImplementedError("Plan with invoicing_status==STARTED needs manual resolution.")
|
raise NotImplementedError("Plan with invoicing_status==STARTED needs manual resolution.")
|
||||||
|
if not plan.customer.stripe_customer_id:
|
||||||
|
raise BillingError(
|
||||||
|
f"Realm {plan.customer.realm.string_id} has a paid plan without a Stripe customer."
|
||||||
|
)
|
||||||
|
|
||||||
make_end_of_cycle_updates_if_needed(plan, event_time)
|
make_end_of_cycle_updates_if_needed(plan, event_time)
|
||||||
|
|
||||||
if plan.invoicing_status == CustomerPlan.INITIAL_INVOICE_TO_BE_SENT:
|
if plan.invoicing_status == CustomerPlan.INITIAL_INVOICE_TO_BE_SENT:
|
||||||
@@ -957,6 +965,8 @@ def void_all_open_invoices(realm: Realm) -> int:
|
|||||||
customer = get_customer_by_realm(realm)
|
customer = get_customer_by_realm(realm)
|
||||||
if customer is None:
|
if customer is None:
|
||||||
return 0
|
return 0
|
||||||
|
if customer.stripe_customer_id is None:
|
||||||
|
return 0
|
||||||
invoices = stripe.Invoice.list(customer=customer.stripe_customer_id)
|
invoices = stripe.Invoice.list(customer=customer.stripe_customer_id)
|
||||||
voided_invoices_count = 0
|
voided_invoices_count = 0
|
||||||
for invoice in invoices:
|
for invoice in invoices:
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ class Customer(models.Model):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
realm: Realm = models.OneToOneField(Realm, on_delete=CASCADE)
|
realm: Realm = models.OneToOneField(Realm, on_delete=CASCADE)
|
||||||
stripe_customer_id: str = models.CharField(max_length=255, null=True, unique=True)
|
stripe_customer_id: Optional[str] = models.CharField(max_length=255, null=True, unique=True)
|
||||||
sponsorship_pending: bool = models.BooleanField(default=False)
|
sponsorship_pending: bool = models.BooleanField(default=False)
|
||||||
# A percentage, like 85.
|
# A percentage, like 85.
|
||||||
default_discount: Optional[Decimal] = models.DecimalField(
|
default_discount: Optional[Decimal] = models.DecimalField(
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
{
|
||||||
|
"account_balance": 0,
|
||||||
|
"address": null,
|
||||||
|
"balance": 0,
|
||||||
|
"created": 1000000000,
|
||||||
|
"currency": null,
|
||||||
|
"default_source": null,
|
||||||
|
"delinquent": false,
|
||||||
|
"description": "lear (Lear & Co.)",
|
||||||
|
"discount": null,
|
||||||
|
"email": "king@lear.org",
|
||||||
|
"id": "cus_NORMALIZED0002",
|
||||||
|
"invoice_prefix": "NORMA02",
|
||||||
|
"invoice_settings": {
|
||||||
|
"custom_fields": null,
|
||||||
|
"default_payment_method": null,
|
||||||
|
"footer": null
|
||||||
|
},
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {
|
||||||
|
"realm_id": "2",
|
||||||
|
"realm_str": "lear"
|
||||||
|
},
|
||||||
|
"name": null,
|
||||||
|
"next_invoice_sequence": 1,
|
||||||
|
"object": "customer",
|
||||||
|
"phone": null,
|
||||||
|
"preferred_locales": [],
|
||||||
|
"shipping": null,
|
||||||
|
"sources": {
|
||||||
|
"data": [],
|
||||||
|
"has_more": false,
|
||||||
|
"object": "list",
|
||||||
|
"total_count": 0,
|
||||||
|
"url": "/v1/customers/cus_NORMALIZED0002/sources"
|
||||||
|
},
|
||||||
|
"subscriptions": {
|
||||||
|
"data": [],
|
||||||
|
"has_more": false,
|
||||||
|
"object": "list",
|
||||||
|
"total_count": 0,
|
||||||
|
"url": "/v1/customers/cus_NORMALIZED0002/subscriptions"
|
||||||
|
},
|
||||||
|
"tax_exempt": "none",
|
||||||
|
"tax_ids": {
|
||||||
|
"data": [],
|
||||||
|
"has_more": false,
|
||||||
|
"object": "list",
|
||||||
|
"total_count": 0,
|
||||||
|
"url": "/v1/customers/cus_NORMALIZED0002/tax_ids"
|
||||||
|
},
|
||||||
|
"tax_info": null,
|
||||||
|
"tax_info_verification": null
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"account_country": "US",
|
"account_country": "US",
|
||||||
"account_name": null,
|
"account_name": "NORMALIZED-1",
|
||||||
|
"account_tax_ids": null,
|
||||||
"amount_due": 6400,
|
"amount_due": 6400,
|
||||||
"amount_paid": 0,
|
"amount_paid": 0,
|
||||||
"amount_remaining": 6400,
|
"amount_remaining": 6400,
|
||||||
@@ -8,6 +9,10 @@
|
|||||||
"attempt_count": 0,
|
"attempt_count": 0,
|
||||||
"attempted": false,
|
"attempted": false,
|
||||||
"auto_advance": true,
|
"auto_advance": true,
|
||||||
|
"automatic_tax": {
|
||||||
|
"enabled": false,
|
||||||
|
"status": null
|
||||||
|
},
|
||||||
"billing": "send_invoice",
|
"billing": "send_invoice",
|
||||||
"billing_reason": "manual",
|
"billing_reason": "manual",
|
||||||
"charge": null,
|
"charge": null,
|
||||||
@@ -37,6 +42,7 @@
|
|||||||
"hosted_invoice_url": null,
|
"hosted_invoice_url": null,
|
||||||
"id": "in_NORMALIZED00000000000001",
|
"id": "in_NORMALIZED00000000000001",
|
||||||
"invoice_pdf": null,
|
"invoice_pdf": null,
|
||||||
|
"last_finalization_error": null,
|
||||||
"lines": {
|
"lines": {
|
||||||
"data": [
|
"data": [
|
||||||
{
|
{
|
||||||
@@ -61,13 +67,13 @@
|
|||||||
"billing_scheme": "per_unit",
|
"billing_scheme": "per_unit",
|
||||||
"created": 1000000000,
|
"created": 1000000000,
|
||||||
"currency": "usd",
|
"currency": "usd",
|
||||||
"id": "price_1HFiX7D2X8vgpBNGZKqyye0n",
|
"id": "price_1J3ngLD2X8vgpBNGNhl10Ejf",
|
||||||
"livemode": false,
|
"livemode": false,
|
||||||
"lookup_key": null,
|
"lookup_key": null,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"nickname": null,
|
"nickname": null,
|
||||||
"object": "price",
|
"object": "price",
|
||||||
"product": "prod_HpNH3ZK9Bpc89P",
|
"product": "prod_JhC49N48jYmZQ8",
|
||||||
"recurring": null,
|
"recurring": null,
|
||||||
"tiers_mode": null,
|
"tiers_mode": null,
|
||||||
"transform_quantity": null,
|
"transform_quantity": null,
|
||||||
@@ -81,7 +87,7 @@
|
|||||||
"tax_amounts": [],
|
"tax_amounts": [],
|
||||||
"tax_rates": [],
|
"tax_rates": [],
|
||||||
"type": "invoiceitem",
|
"type": "invoiceitem",
|
||||||
"unique_id": "il_1HFiX7D2X8vgpBNGYzYwN35m"
|
"unique_id": "il_1J3ngLD2X8vgpBNGyyqmhLYe"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"has_more": false,
|
"has_more": false,
|
||||||
@@ -94,8 +100,13 @@
|
|||||||
"next_payment_attempt": null,
|
"next_payment_attempt": null,
|
||||||
"number": "NORMALI-0001",
|
"number": "NORMALI-0001",
|
||||||
"object": "invoice",
|
"object": "invoice",
|
||||||
|
"on_behalf_of": null,
|
||||||
"paid": false,
|
"paid": false,
|
||||||
"payment_intent": null,
|
"payment_intent": null,
|
||||||
|
"payment_settings": {
|
||||||
|
"payment_method_options": null,
|
||||||
|
"payment_method_types": null
|
||||||
|
},
|
||||||
"period_end": 1000000000,
|
"period_end": 1000000000,
|
||||||
"period_start": 1000000000,
|
"period_start": 1000000000,
|
||||||
"post_payment_credit_notes_amount": 0,
|
"post_payment_credit_notes_amount": 0,
|
||||||
@@ -118,5 +129,5 @@
|
|||||||
"total_discount_amounts": [],
|
"total_discount_amounts": [],
|
||||||
"total_tax_amounts": [],
|
"total_tax_amounts": [],
|
||||||
"transfer_data": null,
|
"transfer_data": null,
|
||||||
"webhooks_delivered_at": 1000000000
|
"webhooks_delivered_at": null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,133 @@
|
|||||||
|
{
|
||||||
|
"account_country": "US",
|
||||||
|
"account_name": "NORMALIZED-1",
|
||||||
|
"account_tax_ids": null,
|
||||||
|
"amount_due": 6400,
|
||||||
|
"amount_paid": 0,
|
||||||
|
"amount_remaining": 6400,
|
||||||
|
"application_fee": null,
|
||||||
|
"attempt_count": 0,
|
||||||
|
"attempted": false,
|
||||||
|
"auto_advance": true,
|
||||||
|
"automatic_tax": {
|
||||||
|
"enabled": false,
|
||||||
|
"status": null
|
||||||
|
},
|
||||||
|
"billing": "send_invoice",
|
||||||
|
"billing_reason": "manual",
|
||||||
|
"charge": null,
|
||||||
|
"collection_method": "send_invoice",
|
||||||
|
"created": 1000000000,
|
||||||
|
"currency": "usd",
|
||||||
|
"custom_fields": null,
|
||||||
|
"customer": "cus_NORMALIZED0002",
|
||||||
|
"customer_address": null,
|
||||||
|
"customer_email": "king@lear.org",
|
||||||
|
"customer_name": null,
|
||||||
|
"customer_phone": null,
|
||||||
|
"customer_shipping": null,
|
||||||
|
"customer_tax_exempt": "none",
|
||||||
|
"customer_tax_ids": [],
|
||||||
|
"date": 1000000000,
|
||||||
|
"default_payment_method": null,
|
||||||
|
"default_source": null,
|
||||||
|
"default_tax_rates": [],
|
||||||
|
"description": null,
|
||||||
|
"discount": null,
|
||||||
|
"discounts": [],
|
||||||
|
"due_date": 1000000000,
|
||||||
|
"ending_balance": null,
|
||||||
|
"finalized_at": null,
|
||||||
|
"footer": null,
|
||||||
|
"hosted_invoice_url": null,
|
||||||
|
"id": "in_NORMALIZED00000000000002",
|
||||||
|
"invoice_pdf": null,
|
||||||
|
"last_finalization_error": null,
|
||||||
|
"lines": {
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"amount": 6400,
|
||||||
|
"currency": "usd",
|
||||||
|
"description": "Zulip standard upgrade",
|
||||||
|
"discount_amounts": [],
|
||||||
|
"discountable": false,
|
||||||
|
"discounts": [],
|
||||||
|
"id": "ii_NORMALIZED00000000000002",
|
||||||
|
"invoice_item": "ii_NORMALIZED00000000000002",
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "line_item",
|
||||||
|
"period": {
|
||||||
|
"end": 1000000000,
|
||||||
|
"start": 1000000000
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"price": {
|
||||||
|
"active": false,
|
||||||
|
"billing_scheme": "per_unit",
|
||||||
|
"created": 1000000000,
|
||||||
|
"currency": "usd",
|
||||||
|
"id": "price_1J3ngOD2X8vgpBNG4pn2DcHN",
|
||||||
|
"livemode": false,
|
||||||
|
"lookup_key": null,
|
||||||
|
"metadata": {},
|
||||||
|
"nickname": null,
|
||||||
|
"object": "price",
|
||||||
|
"product": "prod_JhC4jKCcSa3kkS",
|
||||||
|
"recurring": null,
|
||||||
|
"tiers_mode": null,
|
||||||
|
"transform_quantity": null,
|
||||||
|
"type": "one_time",
|
||||||
|
"unit_amount": 800,
|
||||||
|
"unit_amount_decimal": "800"
|
||||||
|
},
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 8,
|
||||||
|
"subscription": null,
|
||||||
|
"tax_amounts": [],
|
||||||
|
"tax_rates": [],
|
||||||
|
"type": "invoiceitem",
|
||||||
|
"unique_id": "il_1J3ngOD2X8vgpBNG5FHfGv4J"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"has_more": false,
|
||||||
|
"object": "list",
|
||||||
|
"total_count": 1,
|
||||||
|
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||||
|
},
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"next_payment_attempt": null,
|
||||||
|
"number": "NORMALI-0002",
|
||||||
|
"object": "invoice",
|
||||||
|
"on_behalf_of": null,
|
||||||
|
"paid": false,
|
||||||
|
"payment_intent": null,
|
||||||
|
"payment_settings": {
|
||||||
|
"payment_method_options": null,
|
||||||
|
"payment_method_types": null
|
||||||
|
},
|
||||||
|
"period_end": 1000000000,
|
||||||
|
"period_start": 1000000000,
|
||||||
|
"post_payment_credit_notes_amount": 0,
|
||||||
|
"pre_payment_credit_notes_amount": 0,
|
||||||
|
"receipt_number": null,
|
||||||
|
"starting_balance": 0,
|
||||||
|
"statement_descriptor": "Zulip Standard",
|
||||||
|
"status": "draft",
|
||||||
|
"status_transitions": {
|
||||||
|
"finalized_at": null,
|
||||||
|
"marked_uncollectible_at": null,
|
||||||
|
"paid_at": null,
|
||||||
|
"voided_at": null
|
||||||
|
},
|
||||||
|
"subscription": null,
|
||||||
|
"subtotal": 6400,
|
||||||
|
"tax": null,
|
||||||
|
"tax_percent": null,
|
||||||
|
"total": 6400,
|
||||||
|
"total_discount_amounts": [],
|
||||||
|
"total_tax_amounts": [],
|
||||||
|
"transfer_data": null,
|
||||||
|
"webhooks_delivered_at": null
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"account_country": "US",
|
"account_country": "US",
|
||||||
"account_name": null,
|
"account_name": "NORMALIZED-1",
|
||||||
|
"account_tax_ids": null,
|
||||||
"amount_due": 6400,
|
"amount_due": 6400,
|
||||||
"amount_paid": 0,
|
"amount_paid": 0,
|
||||||
"amount_remaining": 6400,
|
"amount_remaining": 6400,
|
||||||
@@ -8,6 +9,10 @@
|
|||||||
"attempt_count": 0,
|
"attempt_count": 0,
|
||||||
"attempted": false,
|
"attempted": false,
|
||||||
"auto_advance": true,
|
"auto_advance": true,
|
||||||
|
"automatic_tax": {
|
||||||
|
"enabled": false,
|
||||||
|
"status": null
|
||||||
|
},
|
||||||
"billing": "send_invoice",
|
"billing": "send_invoice",
|
||||||
"billing_reason": "manual",
|
"billing_reason": "manual",
|
||||||
"charge": null,
|
"charge": null,
|
||||||
@@ -34,9 +39,10 @@
|
|||||||
"ending_balance": 0,
|
"ending_balance": 0,
|
||||||
"finalized_at": 1000000000,
|
"finalized_at": 1000000000,
|
||||||
"footer": null,
|
"footer": null,
|
||||||
"hosted_invoice_url": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/invst_NORMALIZED0000000000000001CU7gS",
|
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/invst_NORMALIZED0000000000000001avHhX",
|
||||||
"id": "in_NORMALIZED00000000000001",
|
"id": "in_NORMALIZED00000000000001",
|
||||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/invst_NORMALIZED0000000000000001CU7gS/pdf",
|
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/invst_NORMALIZED0000000000000001avHhX/pdf",
|
||||||
|
"last_finalization_error": null,
|
||||||
"lines": {
|
"lines": {
|
||||||
"data": [
|
"data": [
|
||||||
{
|
{
|
||||||
@@ -61,13 +67,13 @@
|
|||||||
"billing_scheme": "per_unit",
|
"billing_scheme": "per_unit",
|
||||||
"created": 1000000000,
|
"created": 1000000000,
|
||||||
"currency": "usd",
|
"currency": "usd",
|
||||||
"id": "price_1HFiX7D2X8vgpBNGZKqyye0n",
|
"id": "price_1J3ngLD2X8vgpBNGNhl10Ejf",
|
||||||
"livemode": false,
|
"livemode": false,
|
||||||
"lookup_key": null,
|
"lookup_key": null,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"nickname": null,
|
"nickname": null,
|
||||||
"object": "price",
|
"object": "price",
|
||||||
"product": "prod_HpNH3ZK9Bpc89P",
|
"product": "prod_JhC49N48jYmZQ8",
|
||||||
"recurring": null,
|
"recurring": null,
|
||||||
"tiers_mode": null,
|
"tiers_mode": null,
|
||||||
"transform_quantity": null,
|
"transform_quantity": null,
|
||||||
@@ -81,7 +87,7 @@
|
|||||||
"tax_amounts": [],
|
"tax_amounts": [],
|
||||||
"tax_rates": [],
|
"tax_rates": [],
|
||||||
"type": "invoiceitem",
|
"type": "invoiceitem",
|
||||||
"unique_id": "il_1HFiX7D2X8vgpBNGYzYwN35m"
|
"unique_id": "il_1J3ngLD2X8vgpBNGyyqmhLYe"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"has_more": false,
|
"has_more": false,
|
||||||
@@ -94,8 +100,13 @@
|
|||||||
"next_payment_attempt": null,
|
"next_payment_attempt": null,
|
||||||
"number": "NORMALI-0001",
|
"number": "NORMALI-0001",
|
||||||
"object": "invoice",
|
"object": "invoice",
|
||||||
|
"on_behalf_of": null,
|
||||||
"paid": false,
|
"paid": false,
|
||||||
"payment_intent": "pi_1HFiX8D2X8vgpBNGGjAHPbBr",
|
"payment_intent": "pi_1J3ngND2X8vgpBNGOtTRK3Kn",
|
||||||
|
"payment_settings": {
|
||||||
|
"payment_method_options": null,
|
||||||
|
"payment_method_types": null
|
||||||
|
},
|
||||||
"period_end": 1000000000,
|
"period_end": 1000000000,
|
||||||
"period_start": 1000000000,
|
"period_start": 1000000000,
|
||||||
"post_payment_credit_notes_amount": 0,
|
"post_payment_credit_notes_amount": 0,
|
||||||
@@ -118,5 +129,5 @@
|
|||||||
"total_discount_amounts": [],
|
"total_discount_amounts": [],
|
||||||
"total_tax_amounts": [],
|
"total_tax_amounts": [],
|
||||||
"transfer_data": null,
|
"transfer_data": null,
|
||||||
"webhooks_delivered_at": 1000000000
|
"webhooks_delivered_at": null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,133 @@
|
|||||||
|
{
|
||||||
|
"account_country": "US",
|
||||||
|
"account_name": "NORMALIZED-1",
|
||||||
|
"account_tax_ids": null,
|
||||||
|
"amount_due": 6400,
|
||||||
|
"amount_paid": 0,
|
||||||
|
"amount_remaining": 6400,
|
||||||
|
"application_fee": null,
|
||||||
|
"attempt_count": 0,
|
||||||
|
"attempted": false,
|
||||||
|
"auto_advance": true,
|
||||||
|
"automatic_tax": {
|
||||||
|
"enabled": false,
|
||||||
|
"status": null
|
||||||
|
},
|
||||||
|
"billing": "send_invoice",
|
||||||
|
"billing_reason": "manual",
|
||||||
|
"charge": null,
|
||||||
|
"collection_method": "send_invoice",
|
||||||
|
"created": 1000000000,
|
||||||
|
"currency": "usd",
|
||||||
|
"custom_fields": null,
|
||||||
|
"customer": "cus_NORMALIZED0002",
|
||||||
|
"customer_address": null,
|
||||||
|
"customer_email": "king@lear.org",
|
||||||
|
"customer_name": null,
|
||||||
|
"customer_phone": null,
|
||||||
|
"customer_shipping": null,
|
||||||
|
"customer_tax_exempt": "none",
|
||||||
|
"customer_tax_ids": [],
|
||||||
|
"date": 1000000000,
|
||||||
|
"default_payment_method": null,
|
||||||
|
"default_source": null,
|
||||||
|
"default_tax_rates": [],
|
||||||
|
"description": null,
|
||||||
|
"discount": null,
|
||||||
|
"discounts": [],
|
||||||
|
"due_date": 1000000000,
|
||||||
|
"ending_balance": 0,
|
||||||
|
"finalized_at": 1000000000,
|
||||||
|
"footer": null,
|
||||||
|
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/invst_NORMALIZED00000000000000027mazH",
|
||||||
|
"id": "in_NORMALIZED00000000000002",
|
||||||
|
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/invst_NORMALIZED00000000000000027mazH/pdf",
|
||||||
|
"last_finalization_error": null,
|
||||||
|
"lines": {
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"amount": 6400,
|
||||||
|
"currency": "usd",
|
||||||
|
"description": "Zulip standard upgrade",
|
||||||
|
"discount_amounts": [],
|
||||||
|
"discountable": false,
|
||||||
|
"discounts": [],
|
||||||
|
"id": "ii_NORMALIZED00000000000002",
|
||||||
|
"invoice_item": "ii_NORMALIZED00000000000002",
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "line_item",
|
||||||
|
"period": {
|
||||||
|
"end": 1000000000,
|
||||||
|
"start": 1000000000
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"price": {
|
||||||
|
"active": false,
|
||||||
|
"billing_scheme": "per_unit",
|
||||||
|
"created": 1000000000,
|
||||||
|
"currency": "usd",
|
||||||
|
"id": "price_1J3ngOD2X8vgpBNG4pn2DcHN",
|
||||||
|
"livemode": false,
|
||||||
|
"lookup_key": null,
|
||||||
|
"metadata": {},
|
||||||
|
"nickname": null,
|
||||||
|
"object": "price",
|
||||||
|
"product": "prod_JhC4jKCcSa3kkS",
|
||||||
|
"recurring": null,
|
||||||
|
"tiers_mode": null,
|
||||||
|
"transform_quantity": null,
|
||||||
|
"type": "one_time",
|
||||||
|
"unit_amount": 800,
|
||||||
|
"unit_amount_decimal": "800"
|
||||||
|
},
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 8,
|
||||||
|
"subscription": null,
|
||||||
|
"tax_amounts": [],
|
||||||
|
"tax_rates": [],
|
||||||
|
"type": "invoiceitem",
|
||||||
|
"unique_id": "il_1J3ngOD2X8vgpBNG5FHfGv4J"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"has_more": false,
|
||||||
|
"object": "list",
|
||||||
|
"total_count": 1,
|
||||||
|
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||||
|
},
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"next_payment_attempt": null,
|
||||||
|
"number": "NORMALI-0002",
|
||||||
|
"object": "invoice",
|
||||||
|
"on_behalf_of": null,
|
||||||
|
"paid": false,
|
||||||
|
"payment_intent": "pi_1J3ngPD2X8vgpBNGYKpQXe19",
|
||||||
|
"payment_settings": {
|
||||||
|
"payment_method_options": null,
|
||||||
|
"payment_method_types": null
|
||||||
|
},
|
||||||
|
"period_end": 1000000000,
|
||||||
|
"period_start": 1000000000,
|
||||||
|
"post_payment_credit_notes_amount": 0,
|
||||||
|
"pre_payment_credit_notes_amount": 0,
|
||||||
|
"receipt_number": null,
|
||||||
|
"starting_balance": 0,
|
||||||
|
"statement_descriptor": "Zulip Standard",
|
||||||
|
"status": "open",
|
||||||
|
"status_transitions": {
|
||||||
|
"finalized_at": 1000000000,
|
||||||
|
"marked_uncollectible_at": null,
|
||||||
|
"paid_at": null,
|
||||||
|
"voided_at": null
|
||||||
|
},
|
||||||
|
"subscription": null,
|
||||||
|
"subtotal": 6400,
|
||||||
|
"tax": null,
|
||||||
|
"tax_percent": null,
|
||||||
|
"total": 6400,
|
||||||
|
"total_discount_amounts": [],
|
||||||
|
"total_tax_amounts": [],
|
||||||
|
"transfer_data": null,
|
||||||
|
"webhooks_delivered_at": 1000000000
|
||||||
|
}
|
||||||
@@ -2,7 +2,8 @@
|
|||||||
"data": [
|
"data": [
|
||||||
{
|
{
|
||||||
"account_country": "US",
|
"account_country": "US",
|
||||||
"account_name": null,
|
"account_name": "NORMALIZED-1",
|
||||||
|
"account_tax_ids": null,
|
||||||
"amount_due": 6400,
|
"amount_due": 6400,
|
||||||
"amount_paid": 0,
|
"amount_paid": 0,
|
||||||
"amount_remaining": 6400,
|
"amount_remaining": 6400,
|
||||||
@@ -10,6 +11,10 @@
|
|||||||
"attempt_count": 0,
|
"attempt_count": 0,
|
||||||
"attempted": false,
|
"attempted": false,
|
||||||
"auto_advance": true,
|
"auto_advance": true,
|
||||||
|
"automatic_tax": {
|
||||||
|
"enabled": false,
|
||||||
|
"status": null
|
||||||
|
},
|
||||||
"billing": "send_invoice",
|
"billing": "send_invoice",
|
||||||
"billing_reason": "manual",
|
"billing_reason": "manual",
|
||||||
"charge": null,
|
"charge": null,
|
||||||
@@ -36,9 +41,10 @@
|
|||||||
"ending_balance": 0,
|
"ending_balance": 0,
|
||||||
"finalized_at": 1000000000,
|
"finalized_at": 1000000000,
|
||||||
"footer": null,
|
"footer": null,
|
||||||
"hosted_invoice_url": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/invst_NORMALIZED0000000000000001CU7gS",
|
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/invst_NORMALIZED0000000000000001avHhX",
|
||||||
"id": "in_NORMALIZED00000000000001",
|
"id": "in_NORMALIZED00000000000001",
|
||||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/invst_NORMALIZED0000000000000001CU7gS/pdf",
|
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/invst_NORMALIZED0000000000000001avHhX/pdf",
|
||||||
|
"last_finalization_error": null,
|
||||||
"lines": {
|
"lines": {
|
||||||
"data": [
|
"data": [
|
||||||
{
|
{
|
||||||
@@ -63,13 +69,13 @@
|
|||||||
"billing_scheme": "per_unit",
|
"billing_scheme": "per_unit",
|
||||||
"created": 1000000000,
|
"created": 1000000000,
|
||||||
"currency": "usd",
|
"currency": "usd",
|
||||||
"id": "price_1HFiX7D2X8vgpBNGZKqyye0n",
|
"id": "price_1J3ngLD2X8vgpBNGNhl10Ejf",
|
||||||
"livemode": false,
|
"livemode": false,
|
||||||
"lookup_key": null,
|
"lookup_key": null,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"nickname": null,
|
"nickname": null,
|
||||||
"object": "price",
|
"object": "price",
|
||||||
"product": "prod_HpNH3ZK9Bpc89P",
|
"product": "prod_JhC49N48jYmZQ8",
|
||||||
"recurring": null,
|
"recurring": null,
|
||||||
"tiers_mode": null,
|
"tiers_mode": null,
|
||||||
"transform_quantity": null,
|
"transform_quantity": null,
|
||||||
@@ -83,7 +89,7 @@
|
|||||||
"tax_amounts": [],
|
"tax_amounts": [],
|
||||||
"tax_rates": [],
|
"tax_rates": [],
|
||||||
"type": "invoiceitem",
|
"type": "invoiceitem",
|
||||||
"unique_id": "il_1HFiX7D2X8vgpBNGYzYwN35m"
|
"unique_id": "il_1J3ngLD2X8vgpBNGyyqmhLYe"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"has_more": false,
|
"has_more": false,
|
||||||
@@ -96,8 +102,13 @@
|
|||||||
"next_payment_attempt": null,
|
"next_payment_attempt": null,
|
||||||
"number": "NORMALI-0001",
|
"number": "NORMALI-0001",
|
||||||
"object": "invoice",
|
"object": "invoice",
|
||||||
|
"on_behalf_of": null,
|
||||||
"paid": false,
|
"paid": false,
|
||||||
"payment_intent": "pi_1HFiX8D2X8vgpBNGGjAHPbBr",
|
"payment_intent": "pi_1J3ngND2X8vgpBNGOtTRK3Kn",
|
||||||
|
"payment_settings": {
|
||||||
|
"payment_method_options": null,
|
||||||
|
"payment_method_types": null
|
||||||
|
},
|
||||||
"period_end": 1000000000,
|
"period_end": 1000000000,
|
||||||
"period_start": 1000000000,
|
"period_start": 1000000000,
|
||||||
"post_payment_credit_notes_amount": 0,
|
"post_payment_credit_notes_amount": 0,
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
"data": [
|
"data": [
|
||||||
{
|
{
|
||||||
"account_country": "US",
|
"account_country": "US",
|
||||||
"account_name": null,
|
"account_name": "NORMALIZED-1",
|
||||||
|
"account_tax_ids": null,
|
||||||
"amount_due": 6400,
|
"amount_due": 6400,
|
||||||
"amount_paid": 0,
|
"amount_paid": 0,
|
||||||
"amount_remaining": 6400,
|
"amount_remaining": 6400,
|
||||||
@@ -10,6 +11,10 @@
|
|||||||
"attempt_count": 0,
|
"attempt_count": 0,
|
||||||
"attempted": false,
|
"attempted": false,
|
||||||
"auto_advance": false,
|
"auto_advance": false,
|
||||||
|
"automatic_tax": {
|
||||||
|
"enabled": false,
|
||||||
|
"status": null
|
||||||
|
},
|
||||||
"billing": "send_invoice",
|
"billing": "send_invoice",
|
||||||
"billing_reason": "manual",
|
"billing_reason": "manual",
|
||||||
"charge": null,
|
"charge": null,
|
||||||
@@ -36,9 +41,10 @@
|
|||||||
"ending_balance": 0,
|
"ending_balance": 0,
|
||||||
"finalized_at": 1000000000,
|
"finalized_at": 1000000000,
|
||||||
"footer": null,
|
"footer": null,
|
||||||
"hosted_invoice_url": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/invst_NORMALIZED0000000000000001CU7gS",
|
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/invst_NORMALIZED0000000000000001avHhX",
|
||||||
"id": "in_NORMALIZED00000000000001",
|
"id": "in_NORMALIZED00000000000001",
|
||||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/invst_NORMALIZED0000000000000001CU7gS/pdf",
|
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/invst_NORMALIZED0000000000000001avHhX/pdf",
|
||||||
|
"last_finalization_error": null,
|
||||||
"lines": {
|
"lines": {
|
||||||
"data": [
|
"data": [
|
||||||
{
|
{
|
||||||
@@ -63,13 +69,13 @@
|
|||||||
"billing_scheme": "per_unit",
|
"billing_scheme": "per_unit",
|
||||||
"created": 1000000000,
|
"created": 1000000000,
|
||||||
"currency": "usd",
|
"currency": "usd",
|
||||||
"id": "price_1HFiX7D2X8vgpBNGZKqyye0n",
|
"id": "price_1J3ngLD2X8vgpBNGNhl10Ejf",
|
||||||
"livemode": false,
|
"livemode": false,
|
||||||
"lookup_key": null,
|
"lookup_key": null,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"nickname": null,
|
"nickname": null,
|
||||||
"object": "price",
|
"object": "price",
|
||||||
"product": "prod_HpNH3ZK9Bpc89P",
|
"product": "prod_JhC49N48jYmZQ8",
|
||||||
"recurring": null,
|
"recurring": null,
|
||||||
"tiers_mode": null,
|
"tiers_mode": null,
|
||||||
"transform_quantity": null,
|
"transform_quantity": null,
|
||||||
@@ -83,7 +89,7 @@
|
|||||||
"tax_amounts": [],
|
"tax_amounts": [],
|
||||||
"tax_rates": [],
|
"tax_rates": [],
|
||||||
"type": "invoiceitem",
|
"type": "invoiceitem",
|
||||||
"unique_id": "il_1HFiX7D2X8vgpBNGYzYwN35m"
|
"unique_id": "il_1J3ngLD2X8vgpBNGyyqmhLYe"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"has_more": false,
|
"has_more": false,
|
||||||
@@ -96,8 +102,13 @@
|
|||||||
"next_payment_attempt": null,
|
"next_payment_attempt": null,
|
||||||
"number": "NORMALI-0001",
|
"number": "NORMALI-0001",
|
||||||
"object": "invoice",
|
"object": "invoice",
|
||||||
|
"on_behalf_of": null,
|
||||||
"paid": false,
|
"paid": false,
|
||||||
"payment_intent": "pi_1HFiX8D2X8vgpBNGGjAHPbBr",
|
"payment_intent": "pi_1J3ngND2X8vgpBNGOtTRK3Kn",
|
||||||
|
"payment_settings": {
|
||||||
|
"payment_method_options": null,
|
||||||
|
"payment_method_types": null
|
||||||
|
},
|
||||||
"period_end": 1000000000,
|
"period_end": 1000000000,
|
||||||
"period_start": 1000000000,
|
"period_start": 1000000000,
|
||||||
"post_payment_credit_notes_amount": 0,
|
"post_payment_credit_notes_amount": 0,
|
||||||
|
|||||||
@@ -0,0 +1,140 @@
|
|||||||
|
{
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"account_country": "US",
|
||||||
|
"account_name": "NORMALIZED-1",
|
||||||
|
"account_tax_ids": null,
|
||||||
|
"amount_due": 6400,
|
||||||
|
"amount_paid": 0,
|
||||||
|
"amount_remaining": 6400,
|
||||||
|
"application_fee": null,
|
||||||
|
"attempt_count": 0,
|
||||||
|
"attempted": false,
|
||||||
|
"auto_advance": true,
|
||||||
|
"automatic_tax": {
|
||||||
|
"enabled": false,
|
||||||
|
"status": null
|
||||||
|
},
|
||||||
|
"billing": "send_invoice",
|
||||||
|
"billing_reason": "manual",
|
||||||
|
"charge": null,
|
||||||
|
"collection_method": "send_invoice",
|
||||||
|
"created": 1000000000,
|
||||||
|
"currency": "usd",
|
||||||
|
"custom_fields": null,
|
||||||
|
"customer": "cus_NORMALIZED0002",
|
||||||
|
"customer_address": null,
|
||||||
|
"customer_email": "king@lear.org",
|
||||||
|
"customer_name": null,
|
||||||
|
"customer_phone": null,
|
||||||
|
"customer_shipping": null,
|
||||||
|
"customer_tax_exempt": "none",
|
||||||
|
"customer_tax_ids": [],
|
||||||
|
"date": 1000000000,
|
||||||
|
"default_payment_method": null,
|
||||||
|
"default_source": null,
|
||||||
|
"default_tax_rates": [],
|
||||||
|
"description": null,
|
||||||
|
"discount": null,
|
||||||
|
"discounts": [],
|
||||||
|
"due_date": 1000000000,
|
||||||
|
"ending_balance": 0,
|
||||||
|
"finalized_at": 1000000000,
|
||||||
|
"footer": null,
|
||||||
|
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/invst_NORMALIZED00000000000000027mazH",
|
||||||
|
"id": "in_NORMALIZED00000000000002",
|
||||||
|
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/invst_NORMALIZED00000000000000027mazH/pdf",
|
||||||
|
"last_finalization_error": null,
|
||||||
|
"lines": {
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"amount": 6400,
|
||||||
|
"currency": "usd",
|
||||||
|
"description": "Zulip standard upgrade",
|
||||||
|
"discount_amounts": [],
|
||||||
|
"discountable": false,
|
||||||
|
"discounts": [],
|
||||||
|
"id": "ii_NORMALIZED00000000000002",
|
||||||
|
"invoice_item": "ii_NORMALIZED00000000000002",
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "line_item",
|
||||||
|
"period": {
|
||||||
|
"end": 1000000000,
|
||||||
|
"start": 1000000000
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"price": {
|
||||||
|
"active": false,
|
||||||
|
"billing_scheme": "per_unit",
|
||||||
|
"created": 1000000000,
|
||||||
|
"currency": "usd",
|
||||||
|
"id": "price_1J3ngOD2X8vgpBNG4pn2DcHN",
|
||||||
|
"livemode": false,
|
||||||
|
"lookup_key": null,
|
||||||
|
"metadata": {},
|
||||||
|
"nickname": null,
|
||||||
|
"object": "price",
|
||||||
|
"product": "prod_JhC4jKCcSa3kkS",
|
||||||
|
"recurring": null,
|
||||||
|
"tiers_mode": null,
|
||||||
|
"transform_quantity": null,
|
||||||
|
"type": "one_time",
|
||||||
|
"unit_amount": 800,
|
||||||
|
"unit_amount_decimal": "800"
|
||||||
|
},
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 8,
|
||||||
|
"subscription": null,
|
||||||
|
"tax_amounts": [],
|
||||||
|
"tax_rates": [],
|
||||||
|
"type": "invoiceitem",
|
||||||
|
"unique_id": "il_1J3ngOD2X8vgpBNG5FHfGv4J"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"has_more": false,
|
||||||
|
"object": "list",
|
||||||
|
"total_count": 1,
|
||||||
|
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||||
|
},
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"next_payment_attempt": null,
|
||||||
|
"number": "NORMALI-0002",
|
||||||
|
"object": "invoice",
|
||||||
|
"on_behalf_of": null,
|
||||||
|
"paid": false,
|
||||||
|
"payment_intent": "pi_1J3ngPD2X8vgpBNGYKpQXe19",
|
||||||
|
"payment_settings": {
|
||||||
|
"payment_method_options": null,
|
||||||
|
"payment_method_types": null
|
||||||
|
},
|
||||||
|
"period_end": 1000000000,
|
||||||
|
"period_start": 1000000000,
|
||||||
|
"post_payment_credit_notes_amount": 0,
|
||||||
|
"pre_payment_credit_notes_amount": 0,
|
||||||
|
"receipt_number": null,
|
||||||
|
"starting_balance": 0,
|
||||||
|
"statement_descriptor": "Zulip Standard",
|
||||||
|
"status": "open",
|
||||||
|
"status_transitions": {
|
||||||
|
"finalized_at": 1000000000,
|
||||||
|
"marked_uncollectible_at": null,
|
||||||
|
"paid_at": null,
|
||||||
|
"voided_at": null
|
||||||
|
},
|
||||||
|
"subscription": null,
|
||||||
|
"subtotal": 6400,
|
||||||
|
"tax": null,
|
||||||
|
"tax_percent": null,
|
||||||
|
"total": 6400,
|
||||||
|
"total_discount_amounts": [],
|
||||||
|
"total_tax_amounts": [],
|
||||||
|
"transfer_data": null,
|
||||||
|
"webhooks_delivered_at": 1000000000
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"has_more": false,
|
||||||
|
"object": "list",
|
||||||
|
"url": "/v1/invoices"
|
||||||
|
}
|
||||||
@@ -0,0 +1,140 @@
|
|||||||
|
{
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"account_country": "US",
|
||||||
|
"account_name": "NORMALIZED-1",
|
||||||
|
"account_tax_ids": null,
|
||||||
|
"amount_due": 6400,
|
||||||
|
"amount_paid": 0,
|
||||||
|
"amount_remaining": 6400,
|
||||||
|
"application_fee": null,
|
||||||
|
"attempt_count": 0,
|
||||||
|
"attempted": false,
|
||||||
|
"auto_advance": false,
|
||||||
|
"automatic_tax": {
|
||||||
|
"enabled": false,
|
||||||
|
"status": null
|
||||||
|
},
|
||||||
|
"billing": "send_invoice",
|
||||||
|
"billing_reason": "manual",
|
||||||
|
"charge": null,
|
||||||
|
"collection_method": "send_invoice",
|
||||||
|
"created": 1000000000,
|
||||||
|
"currency": "usd",
|
||||||
|
"custom_fields": null,
|
||||||
|
"customer": "cus_NORMALIZED0002",
|
||||||
|
"customer_address": null,
|
||||||
|
"customer_email": "king@lear.org",
|
||||||
|
"customer_name": null,
|
||||||
|
"customer_phone": null,
|
||||||
|
"customer_shipping": null,
|
||||||
|
"customer_tax_exempt": "none",
|
||||||
|
"customer_tax_ids": [],
|
||||||
|
"date": 1000000000,
|
||||||
|
"default_payment_method": null,
|
||||||
|
"default_source": null,
|
||||||
|
"default_tax_rates": [],
|
||||||
|
"description": null,
|
||||||
|
"discount": null,
|
||||||
|
"discounts": [],
|
||||||
|
"due_date": 1000000000,
|
||||||
|
"ending_balance": 0,
|
||||||
|
"finalized_at": 1000000000,
|
||||||
|
"footer": null,
|
||||||
|
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/invst_NORMALIZED00000000000000027mazH",
|
||||||
|
"id": "in_NORMALIZED00000000000002",
|
||||||
|
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/invst_NORMALIZED00000000000000027mazH/pdf",
|
||||||
|
"last_finalization_error": null,
|
||||||
|
"lines": {
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"amount": 6400,
|
||||||
|
"currency": "usd",
|
||||||
|
"description": "Zulip standard upgrade",
|
||||||
|
"discount_amounts": [],
|
||||||
|
"discountable": false,
|
||||||
|
"discounts": [],
|
||||||
|
"id": "ii_NORMALIZED00000000000002",
|
||||||
|
"invoice_item": "ii_NORMALIZED00000000000002",
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "line_item",
|
||||||
|
"period": {
|
||||||
|
"end": 1000000000,
|
||||||
|
"start": 1000000000
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"price": {
|
||||||
|
"active": false,
|
||||||
|
"billing_scheme": "per_unit",
|
||||||
|
"created": 1000000000,
|
||||||
|
"currency": "usd",
|
||||||
|
"id": "price_1J3ngOD2X8vgpBNG4pn2DcHN",
|
||||||
|
"livemode": false,
|
||||||
|
"lookup_key": null,
|
||||||
|
"metadata": {},
|
||||||
|
"nickname": null,
|
||||||
|
"object": "price",
|
||||||
|
"product": "prod_JhC4jKCcSa3kkS",
|
||||||
|
"recurring": null,
|
||||||
|
"tiers_mode": null,
|
||||||
|
"transform_quantity": null,
|
||||||
|
"type": "one_time",
|
||||||
|
"unit_amount": 800,
|
||||||
|
"unit_amount_decimal": "800"
|
||||||
|
},
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 8,
|
||||||
|
"subscription": null,
|
||||||
|
"tax_amounts": [],
|
||||||
|
"tax_rates": [],
|
||||||
|
"type": "invoiceitem",
|
||||||
|
"unique_id": "il_1J3ngOD2X8vgpBNG5FHfGv4J"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"has_more": false,
|
||||||
|
"object": "list",
|
||||||
|
"total_count": 1,
|
||||||
|
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||||
|
},
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"next_payment_attempt": null,
|
||||||
|
"number": "NORMALI-0002",
|
||||||
|
"object": "invoice",
|
||||||
|
"on_behalf_of": null,
|
||||||
|
"paid": false,
|
||||||
|
"payment_intent": "pi_1J3ngPD2X8vgpBNGYKpQXe19",
|
||||||
|
"payment_settings": {
|
||||||
|
"payment_method_options": null,
|
||||||
|
"payment_method_types": null
|
||||||
|
},
|
||||||
|
"period_end": 1000000000,
|
||||||
|
"period_start": 1000000000,
|
||||||
|
"post_payment_credit_notes_amount": 0,
|
||||||
|
"pre_payment_credit_notes_amount": 0,
|
||||||
|
"receipt_number": null,
|
||||||
|
"starting_balance": 0,
|
||||||
|
"statement_descriptor": "Zulip Standard",
|
||||||
|
"status": "void",
|
||||||
|
"status_transitions": {
|
||||||
|
"finalized_at": 1000000000,
|
||||||
|
"marked_uncollectible_at": null,
|
||||||
|
"paid_at": null,
|
||||||
|
"voided_at": 1000000000
|
||||||
|
},
|
||||||
|
"subscription": null,
|
||||||
|
"subtotal": 6400,
|
||||||
|
"tax": null,
|
||||||
|
"tax_percent": null,
|
||||||
|
"total": 6400,
|
||||||
|
"total_discount_amounts": [],
|
||||||
|
"total_tax_amounts": [],
|
||||||
|
"transfer_data": null,
|
||||||
|
"webhooks_delivered_at": 1000000000
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"has_more": false,
|
||||||
|
"object": "list",
|
||||||
|
"url": "/v1/invoices"
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"account_country": "US",
|
"account_country": "US",
|
||||||
"account_name": null,
|
"account_name": "NORMALIZED-1",
|
||||||
|
"account_tax_ids": null,
|
||||||
"amount_due": 6400,
|
"amount_due": 6400,
|
||||||
"amount_paid": 0,
|
"amount_paid": 0,
|
||||||
"amount_remaining": 6400,
|
"amount_remaining": 6400,
|
||||||
@@ -8,6 +9,10 @@
|
|||||||
"attempt_count": 0,
|
"attempt_count": 0,
|
||||||
"attempted": false,
|
"attempted": false,
|
||||||
"auto_advance": false,
|
"auto_advance": false,
|
||||||
|
"automatic_tax": {
|
||||||
|
"enabled": false,
|
||||||
|
"status": null
|
||||||
|
},
|
||||||
"billing": "send_invoice",
|
"billing": "send_invoice",
|
||||||
"billing_reason": "manual",
|
"billing_reason": "manual",
|
||||||
"charge": null,
|
"charge": null,
|
||||||
@@ -34,9 +39,10 @@
|
|||||||
"ending_balance": 0,
|
"ending_balance": 0,
|
||||||
"finalized_at": 1000000000,
|
"finalized_at": 1000000000,
|
||||||
"footer": null,
|
"footer": null,
|
||||||
"hosted_invoice_url": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/invst_NORMALIZED0000000000000001CU7gS",
|
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/invst_NORMALIZED0000000000000001avHhX",
|
||||||
"id": "in_NORMALIZED00000000000001",
|
"id": "in_NORMALIZED00000000000001",
|
||||||
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/invst_NORMALIZED0000000000000001CU7gS/pdf",
|
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/invst_NORMALIZED0000000000000001avHhX/pdf",
|
||||||
|
"last_finalization_error": null,
|
||||||
"lines": {
|
"lines": {
|
||||||
"data": [
|
"data": [
|
||||||
{
|
{
|
||||||
@@ -61,13 +67,13 @@
|
|||||||
"billing_scheme": "per_unit",
|
"billing_scheme": "per_unit",
|
||||||
"created": 1000000000,
|
"created": 1000000000,
|
||||||
"currency": "usd",
|
"currency": "usd",
|
||||||
"id": "price_1HFiX7D2X8vgpBNGZKqyye0n",
|
"id": "price_1J3ngLD2X8vgpBNGNhl10Ejf",
|
||||||
"livemode": false,
|
"livemode": false,
|
||||||
"lookup_key": null,
|
"lookup_key": null,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"nickname": null,
|
"nickname": null,
|
||||||
"object": "price",
|
"object": "price",
|
||||||
"product": "prod_HpNH3ZK9Bpc89P",
|
"product": "prod_JhC49N48jYmZQ8",
|
||||||
"recurring": null,
|
"recurring": null,
|
||||||
"tiers_mode": null,
|
"tiers_mode": null,
|
||||||
"transform_quantity": null,
|
"transform_quantity": null,
|
||||||
@@ -81,7 +87,7 @@
|
|||||||
"tax_amounts": [],
|
"tax_amounts": [],
|
||||||
"tax_rates": [],
|
"tax_rates": [],
|
||||||
"type": "invoiceitem",
|
"type": "invoiceitem",
|
||||||
"unique_id": "il_1HFiX7D2X8vgpBNGYzYwN35m"
|
"unique_id": "il_1J3ngLD2X8vgpBNGyyqmhLYe"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"has_more": false,
|
"has_more": false,
|
||||||
@@ -94,8 +100,13 @@
|
|||||||
"next_payment_attempt": null,
|
"next_payment_attempt": null,
|
||||||
"number": "NORMALI-0001",
|
"number": "NORMALI-0001",
|
||||||
"object": "invoice",
|
"object": "invoice",
|
||||||
|
"on_behalf_of": null,
|
||||||
"paid": false,
|
"paid": false,
|
||||||
"payment_intent": "pi_1HFiX8D2X8vgpBNGGjAHPbBr",
|
"payment_intent": "pi_1J3ngND2X8vgpBNGOtTRK3Kn",
|
||||||
|
"payment_settings": {
|
||||||
|
"payment_method_options": null,
|
||||||
|
"payment_method_types": null
|
||||||
|
},
|
||||||
"period_end": 1000000000,
|
"period_end": 1000000000,
|
||||||
"period_start": 1000000000,
|
"period_start": 1000000000,
|
||||||
"post_payment_credit_notes_amount": 0,
|
"post_payment_credit_notes_amount": 0,
|
||||||
|
|||||||
@@ -0,0 +1,133 @@
|
|||||||
|
{
|
||||||
|
"account_country": "US",
|
||||||
|
"account_name": "NORMALIZED-1",
|
||||||
|
"account_tax_ids": null,
|
||||||
|
"amount_due": 6400,
|
||||||
|
"amount_paid": 0,
|
||||||
|
"amount_remaining": 6400,
|
||||||
|
"application_fee": null,
|
||||||
|
"attempt_count": 0,
|
||||||
|
"attempted": false,
|
||||||
|
"auto_advance": false,
|
||||||
|
"automatic_tax": {
|
||||||
|
"enabled": false,
|
||||||
|
"status": null
|
||||||
|
},
|
||||||
|
"billing": "send_invoice",
|
||||||
|
"billing_reason": "manual",
|
||||||
|
"charge": null,
|
||||||
|
"collection_method": "send_invoice",
|
||||||
|
"created": 1000000000,
|
||||||
|
"currency": "usd",
|
||||||
|
"custom_fields": null,
|
||||||
|
"customer": "cus_NORMALIZED0002",
|
||||||
|
"customer_address": null,
|
||||||
|
"customer_email": "king@lear.org",
|
||||||
|
"customer_name": null,
|
||||||
|
"customer_phone": null,
|
||||||
|
"customer_shipping": null,
|
||||||
|
"customer_tax_exempt": "none",
|
||||||
|
"customer_tax_ids": [],
|
||||||
|
"date": 1000000000,
|
||||||
|
"default_payment_method": null,
|
||||||
|
"default_source": null,
|
||||||
|
"default_tax_rates": [],
|
||||||
|
"description": null,
|
||||||
|
"discount": null,
|
||||||
|
"discounts": [],
|
||||||
|
"due_date": 1000000000,
|
||||||
|
"ending_balance": 0,
|
||||||
|
"finalized_at": 1000000000,
|
||||||
|
"footer": null,
|
||||||
|
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/invst_NORMALIZED00000000000000027mazH",
|
||||||
|
"id": "in_NORMALIZED00000000000002",
|
||||||
|
"invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/invst_NORMALIZED00000000000000027mazH/pdf",
|
||||||
|
"last_finalization_error": null,
|
||||||
|
"lines": {
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"amount": 6400,
|
||||||
|
"currency": "usd",
|
||||||
|
"description": "Zulip standard upgrade",
|
||||||
|
"discount_amounts": [],
|
||||||
|
"discountable": false,
|
||||||
|
"discounts": [],
|
||||||
|
"id": "ii_NORMALIZED00000000000002",
|
||||||
|
"invoice_item": "ii_NORMALIZED00000000000002",
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "line_item",
|
||||||
|
"period": {
|
||||||
|
"end": 1000000000,
|
||||||
|
"start": 1000000000
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"price": {
|
||||||
|
"active": false,
|
||||||
|
"billing_scheme": "per_unit",
|
||||||
|
"created": 1000000000,
|
||||||
|
"currency": "usd",
|
||||||
|
"id": "price_1J3ngOD2X8vgpBNG4pn2DcHN",
|
||||||
|
"livemode": false,
|
||||||
|
"lookup_key": null,
|
||||||
|
"metadata": {},
|
||||||
|
"nickname": null,
|
||||||
|
"object": "price",
|
||||||
|
"product": "prod_JhC4jKCcSa3kkS",
|
||||||
|
"recurring": null,
|
||||||
|
"tiers_mode": null,
|
||||||
|
"transform_quantity": null,
|
||||||
|
"type": "one_time",
|
||||||
|
"unit_amount": 800,
|
||||||
|
"unit_amount_decimal": "800"
|
||||||
|
},
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 8,
|
||||||
|
"subscription": null,
|
||||||
|
"tax_amounts": [],
|
||||||
|
"tax_rates": [],
|
||||||
|
"type": "invoiceitem",
|
||||||
|
"unique_id": "il_1J3ngOD2X8vgpBNG5FHfGv4J"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"has_more": false,
|
||||||
|
"object": "list",
|
||||||
|
"total_count": 1,
|
||||||
|
"url": "/v1/invoices/in_NORMALIZED00000000000002/lines"
|
||||||
|
},
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"next_payment_attempt": null,
|
||||||
|
"number": "NORMALI-0002",
|
||||||
|
"object": "invoice",
|
||||||
|
"on_behalf_of": null,
|
||||||
|
"paid": false,
|
||||||
|
"payment_intent": "pi_1J3ngPD2X8vgpBNGYKpQXe19",
|
||||||
|
"payment_settings": {
|
||||||
|
"payment_method_options": null,
|
||||||
|
"payment_method_types": null
|
||||||
|
},
|
||||||
|
"period_end": 1000000000,
|
||||||
|
"period_start": 1000000000,
|
||||||
|
"post_payment_credit_notes_amount": 0,
|
||||||
|
"pre_payment_credit_notes_amount": 0,
|
||||||
|
"receipt_number": null,
|
||||||
|
"starting_balance": 0,
|
||||||
|
"statement_descriptor": "Zulip Standard",
|
||||||
|
"status": "void",
|
||||||
|
"status_transitions": {
|
||||||
|
"finalized_at": 1000000000,
|
||||||
|
"marked_uncollectible_at": null,
|
||||||
|
"paid_at": null,
|
||||||
|
"voided_at": 1000000000
|
||||||
|
},
|
||||||
|
"subscription": null,
|
||||||
|
"subtotal": 6400,
|
||||||
|
"tax": null,
|
||||||
|
"tax_percent": null,
|
||||||
|
"total": 6400,
|
||||||
|
"total_discount_amounts": [],
|
||||||
|
"total_tax_amounts": [],
|
||||||
|
"transfer_data": null,
|
||||||
|
"webhooks_delivered_at": 1000000000
|
||||||
|
}
|
||||||
@@ -21,13 +21,13 @@
|
|||||||
"billing_scheme": "per_unit",
|
"billing_scheme": "per_unit",
|
||||||
"created": 1000000000,
|
"created": 1000000000,
|
||||||
"currency": "usd",
|
"currency": "usd",
|
||||||
"id": "price_1HFiX7D2X8vgpBNGZKqyye0n",
|
"id": "price_1J3ngLD2X8vgpBNGNhl10Ejf",
|
||||||
"livemode": false,
|
"livemode": false,
|
||||||
"lookup_key": null,
|
"lookup_key": null,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"nickname": null,
|
"nickname": null,
|
||||||
"object": "price",
|
"object": "price",
|
||||||
"product": "prod_HpNH3ZK9Bpc89P",
|
"product": "prod_JhC49N48jYmZQ8",
|
||||||
"recurring": null,
|
"recurring": null,
|
||||||
"tiers_mode": null,
|
"tiers_mode": null,
|
||||||
"transform_quantity": null,
|
"transform_quantity": null,
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"amount": 6400,
|
||||||
|
"currency": "usd",
|
||||||
|
"customer": "cus_NORMALIZED0002",
|
||||||
|
"date": 1000000000,
|
||||||
|
"description": "Zulip standard upgrade",
|
||||||
|
"discountable": false,
|
||||||
|
"discounts": [],
|
||||||
|
"id": "ii_NORMALIZED00000000000002",
|
||||||
|
"invoice": null,
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "invoiceitem",
|
||||||
|
"period": {
|
||||||
|
"end": 1000000000,
|
||||||
|
"start": 1000000000
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"price": {
|
||||||
|
"active": false,
|
||||||
|
"billing_scheme": "per_unit",
|
||||||
|
"created": 1000000000,
|
||||||
|
"currency": "usd",
|
||||||
|
"id": "price_1J3ngOD2X8vgpBNG4pn2DcHN",
|
||||||
|
"livemode": false,
|
||||||
|
"lookup_key": null,
|
||||||
|
"metadata": {},
|
||||||
|
"nickname": null,
|
||||||
|
"object": "price",
|
||||||
|
"product": "prod_JhC4jKCcSa3kkS",
|
||||||
|
"recurring": null,
|
||||||
|
"tiers_mode": null,
|
||||||
|
"transform_quantity": null,
|
||||||
|
"type": "one_time",
|
||||||
|
"unit_amount": 800,
|
||||||
|
"unit_amount_decimal": "800"
|
||||||
|
},
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 8,
|
||||||
|
"subscription": null,
|
||||||
|
"tax_rates": [],
|
||||||
|
"unit_amount": 800,
|
||||||
|
"unit_amount_decimal": "800"
|
||||||
|
}
|
||||||
@@ -1990,6 +1990,7 @@ class StripeTest(StripeTestCase):
|
|||||||
monthly_plan.refresh_from_db()
|
monthly_plan.refresh_from_db()
|
||||||
self.assertEqual(monthly_plan.next_invoice_date, None)
|
self.assertEqual(monthly_plan.next_invoice_date, None)
|
||||||
|
|
||||||
|
assert customer.stripe_customer_id
|
||||||
[invoice0, invoice1, invoice2] = stripe.Invoice.list(customer=customer.stripe_customer_id)
|
[invoice0, invoice1, invoice2] = stripe.Invoice.list(customer=customer.stripe_customer_id)
|
||||||
|
|
||||||
[invoice_item0, invoice_item1] = invoice0.get("lines")
|
[invoice_item0, invoice_item1] = invoice0.get("lines")
|
||||||
@@ -2154,6 +2155,7 @@ class StripeTest(StripeTestCase):
|
|||||||
self.assertEqual(annual_plan.next_invoice_date, add_months(self.next_month, 12))
|
self.assertEqual(annual_plan.next_invoice_date, add_months(self.next_month, 12))
|
||||||
self.assertEqual(annual_plan.invoicing_status, CustomerPlan.DONE)
|
self.assertEqual(annual_plan.invoicing_status, CustomerPlan.DONE)
|
||||||
|
|
||||||
|
assert customer.stripe_customer_id
|
||||||
[invoice0, invoice1] = stripe.Invoice.list(customer=customer.stripe_customer_id)
|
[invoice0, invoice1] = stripe.Invoice.list(customer=customer.stripe_customer_id)
|
||||||
|
|
||||||
[invoice_item] = invoice0.get("lines")
|
[invoice_item] = invoice0.get("lines")
|
||||||
@@ -2632,12 +2634,17 @@ class StripeTest(StripeTestCase):
|
|||||||
@mock_stripe()
|
@mock_stripe()
|
||||||
def test_void_all_open_invoices(self, *mock: Mock) -> None:
|
def test_void_all_open_invoices(self, *mock: Mock) -> None:
|
||||||
iago = self.example_user("iago")
|
iago = self.example_user("iago")
|
||||||
self.assertEqual(void_all_open_invoices(iago.realm), 0)
|
king = self.lear_user("king")
|
||||||
customer = update_or_create_stripe_customer(iago)
|
|
||||||
|
|
||||||
|
self.assertEqual(void_all_open_invoices(iago.realm), 0)
|
||||||
|
|
||||||
|
zulip_customer = update_or_create_stripe_customer(iago)
|
||||||
|
lear_customer = update_or_create_stripe_customer(king)
|
||||||
|
|
||||||
|
assert zulip_customer.stripe_customer_id
|
||||||
stripe.InvoiceItem.create(
|
stripe.InvoiceItem.create(
|
||||||
currency="usd",
|
currency="usd",
|
||||||
customer=customer.stripe_customer_id,
|
customer=zulip_customer.stripe_customer_id,
|
||||||
description="Zulip standard upgrade",
|
description="Zulip standard upgrade",
|
||||||
discountable=False,
|
discountable=False,
|
||||||
unit_amount=800,
|
unit_amount=800,
|
||||||
@@ -2646,14 +2653,45 @@ class StripeTest(StripeTestCase):
|
|||||||
stripe_invoice = stripe.Invoice.create(
|
stripe_invoice = stripe.Invoice.create(
|
||||||
auto_advance=True,
|
auto_advance=True,
|
||||||
billing="send_invoice",
|
billing="send_invoice",
|
||||||
customer=customer.stripe_customer_id,
|
customer=zulip_customer.stripe_customer_id,
|
||||||
|
days_until_due=30,
|
||||||
|
statement_descriptor="Zulip Standard",
|
||||||
|
)
|
||||||
|
stripe.Invoice.finalize_invoice(stripe_invoice)
|
||||||
|
|
||||||
|
assert lear_customer.stripe_customer_id
|
||||||
|
stripe.InvoiceItem.create(
|
||||||
|
currency="usd",
|
||||||
|
customer=lear_customer.stripe_customer_id,
|
||||||
|
description="Zulip standard upgrade",
|
||||||
|
discountable=False,
|
||||||
|
unit_amount=800,
|
||||||
|
quantity=8,
|
||||||
|
)
|
||||||
|
stripe_invoice = stripe.Invoice.create(
|
||||||
|
auto_advance=True,
|
||||||
|
billing="send_invoice",
|
||||||
|
customer=lear_customer.stripe_customer_id,
|
||||||
days_until_due=30,
|
days_until_due=30,
|
||||||
statement_descriptor="Zulip Standard",
|
statement_descriptor="Zulip Standard",
|
||||||
)
|
)
|
||||||
stripe.Invoice.finalize_invoice(stripe_invoice)
|
stripe.Invoice.finalize_invoice(stripe_invoice)
|
||||||
|
|
||||||
self.assertEqual(void_all_open_invoices(iago.realm), 1)
|
self.assertEqual(void_all_open_invoices(iago.realm), 1)
|
||||||
invoices = stripe.Invoice.list(customer=customer.stripe_customer_id)
|
invoices = stripe.Invoice.list(customer=zulip_customer.stripe_customer_id)
|
||||||
|
self.assert_length(invoices, 1)
|
||||||
|
for invoice in invoices:
|
||||||
|
self.assertEqual(invoice.status, "void")
|
||||||
|
|
||||||
|
lear_stripe_customer_id = lear_customer.stripe_customer_id
|
||||||
|
lear_customer.stripe_customer_id = None
|
||||||
|
lear_customer.save(update_fields=["stripe_customer_id"])
|
||||||
|
self.assertEqual(void_all_open_invoices(king.realm), 0)
|
||||||
|
|
||||||
|
lear_customer.stripe_customer_id = lear_stripe_customer_id
|
||||||
|
lear_customer.save(update_fields=["stripe_customer_id"])
|
||||||
|
self.assertEqual(void_all_open_invoices(king.realm), 1)
|
||||||
|
invoices = stripe.Invoice.list(customer=lear_customer.stripe_customer_id)
|
||||||
self.assert_length(invoices, 1)
|
self.assert_length(invoices, 1)
|
||||||
for invoice in invoices:
|
for invoice in invoices:
|
||||||
self.assertEqual(invoice.status, "void")
|
self.assertEqual(invoice.status, "void")
|
||||||
@@ -3207,6 +3245,17 @@ class InvoiceTest(StripeTestCase):
|
|||||||
with self.assertRaises(NotImplementedError):
|
with self.assertRaises(NotImplementedError):
|
||||||
invoice_plan(CustomerPlan.objects.first(), self.now)
|
invoice_plan(CustomerPlan.objects.first(), self.now)
|
||||||
|
|
||||||
|
def test_invoice_plan_without_stripe_customer(self) -> None:
|
||||||
|
self.local_upgrade(self.seat_count, True, CustomerPlan.ANNUAL)
|
||||||
|
plan = get_current_plan_by_realm(get_realm("zulip"))
|
||||||
|
assert plan and plan.customer
|
||||||
|
plan.customer.stripe_customer_id = None
|
||||||
|
plan.customer.save(update_fields=["stripe_customer_id"])
|
||||||
|
with self.assertRaisesRegex(
|
||||||
|
BillingError, "Realm zulip has a paid plan without a Stripe customer"
|
||||||
|
):
|
||||||
|
invoice_plan(plan, timezone_now())
|
||||||
|
|
||||||
@mock_stripe()
|
@mock_stripe()
|
||||||
def test_invoice_plan(self, *mocks: Mock) -> None:
|
def test_invoice_plan(self, *mocks: Mock) -> None:
|
||||||
user = self.example_user("hamlet")
|
user = self.example_user("hamlet")
|
||||||
|
|||||||
@@ -317,6 +317,7 @@ def billing_home(request: HttpRequest) -> HttpResponse:
|
|||||||
)
|
)
|
||||||
renewal_cents = renewal_amount(plan, now)
|
renewal_cents = renewal_amount(plan, now)
|
||||||
charge_automatically = plan.charge_automatically
|
charge_automatically = plan.charge_automatically
|
||||||
|
assert customer.stripe_customer_id is not None # for mypy
|
||||||
stripe_customer = stripe_get_customer(customer.stripe_customer_id)
|
stripe_customer = stripe_get_customer(customer.stripe_customer_id)
|
||||||
if charge_automatically:
|
if charge_automatically:
|
||||||
payment_method = payment_method_string(stripe_customer)
|
payment_method = payment_method_string(stripe_customer)
|
||||||
|
|||||||
Reference in New Issue
Block a user