mirror of
https://github.com/zulip/zulip.git
synced 2025-11-09 08:26:11 +00:00
billing: Add functions for automatic invoicing of plans.
This commit is contained in:
@@ -91,6 +91,21 @@ def next_renewal_date(plan: CustomerPlan, event_time: datetime) -> datetime:
|
|||||||
periods += 1
|
periods += 1
|
||||||
return dt
|
return dt
|
||||||
|
|
||||||
|
# TODO take downgrade into account
|
||||||
|
def next_invoice_date(plan: CustomerPlan) -> datetime:
|
||||||
|
months_per_period = {
|
||||||
|
CustomerPlan.ANNUAL: 12,
|
||||||
|
CustomerPlan.MONTHLY: 1,
|
||||||
|
}[plan.billing_schedule]
|
||||||
|
if plan.automanage_licenses:
|
||||||
|
months_per_period = 1
|
||||||
|
periods = 1
|
||||||
|
dt = plan.billing_cycle_anchor
|
||||||
|
while dt <= plan.next_invoice_date:
|
||||||
|
dt = add_months(plan.billing_cycle_anchor, months_per_period * periods)
|
||||||
|
periods += 1
|
||||||
|
return dt
|
||||||
|
|
||||||
def renewal_amount(plan: CustomerPlan) -> Optional[int]: # nocoverage: TODO
|
def renewal_amount(plan: CustomerPlan) -> Optional[int]: # nocoverage: TODO
|
||||||
if plan.fixed_price is not None:
|
if plan.fixed_price is not None:
|
||||||
return plan.fixed_price
|
return plan.fixed_price
|
||||||
@@ -356,6 +371,77 @@ def update_license_ledger_if_needed(realm: Realm, event_time: datetime) -> None:
|
|||||||
return
|
return
|
||||||
update_license_ledger_for_automanaged_plan(realm, plan, event_time)
|
update_license_ledger_for_automanaged_plan(realm, plan, event_time)
|
||||||
|
|
||||||
|
def invoice_plan(plan: CustomerPlan, event_time: datetime) -> None:
|
||||||
|
if plan.invoicing_status == CustomerPlan.STARTED:
|
||||||
|
raise NotImplementedError('Plan with invoicing_status==STARTED needs manual resolution.')
|
||||||
|
add_plan_renewal_to_license_ledger_if_needed(plan, event_time)
|
||||||
|
assert(plan.invoiced_through is not None)
|
||||||
|
licenses_base = plan.invoiced_through.licenses
|
||||||
|
invoice_item_created = False
|
||||||
|
for ledger_entry in LicenseLedger.objects.filter(plan=plan, id__gt=plan.invoiced_through.id,
|
||||||
|
event_time__lte=event_time).order_by('id'):
|
||||||
|
price_args = {} # type: Dict[str, int]
|
||||||
|
if ledger_entry.is_renewal:
|
||||||
|
if plan.fixed_price is not None:
|
||||||
|
price_args = {'amount': plan.fixed_price}
|
||||||
|
else:
|
||||||
|
assert(plan.price_per_license is not None) # needed for mypy
|
||||||
|
price_args = {'unit_amount': plan.price_per_license,
|
||||||
|
'quantity': ledger_entry.licenses}
|
||||||
|
description = "Zulip Standard - renewal"
|
||||||
|
elif ledger_entry.licenses != licenses_base:
|
||||||
|
assert(plan.price_per_license)
|
||||||
|
last_renewal = LicenseLedger.objects.filter(
|
||||||
|
plan=plan, is_renewal=True, event_time__lte=ledger_entry.event_time) \
|
||||||
|
.order_by('-id').first().event_time
|
||||||
|
period_end = next_renewal_date(plan, ledger_entry.event_time)
|
||||||
|
proration_fraction = (period_end - ledger_entry.event_time) / (period_end - last_renewal)
|
||||||
|
price_args = {'unit_amount': int(plan.price_per_license * proration_fraction + .5),
|
||||||
|
'quantity': ledger_entry.licenses - licenses_base}
|
||||||
|
description = "Additional license ({} - {})".format(
|
||||||
|
ledger_entry.event_time.strftime('%b %-d, %Y'), period_end.strftime('%b %-d, %Y'))
|
||||||
|
|
||||||
|
if price_args:
|
||||||
|
plan.invoiced_through = ledger_entry
|
||||||
|
plan.invoicing_status = CustomerPlan.STARTED
|
||||||
|
plan.save(update_fields=['invoicing_status', 'invoiced_through'])
|
||||||
|
stripe.InvoiceItem.create(
|
||||||
|
currency='usd',
|
||||||
|
customer=plan.customer.stripe_customer_id,
|
||||||
|
description=description,
|
||||||
|
discountable=False,
|
||||||
|
period = {'start': datetime_to_timestamp(ledger_entry.event_time),
|
||||||
|
'end': datetime_to_timestamp(next_renewal_date(plan, ledger_entry.event_time))},
|
||||||
|
idempotency_key='ledger_entry:{}'.format(ledger_entry.id),
|
||||||
|
**price_args)
|
||||||
|
invoice_item_created = True
|
||||||
|
plan.invoiced_through = ledger_entry
|
||||||
|
plan.invoicing_status = CustomerPlan.DONE
|
||||||
|
plan.save(update_fields=['invoicing_status', 'invoiced_through'])
|
||||||
|
licenses_base = ledger_entry.licenses
|
||||||
|
|
||||||
|
if invoice_item_created:
|
||||||
|
if plan.charge_automatically:
|
||||||
|
billing_method = 'charge_automatically'
|
||||||
|
days_until_due = None
|
||||||
|
else:
|
||||||
|
billing_method = 'send_invoice'
|
||||||
|
days_until_due = DEFAULT_INVOICE_DAYS_UNTIL_DUE
|
||||||
|
stripe_invoice = stripe.Invoice.create(
|
||||||
|
auto_advance=True,
|
||||||
|
billing=billing_method,
|
||||||
|
customer=plan.customer.stripe_customer_id,
|
||||||
|
days_until_due=days_until_due,
|
||||||
|
statement_descriptor='Zulip Standard')
|
||||||
|
stripe.Invoice.finalize_invoice(stripe_invoice)
|
||||||
|
|
||||||
|
plan.next_invoice_date = next_invoice_date(plan)
|
||||||
|
plan.save(update_fields=['next_invoice_date'])
|
||||||
|
|
||||||
|
def invoice_plans_as_needed(event_time: datetime) -> None:
|
||||||
|
for plan in CustomerPlan.objects.filter(next_invoice_date__lte=event_time):
|
||||||
|
invoice_plan(plan, event_time)
|
||||||
|
|
||||||
def attach_discount_to_realm(user: UserProfile, discount: Decimal) -> None:
|
def attach_discount_to_realm(user: UserProfile, discount: Decimal) -> None:
|
||||||
customer = Customer.objects.filter(realm=user.realm).first()
|
customer = Customer.objects.filter(realm=user.realm).first()
|
||||||
if customer is None:
|
if customer is None:
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
{
|
||||||
|
"account_balance": 0,
|
||||||
|
"created": 1000000000,
|
||||||
|
"currency": null,
|
||||||
|
"default_source": null,
|
||||||
|
"delinquent": false,
|
||||||
|
"description": "zulip (Zulip Dev)",
|
||||||
|
"discount": null,
|
||||||
|
"email": "hamlet@zulip.com",
|
||||||
|
"id": "cus_NORMALIZED0001",
|
||||||
|
"invoice_prefix": "NORMA01",
|
||||||
|
"invoice_settings": {
|
||||||
|
"custom_fields": null,
|
||||||
|
"footer": null
|
||||||
|
},
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {
|
||||||
|
"realm_id": "1",
|
||||||
|
"realm_str": "zulip"
|
||||||
|
},
|
||||||
|
"object": "customer",
|
||||||
|
"shipping": null,
|
||||||
|
"sources": {
|
||||||
|
"data": [],
|
||||||
|
"has_more": false,
|
||||||
|
"object": "list",
|
||||||
|
"total_count": 0,
|
||||||
|
"url": "/v1/customers/cus_NORMALIZED0001/sources"
|
||||||
|
},
|
||||||
|
"subscriptions": {
|
||||||
|
"data": [],
|
||||||
|
"has_more": false,
|
||||||
|
"object": "list",
|
||||||
|
"total_count": 0,
|
||||||
|
"url": "/v1/customers/cus_NORMALIZED0001/subscriptions"
|
||||||
|
},
|
||||||
|
"tax_info": null,
|
||||||
|
"tax_info_verification": null
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
{
|
||||||
|
"amount_due": 984000,
|
||||||
|
"amount_paid": 0,
|
||||||
|
"amount_remaining": 984000,
|
||||||
|
"application_fee": null,
|
||||||
|
"attempt_count": 0,
|
||||||
|
"attempted": false,
|
||||||
|
"auto_advance": true,
|
||||||
|
"billing": "send_invoice",
|
||||||
|
"billing_reason": "manual",
|
||||||
|
"charge": null,
|
||||||
|
"currency": "usd",
|
||||||
|
"custom_fields": null,
|
||||||
|
"customer": "cus_NORMALIZED0001",
|
||||||
|
"date": 1000000000,
|
||||||
|
"default_source": null,
|
||||||
|
"description": "",
|
||||||
|
"discount": null,
|
||||||
|
"due_date": 1000000000,
|
||||||
|
"ending_balance": null,
|
||||||
|
"finalized_at": null,
|
||||||
|
"footer": null,
|
||||||
|
"hosted_invoice_url": null,
|
||||||
|
"id": "in_NORMALIZED00000000000001",
|
||||||
|
"invoice_pdf": null,
|
||||||
|
"lines": {
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"amount": 984000,
|
||||||
|
"currency": "usd",
|
||||||
|
"description": "Zulip Standard",
|
||||||
|
"discountable": false,
|
||||||
|
"id": "ii_NORMALIZED00000000000001",
|
||||||
|
"invoice_item": "ii_NORMALIZED00000000000001",
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "line_item",
|
||||||
|
"period": {
|
||||||
|
"end": 1357095845,
|
||||||
|
"start": 1325473445
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 123,
|
||||||
|
"subscription": null,
|
||||||
|
"type": "invoiceitem"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"has_more": false,
|
||||||
|
"object": "list",
|
||||||
|
"total_count": 1,
|
||||||
|
"url": "/v1/invoices/in_NORMALIZED00000000000001/lines"
|
||||||
|
},
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"next_payment_attempt": null,
|
||||||
|
"number": "NORMALI-0001",
|
||||||
|
"object": "invoice",
|
||||||
|
"paid": false,
|
||||||
|
"period_end": 1000000000,
|
||||||
|
"period_start": 1000000000,
|
||||||
|
"receipt_number": null,
|
||||||
|
"starting_balance": 0,
|
||||||
|
"statement_descriptor": "Zulip Standard",
|
||||||
|
"status": "draft",
|
||||||
|
"subscription": null,
|
||||||
|
"subtotal": 984000,
|
||||||
|
"tax": 0,
|
||||||
|
"tax_percent": null,
|
||||||
|
"total": 984000,
|
||||||
|
"webhooks_delivered_at": null
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
{
|
||||||
|
"amount_due": 100,
|
||||||
|
"amount_paid": 0,
|
||||||
|
"amount_remaining": 100,
|
||||||
|
"application_fee": null,
|
||||||
|
"attempt_count": 0,
|
||||||
|
"attempted": false,
|
||||||
|
"auto_advance": true,
|
||||||
|
"billing": "send_invoice",
|
||||||
|
"billing_reason": "manual",
|
||||||
|
"charge": null,
|
||||||
|
"currency": "usd",
|
||||||
|
"custom_fields": null,
|
||||||
|
"customer": "cus_NORMALIZED0001",
|
||||||
|
"date": 1000000000,
|
||||||
|
"default_source": null,
|
||||||
|
"description": "",
|
||||||
|
"discount": null,
|
||||||
|
"due_date": 1000000000,
|
||||||
|
"ending_balance": null,
|
||||||
|
"finalized_at": null,
|
||||||
|
"footer": null,
|
||||||
|
"hosted_invoice_url": null,
|
||||||
|
"id": "in_NORMALIZED00000000000002",
|
||||||
|
"invoice_pdf": null,
|
||||||
|
"lines": {
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"amount": 100,
|
||||||
|
"currency": "usd",
|
||||||
|
"description": "Zulip Standard - renewal",
|
||||||
|
"discountable": false,
|
||||||
|
"id": "ii_NORMALIZED00000000000002",
|
||||||
|
"invoice_item": "ii_NORMALIZED00000000000002",
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "line_item",
|
||||||
|
"period": {
|
||||||
|
"end": 1388631845,
|
||||||
|
"start": 1357095845
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 1,
|
||||||
|
"subscription": null,
|
||||||
|
"type": "invoiceitem"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"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",
|
||||||
|
"paid": false,
|
||||||
|
"period_end": 1000000000,
|
||||||
|
"period_start": 1000000000,
|
||||||
|
"receipt_number": null,
|
||||||
|
"starting_balance": 0,
|
||||||
|
"statement_descriptor": "Zulip Standard",
|
||||||
|
"status": "draft",
|
||||||
|
"subscription": null,
|
||||||
|
"subtotal": 100,
|
||||||
|
"tax": 0,
|
||||||
|
"tax_percent": null,
|
||||||
|
"total": 100,
|
||||||
|
"webhooks_delivered_at": null
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
{
|
||||||
|
"amount_due": 984000,
|
||||||
|
"amount_paid": 0,
|
||||||
|
"amount_remaining": 984000,
|
||||||
|
"application_fee": null,
|
||||||
|
"attempt_count": 0,
|
||||||
|
"attempted": false,
|
||||||
|
"auto_advance": true,
|
||||||
|
"billing": "send_invoice",
|
||||||
|
"billing_reason": "manual",
|
||||||
|
"charge": null,
|
||||||
|
"currency": "usd",
|
||||||
|
"custom_fields": null,
|
||||||
|
"customer": "cus_NORMALIZED0001",
|
||||||
|
"date": 1000000000,
|
||||||
|
"default_source": null,
|
||||||
|
"description": "",
|
||||||
|
"discount": null,
|
||||||
|
"due_date": 1000000000,
|
||||||
|
"ending_balance": 0,
|
||||||
|
"finalized_at": 1000000000,
|
||||||
|
"footer": null,
|
||||||
|
"hosted_invoice_url": "https://pay.stripe.com/invoice/invst_NORMALIZED0000000000000001",
|
||||||
|
"id": "in_NORMALIZED00000000000001",
|
||||||
|
"invoice_pdf": "https://pay.stripe.com/invoice/invst_NORMALIZED0000000000000001/pdf",
|
||||||
|
"lines": {
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"amount": 984000,
|
||||||
|
"currency": "usd",
|
||||||
|
"description": "Zulip Standard",
|
||||||
|
"discountable": false,
|
||||||
|
"id": "ii_NORMALIZED00000000000001",
|
||||||
|
"invoice_item": "ii_NORMALIZED00000000000001",
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "line_item",
|
||||||
|
"period": {
|
||||||
|
"end": 1357095845,
|
||||||
|
"start": 1325473445
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 123,
|
||||||
|
"subscription": null,
|
||||||
|
"type": "invoiceitem"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"has_more": false,
|
||||||
|
"object": "list",
|
||||||
|
"total_count": 1,
|
||||||
|
"url": "/v1/invoices/in_NORMALIZED00000000000001/lines"
|
||||||
|
},
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"next_payment_attempt": null,
|
||||||
|
"number": "NORMALI-0001",
|
||||||
|
"object": "invoice",
|
||||||
|
"paid": false,
|
||||||
|
"period_end": 1000000000,
|
||||||
|
"period_start": 1000000000,
|
||||||
|
"receipt_number": null,
|
||||||
|
"starting_balance": 0,
|
||||||
|
"statement_descriptor": "Zulip Standard",
|
||||||
|
"status": "open",
|
||||||
|
"subscription": null,
|
||||||
|
"subtotal": 984000,
|
||||||
|
"tax": 0,
|
||||||
|
"tax_percent": null,
|
||||||
|
"total": 984000,
|
||||||
|
"webhooks_delivered_at": 1000000000
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
{
|
||||||
|
"amount_due": 100,
|
||||||
|
"amount_paid": 0,
|
||||||
|
"amount_remaining": 100,
|
||||||
|
"application_fee": null,
|
||||||
|
"attempt_count": 0,
|
||||||
|
"attempted": false,
|
||||||
|
"auto_advance": true,
|
||||||
|
"billing": "send_invoice",
|
||||||
|
"billing_reason": "manual",
|
||||||
|
"charge": null,
|
||||||
|
"currency": "usd",
|
||||||
|
"custom_fields": null,
|
||||||
|
"customer": "cus_NORMALIZED0001",
|
||||||
|
"date": 1000000000,
|
||||||
|
"default_source": null,
|
||||||
|
"description": "",
|
||||||
|
"discount": null,
|
||||||
|
"due_date": 1000000000,
|
||||||
|
"ending_balance": 0,
|
||||||
|
"finalized_at": 1000000000,
|
||||||
|
"footer": null,
|
||||||
|
"hosted_invoice_url": "https://pay.stripe.com/invoice/invst_NORMALIZED0000000000000002",
|
||||||
|
"id": "in_NORMALIZED00000000000002",
|
||||||
|
"invoice_pdf": "https://pay.stripe.com/invoice/invst_NORMALIZED0000000000000002/pdf",
|
||||||
|
"lines": {
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"amount": 100,
|
||||||
|
"currency": "usd",
|
||||||
|
"description": "Zulip Standard - renewal",
|
||||||
|
"discountable": false,
|
||||||
|
"id": "ii_NORMALIZED00000000000002",
|
||||||
|
"invoice_item": "ii_NORMALIZED00000000000002",
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "line_item",
|
||||||
|
"period": {
|
||||||
|
"end": 1388631845,
|
||||||
|
"start": 1357095845
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 1,
|
||||||
|
"subscription": null,
|
||||||
|
"type": "invoiceitem"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"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",
|
||||||
|
"paid": false,
|
||||||
|
"period_end": 1000000000,
|
||||||
|
"period_start": 1000000000,
|
||||||
|
"receipt_number": null,
|
||||||
|
"starting_balance": 0,
|
||||||
|
"statement_descriptor": "Zulip Standard",
|
||||||
|
"status": "open",
|
||||||
|
"subscription": null,
|
||||||
|
"subtotal": 100,
|
||||||
|
"tax": 0,
|
||||||
|
"tax_percent": null,
|
||||||
|
"total": 100,
|
||||||
|
"webhooks_delivered_at": 1000000000
|
||||||
|
}
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
{
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"amount_due": 100,
|
||||||
|
"amount_paid": 0,
|
||||||
|
"amount_remaining": 100,
|
||||||
|
"application_fee": null,
|
||||||
|
"attempt_count": 0,
|
||||||
|
"attempted": false,
|
||||||
|
"auto_advance": true,
|
||||||
|
"billing": "send_invoice",
|
||||||
|
"billing_reason": "manual",
|
||||||
|
"charge": null,
|
||||||
|
"currency": "usd",
|
||||||
|
"custom_fields": null,
|
||||||
|
"customer": "cus_NORMALIZED0001",
|
||||||
|
"date": 1000000000,
|
||||||
|
"default_source": null,
|
||||||
|
"description": "",
|
||||||
|
"discount": null,
|
||||||
|
"due_date": 1000000000,
|
||||||
|
"ending_balance": 0,
|
||||||
|
"finalized_at": 1000000000,
|
||||||
|
"footer": null,
|
||||||
|
"hosted_invoice_url": "https://pay.stripe.com/invoice/invst_NORMALIZED0000000000000002",
|
||||||
|
"id": "in_NORMALIZED00000000000002",
|
||||||
|
"invoice_pdf": "https://pay.stripe.com/invoice/invst_NORMALIZED0000000000000002/pdf",
|
||||||
|
"lines": {
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"amount": 100,
|
||||||
|
"currency": "usd",
|
||||||
|
"description": "Zulip Standard - renewal",
|
||||||
|
"discountable": false,
|
||||||
|
"id": "ii_NORMALIZED00000000000002",
|
||||||
|
"invoice_item": "ii_NORMALIZED00000000000002",
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "line_item",
|
||||||
|
"period": {
|
||||||
|
"end": 1388631845,
|
||||||
|
"start": 1357095845
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 1,
|
||||||
|
"subscription": null,
|
||||||
|
"type": "invoiceitem"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"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",
|
||||||
|
"paid": false,
|
||||||
|
"period_end": 1000000000,
|
||||||
|
"period_start": 1000000000,
|
||||||
|
"receipt_number": null,
|
||||||
|
"starting_balance": 0,
|
||||||
|
"statement_descriptor": "Zulip Standard",
|
||||||
|
"status": "open",
|
||||||
|
"subscription": null,
|
||||||
|
"subtotal": 100,
|
||||||
|
"tax": 0,
|
||||||
|
"tax_percent": null,
|
||||||
|
"total": 100,
|
||||||
|
"webhooks_delivered_at": 1000000000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount_due": 984000,
|
||||||
|
"amount_paid": 0,
|
||||||
|
"amount_remaining": 984000,
|
||||||
|
"application_fee": null,
|
||||||
|
"attempt_count": 0,
|
||||||
|
"attempted": false,
|
||||||
|
"auto_advance": true,
|
||||||
|
"billing": "send_invoice",
|
||||||
|
"billing_reason": "manual",
|
||||||
|
"charge": null,
|
||||||
|
"currency": "usd",
|
||||||
|
"custom_fields": null,
|
||||||
|
"customer": "cus_NORMALIZED0001",
|
||||||
|
"date": 1000000000,
|
||||||
|
"default_source": null,
|
||||||
|
"description": "",
|
||||||
|
"discount": null,
|
||||||
|
"due_date": 1000000000,
|
||||||
|
"ending_balance": 0,
|
||||||
|
"finalized_at": 1000000000,
|
||||||
|
"footer": null,
|
||||||
|
"hosted_invoice_url": "https://pay.stripe.com/invoice/invst_NORMALIZED0000000000000001",
|
||||||
|
"id": "in_NORMALIZED00000000000001",
|
||||||
|
"invoice_pdf": "https://pay.stripe.com/invoice/invst_NORMALIZED0000000000000001/pdf",
|
||||||
|
"lines": {
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"amount": 984000,
|
||||||
|
"currency": "usd",
|
||||||
|
"description": "Zulip Standard",
|
||||||
|
"discountable": false,
|
||||||
|
"id": "ii_NORMALIZED00000000000001",
|
||||||
|
"invoice_item": "ii_NORMALIZED00000000000001",
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "line_item",
|
||||||
|
"period": {
|
||||||
|
"end": 1357095845,
|
||||||
|
"start": 1325473445
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 123,
|
||||||
|
"subscription": null,
|
||||||
|
"type": "invoiceitem"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"has_more": false,
|
||||||
|
"object": "list",
|
||||||
|
"total_count": 1,
|
||||||
|
"url": "/v1/invoices/in_NORMALIZED00000000000001/lines"
|
||||||
|
},
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"next_payment_attempt": null,
|
||||||
|
"number": "NORMALI-0001",
|
||||||
|
"object": "invoice",
|
||||||
|
"paid": false,
|
||||||
|
"period_end": 1000000000,
|
||||||
|
"period_start": 1000000000,
|
||||||
|
"receipt_number": null,
|
||||||
|
"starting_balance": 0,
|
||||||
|
"statement_descriptor": "Zulip Standard",
|
||||||
|
"status": "open",
|
||||||
|
"subscription": null,
|
||||||
|
"subtotal": 984000,
|
||||||
|
"tax": 0,
|
||||||
|
"tax_percent": null,
|
||||||
|
"total": 984000,
|
||||||
|
"webhooks_delivered_at": 1000000000
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"has_more": false,
|
||||||
|
"object": "list",
|
||||||
|
"url": "/v1/invoices"
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"amount": 984000,
|
||||||
|
"currency": "usd",
|
||||||
|
"customer": "cus_NORMALIZED0001",
|
||||||
|
"date": 1000000000,
|
||||||
|
"description": "Zulip Standard",
|
||||||
|
"discountable": false,
|
||||||
|
"id": "ii_NORMALIZED00000000000001",
|
||||||
|
"invoice": null,
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "invoiceitem",
|
||||||
|
"period": {
|
||||||
|
"end": 1357095845,
|
||||||
|
"start": 1325473445
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 123,
|
||||||
|
"subscription": null,
|
||||||
|
"unit_amount": 8000
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"amount": 100,
|
||||||
|
"currency": "usd",
|
||||||
|
"customer": "cus_NORMALIZED0001",
|
||||||
|
"date": 1000000000,
|
||||||
|
"description": "Zulip Standard - renewal",
|
||||||
|
"discountable": false,
|
||||||
|
"id": "ii_NORMALIZED00000000000002",
|
||||||
|
"invoice": null,
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "invoiceitem",
|
||||||
|
"period": {
|
||||||
|
"end": 1388631845,
|
||||||
|
"start": 1357095845
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 1,
|
||||||
|
"subscription": null,
|
||||||
|
"unit_amount": 100
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
{
|
||||||
|
"amount": 64000,
|
||||||
|
"amount_refunded": 0,
|
||||||
|
"application": null,
|
||||||
|
"application_fee": null,
|
||||||
|
"application_fee_amount": null,
|
||||||
|
"balance_transaction": "txn_1DxdruGh0CmXqmnwJQIcAlGj",
|
||||||
|
"captured": true,
|
||||||
|
"created": 1548696358,
|
||||||
|
"currency": "usd",
|
||||||
|
"customer": "cus_EQUrCdXCP2oqIF",
|
||||||
|
"description": "Upgrade to Zulip Standard, $80.0 x 8",
|
||||||
|
"destination": null,
|
||||||
|
"dispute": null,
|
||||||
|
"failure_code": null,
|
||||||
|
"failure_message": null,
|
||||||
|
"fraud_details": {},
|
||||||
|
"id": "ch_1DxdruGh0CmXqmnwSwEPHAI6",
|
||||||
|
"invoice": null,
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "charge",
|
||||||
|
"on_behalf_of": null,
|
||||||
|
"order": null,
|
||||||
|
"outcome": {
|
||||||
|
"network_status": "approved_by_network",
|
||||||
|
"reason": null,
|
||||||
|
"risk_level": "normal",
|
||||||
|
"risk_score": 6,
|
||||||
|
"seller_message": "Payment complete.",
|
||||||
|
"type": "authorized"
|
||||||
|
},
|
||||||
|
"paid": true,
|
||||||
|
"payment_intent": null,
|
||||||
|
"receipt_email": "hamlet@zulip.com",
|
||||||
|
"receipt_number": null,
|
||||||
|
"receipt_url": "https://pay.stripe.com/receipts/acct_1BWYgHGh0CmXqmnw/ch_1DxdruGh0CmXqmnwSwEPHAI6/rcpt_EQUr7TAzRbJU3vjRTVdNKpnyUvWTXz2",
|
||||||
|
"refunded": false,
|
||||||
|
"refunds": {
|
||||||
|
"data": [],
|
||||||
|
"has_more": false,
|
||||||
|
"object": "list",
|
||||||
|
"total_count": 0,
|
||||||
|
"url": "/v1/charges/ch_1DxdruGh0CmXqmnwSwEPHAI6/refunds"
|
||||||
|
},
|
||||||
|
"review": null,
|
||||||
|
"shipping": null,
|
||||||
|
"source": {
|
||||||
|
"address_city": "Pacific",
|
||||||
|
"address_country": "United States",
|
||||||
|
"address_line1": "Under the sea,",
|
||||||
|
"address_line1_check": "pass",
|
||||||
|
"address_line2": null,
|
||||||
|
"address_state": null,
|
||||||
|
"address_zip": "33333",
|
||||||
|
"address_zip_check": "pass",
|
||||||
|
"brand": "Visa",
|
||||||
|
"country": "US",
|
||||||
|
"customer": "cus_EQUrCdXCP2oqIF",
|
||||||
|
"cvc_check": "pass",
|
||||||
|
"dynamic_last4": null,
|
||||||
|
"exp_month": 3,
|
||||||
|
"exp_year": 2033,
|
||||||
|
"fingerprint": "6dAXT9VZvwro65EK",
|
||||||
|
"funding": "credit",
|
||||||
|
"id": "card_1DxdrtGh0CmXqmnw1LvZ0cL4",
|
||||||
|
"last4": "4242",
|
||||||
|
"metadata": {},
|
||||||
|
"name": "Ada Starr",
|
||||||
|
"object": "card",
|
||||||
|
"tokenization_method": null
|
||||||
|
},
|
||||||
|
"source_transfer": null,
|
||||||
|
"statement_descriptor": "Zulip Standard",
|
||||||
|
"status": "succeeded",
|
||||||
|
"transfer_data": null,
|
||||||
|
"transfer_group": null
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
{
|
||||||
|
"account_balance": 0,
|
||||||
|
"created": 1548696357,
|
||||||
|
"currency": null,
|
||||||
|
"default_source": "card_1DxdrtGh0CmXqmnw1LvZ0cL4",
|
||||||
|
"delinquent": false,
|
||||||
|
"description": "zulip (Zulip Dev)",
|
||||||
|
"discount": null,
|
||||||
|
"email": "hamlet@zulip.com",
|
||||||
|
"id": "cus_EQUrCdXCP2oqIF",
|
||||||
|
"invoice_prefix": "81F7A21",
|
||||||
|
"invoice_settings": {
|
||||||
|
"custom_fields": null,
|
||||||
|
"footer": null
|
||||||
|
},
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {
|
||||||
|
"realm_id": "1",
|
||||||
|
"realm_str": "zulip"
|
||||||
|
},
|
||||||
|
"object": "customer",
|
||||||
|
"shipping": null,
|
||||||
|
"sources": {
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"address_city": "Pacific",
|
||||||
|
"address_country": "United States",
|
||||||
|
"address_line1": "Under the sea,",
|
||||||
|
"address_line1_check": "pass",
|
||||||
|
"address_line2": null,
|
||||||
|
"address_state": null,
|
||||||
|
"address_zip": "33333",
|
||||||
|
"address_zip_check": "pass",
|
||||||
|
"brand": "Visa",
|
||||||
|
"country": "US",
|
||||||
|
"customer": "cus_EQUrCdXCP2oqIF",
|
||||||
|
"cvc_check": "pass",
|
||||||
|
"dynamic_last4": null,
|
||||||
|
"exp_month": 3,
|
||||||
|
"exp_year": 2033,
|
||||||
|
"fingerprint": "6dAXT9VZvwro65EK",
|
||||||
|
"funding": "credit",
|
||||||
|
"id": "card_1DxdrtGh0CmXqmnw1LvZ0cL4",
|
||||||
|
"last4": "4242",
|
||||||
|
"metadata": {},
|
||||||
|
"name": "Ada Starr",
|
||||||
|
"object": "card",
|
||||||
|
"tokenization_method": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"has_more": false,
|
||||||
|
"object": "list",
|
||||||
|
"total_count": 1,
|
||||||
|
"url": "/v1/customers/cus_EQUrCdXCP2oqIF/sources"
|
||||||
|
},
|
||||||
|
"subscriptions": {
|
||||||
|
"data": [],
|
||||||
|
"has_more": false,
|
||||||
|
"object": "list",
|
||||||
|
"total_count": 0,
|
||||||
|
"url": "/v1/customers/cus_EQUrCdXCP2oqIF/subscriptions"
|
||||||
|
},
|
||||||
|
"tax_info": null,
|
||||||
|
"tax_info_verification": null
|
||||||
|
}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
{
|
||||||
|
"amount_due": 0,
|
||||||
|
"amount_paid": 0,
|
||||||
|
"amount_remaining": 0,
|
||||||
|
"application_fee": null,
|
||||||
|
"attempt_count": 0,
|
||||||
|
"attempted": false,
|
||||||
|
"auto_advance": true,
|
||||||
|
"billing": "charge_automatically",
|
||||||
|
"billing_reason": "manual",
|
||||||
|
"charge": null,
|
||||||
|
"currency": "usd",
|
||||||
|
"custom_fields": null,
|
||||||
|
"customer": "cus_EQUrCdXCP2oqIF",
|
||||||
|
"date": 1548696360,
|
||||||
|
"default_source": null,
|
||||||
|
"description": "",
|
||||||
|
"discount": null,
|
||||||
|
"due_date": null,
|
||||||
|
"ending_balance": null,
|
||||||
|
"finalized_at": null,
|
||||||
|
"footer": null,
|
||||||
|
"hosted_invoice_url": null,
|
||||||
|
"id": "in_1DxdrwGh0CmXqmnw7x9G2rWd",
|
||||||
|
"invoice_pdf": null,
|
||||||
|
"lines": {
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"amount": 64000,
|
||||||
|
"currency": "usd",
|
||||||
|
"description": "Zulip Standard",
|
||||||
|
"discountable": false,
|
||||||
|
"id": "ii_1DxdrvGh0CmXqmnwhHM5DcR1",
|
||||||
|
"invoice_item": "ii_1DxdrvGh0CmXqmnwhHM5DcR1",
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "line_item",
|
||||||
|
"period": {
|
||||||
|
"end": 1357095845,
|
||||||
|
"start": 1325473445
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 8,
|
||||||
|
"subscription": null,
|
||||||
|
"type": "invoiceitem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": -64000,
|
||||||
|
"currency": "usd",
|
||||||
|
"description": "Payment (Card ending in 4242)",
|
||||||
|
"discountable": false,
|
||||||
|
"id": "ii_1DxdrvGh0CmXqmnwg0R6ha8n",
|
||||||
|
"invoice_item": "ii_1DxdrvGh0CmXqmnwg0R6ha8n",
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "line_item",
|
||||||
|
"period": {
|
||||||
|
"end": 1548696359,
|
||||||
|
"start": 1548696359
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 1,
|
||||||
|
"subscription": null,
|
||||||
|
"type": "invoiceitem"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"has_more": false,
|
||||||
|
"object": "list",
|
||||||
|
"total_count": 2,
|
||||||
|
"url": "/v1/invoices/in_1DxdrwGh0CmXqmnw7x9G2rWd/lines"
|
||||||
|
},
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"next_payment_attempt": 1548699960,
|
||||||
|
"number": "81F7A21-0001",
|
||||||
|
"object": "invoice",
|
||||||
|
"paid": false,
|
||||||
|
"period_end": 1548696360,
|
||||||
|
"period_start": 1548696360,
|
||||||
|
"receipt_number": null,
|
||||||
|
"starting_balance": 0,
|
||||||
|
"statement_descriptor": "Zulip Standard",
|
||||||
|
"status": "draft",
|
||||||
|
"subscription": null,
|
||||||
|
"subtotal": 0,
|
||||||
|
"tax": 0,
|
||||||
|
"tax_percent": null,
|
||||||
|
"total": 0,
|
||||||
|
"webhooks_delivered_at": null
|
||||||
|
}
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
{
|
||||||
|
"amount_due": 96697,
|
||||||
|
"amount_paid": 0,
|
||||||
|
"amount_remaining": 96697,
|
||||||
|
"application_fee": null,
|
||||||
|
"attempt_count": 0,
|
||||||
|
"attempted": false,
|
||||||
|
"auto_advance": true,
|
||||||
|
"billing": "charge_automatically",
|
||||||
|
"billing_reason": "manual",
|
||||||
|
"charge": null,
|
||||||
|
"currency": "usd",
|
||||||
|
"custom_fields": null,
|
||||||
|
"customer": "cus_EQUrCdXCP2oqIF",
|
||||||
|
"date": 1548696362,
|
||||||
|
"default_source": null,
|
||||||
|
"description": "",
|
||||||
|
"discount": null,
|
||||||
|
"due_date": null,
|
||||||
|
"ending_balance": null,
|
||||||
|
"finalized_at": null,
|
||||||
|
"footer": null,
|
||||||
|
"hosted_invoice_url": null,
|
||||||
|
"id": "in_1DxdryGh0CmXqmnwqSArnOBA",
|
||||||
|
"invoice_pdf": null,
|
||||||
|
"lines": {
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"amount": 7255,
|
||||||
|
"currency": "usd",
|
||||||
|
"description": "Additional license (Feb 5, 2013 - Jan 2, 2014)",
|
||||||
|
"discountable": false,
|
||||||
|
"id": "ii_1DxdryGh0CmXqmnwXSzdImK3",
|
||||||
|
"invoice_item": "ii_1DxdryGh0CmXqmnwXSzdImK3",
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "line_item",
|
||||||
|
"period": {
|
||||||
|
"end": 1388631845,
|
||||||
|
"start": 1360033445
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 1,
|
||||||
|
"subscription": null,
|
||||||
|
"type": "invoiceitem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": 72000,
|
||||||
|
"currency": "usd",
|
||||||
|
"description": "Zulip Standard - renewal",
|
||||||
|
"discountable": false,
|
||||||
|
"id": "ii_1DxdrxGh0CmXqmnw183j11lw",
|
||||||
|
"invoice_item": "ii_1DxdrxGh0CmXqmnw183j11lw",
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "line_item",
|
||||||
|
"period": {
|
||||||
|
"end": 1388631845,
|
||||||
|
"start": 1357095845
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 9,
|
||||||
|
"subscription": null,
|
||||||
|
"type": "invoiceitem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": 17442,
|
||||||
|
"currency": "usd",
|
||||||
|
"description": "Additional license (Apr 11, 2012 - Jan 2, 2013)",
|
||||||
|
"discountable": false,
|
||||||
|
"id": "ii_1DxdrxGh0CmXqmnwSpeA2crG",
|
||||||
|
"invoice_item": "ii_1DxdrxGh0CmXqmnwSpeA2crG",
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "line_item",
|
||||||
|
"period": {
|
||||||
|
"end": 1357095845,
|
||||||
|
"start": 1334113445
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 3,
|
||||||
|
"subscription": null,
|
||||||
|
"type": "invoiceitem"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"has_more": false,
|
||||||
|
"object": "list",
|
||||||
|
"total_count": 3,
|
||||||
|
"url": "/v1/invoices/in_1DxdryGh0CmXqmnwqSArnOBA/lines"
|
||||||
|
},
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"next_payment_attempt": 1548699962,
|
||||||
|
"number": "81F7A21-0002",
|
||||||
|
"object": "invoice",
|
||||||
|
"paid": false,
|
||||||
|
"period_end": 1548696362,
|
||||||
|
"period_start": 1548696362,
|
||||||
|
"receipt_number": null,
|
||||||
|
"starting_balance": 0,
|
||||||
|
"statement_descriptor": "Zulip Standard",
|
||||||
|
"status": "draft",
|
||||||
|
"subscription": null,
|
||||||
|
"subtotal": 96697,
|
||||||
|
"tax": 0,
|
||||||
|
"tax_percent": null,
|
||||||
|
"total": 96697,
|
||||||
|
"webhooks_delivered_at": null
|
||||||
|
}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
{
|
||||||
|
"amount_due": 0,
|
||||||
|
"amount_paid": 0,
|
||||||
|
"amount_remaining": 0,
|
||||||
|
"application_fee": null,
|
||||||
|
"attempt_count": 0,
|
||||||
|
"attempted": true,
|
||||||
|
"auto_advance": false,
|
||||||
|
"billing": "charge_automatically",
|
||||||
|
"billing_reason": "manual",
|
||||||
|
"charge": null,
|
||||||
|
"currency": "usd",
|
||||||
|
"custom_fields": null,
|
||||||
|
"customer": "cus_EQUrCdXCP2oqIF",
|
||||||
|
"date": 1548696360,
|
||||||
|
"default_source": null,
|
||||||
|
"description": "",
|
||||||
|
"discount": null,
|
||||||
|
"due_date": 1551288360,
|
||||||
|
"ending_balance": 0,
|
||||||
|
"finalized_at": 1548696360,
|
||||||
|
"footer": null,
|
||||||
|
"hosted_invoice_url": "https://pay.stripe.com/invoice/invst_QWWFlNhg4YyUdnWxVhUvuDs8TZ",
|
||||||
|
"id": "in_1DxdrwGh0CmXqmnw7x9G2rWd",
|
||||||
|
"invoice_pdf": "https://pay.stripe.com/invoice/invst_QWWFlNhg4YyUdnWxVhUvuDs8TZ/pdf",
|
||||||
|
"lines": {
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"amount": 64000,
|
||||||
|
"currency": "usd",
|
||||||
|
"description": "Zulip Standard",
|
||||||
|
"discountable": false,
|
||||||
|
"id": "ii_1DxdrvGh0CmXqmnwhHM5DcR1",
|
||||||
|
"invoice_item": "ii_1DxdrvGh0CmXqmnwhHM5DcR1",
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "line_item",
|
||||||
|
"period": {
|
||||||
|
"end": 1357095845,
|
||||||
|
"start": 1325473445
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 8,
|
||||||
|
"subscription": null,
|
||||||
|
"type": "invoiceitem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": -64000,
|
||||||
|
"currency": "usd",
|
||||||
|
"description": "Payment (Card ending in 4242)",
|
||||||
|
"discountable": false,
|
||||||
|
"id": "ii_1DxdrvGh0CmXqmnwg0R6ha8n",
|
||||||
|
"invoice_item": "ii_1DxdrvGh0CmXqmnwg0R6ha8n",
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "line_item",
|
||||||
|
"period": {
|
||||||
|
"end": 1548696359,
|
||||||
|
"start": 1548696359
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 1,
|
||||||
|
"subscription": null,
|
||||||
|
"type": "invoiceitem"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"has_more": false,
|
||||||
|
"object": "list",
|
||||||
|
"total_count": 2,
|
||||||
|
"url": "/v1/invoices/in_1DxdrwGh0CmXqmnw7x9G2rWd/lines"
|
||||||
|
},
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"next_payment_attempt": null,
|
||||||
|
"number": "81F7A21-0001",
|
||||||
|
"object": "invoice",
|
||||||
|
"paid": true,
|
||||||
|
"period_end": 1548696360,
|
||||||
|
"period_start": 1548696360,
|
||||||
|
"receipt_number": null,
|
||||||
|
"starting_balance": 0,
|
||||||
|
"statement_descriptor": "Zulip Standard",
|
||||||
|
"status": "paid",
|
||||||
|
"subscription": null,
|
||||||
|
"subtotal": 0,
|
||||||
|
"tax": 0,
|
||||||
|
"tax_percent": null,
|
||||||
|
"total": 0,
|
||||||
|
"webhooks_delivered_at": 1548696360
|
||||||
|
}
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
{
|
||||||
|
"amount_due": 96697,
|
||||||
|
"amount_paid": 0,
|
||||||
|
"amount_remaining": 96697,
|
||||||
|
"application_fee": null,
|
||||||
|
"attempt_count": 0,
|
||||||
|
"attempted": false,
|
||||||
|
"auto_advance": true,
|
||||||
|
"billing": "charge_automatically",
|
||||||
|
"billing_reason": "manual",
|
||||||
|
"charge": null,
|
||||||
|
"currency": "usd",
|
||||||
|
"custom_fields": null,
|
||||||
|
"customer": "cus_EQUrCdXCP2oqIF",
|
||||||
|
"date": 1548696362,
|
||||||
|
"default_source": null,
|
||||||
|
"description": "",
|
||||||
|
"discount": null,
|
||||||
|
"due_date": 1551288363,
|
||||||
|
"ending_balance": 0,
|
||||||
|
"finalized_at": 1548696363,
|
||||||
|
"footer": null,
|
||||||
|
"hosted_invoice_url": "https://pay.stripe.com/invoice/invst_sT02SUZUJrLO3QmdmKIAQwQi9F",
|
||||||
|
"id": "in_1DxdryGh0CmXqmnwqSArnOBA",
|
||||||
|
"invoice_pdf": "https://pay.stripe.com/invoice/invst_sT02SUZUJrLO3QmdmKIAQwQi9F/pdf",
|
||||||
|
"lines": {
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"amount": 7255,
|
||||||
|
"currency": "usd",
|
||||||
|
"description": "Additional license (Feb 5, 2013 - Jan 2, 2014)",
|
||||||
|
"discountable": false,
|
||||||
|
"id": "ii_1DxdryGh0CmXqmnwXSzdImK3",
|
||||||
|
"invoice_item": "ii_1DxdryGh0CmXqmnwXSzdImK3",
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "line_item",
|
||||||
|
"period": {
|
||||||
|
"end": 1388631845,
|
||||||
|
"start": 1360033445
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 1,
|
||||||
|
"subscription": null,
|
||||||
|
"type": "invoiceitem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": 72000,
|
||||||
|
"currency": "usd",
|
||||||
|
"description": "Zulip Standard - renewal",
|
||||||
|
"discountable": false,
|
||||||
|
"id": "ii_1DxdrxGh0CmXqmnw183j11lw",
|
||||||
|
"invoice_item": "ii_1DxdrxGh0CmXqmnw183j11lw",
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "line_item",
|
||||||
|
"period": {
|
||||||
|
"end": 1388631845,
|
||||||
|
"start": 1357095845
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 9,
|
||||||
|
"subscription": null,
|
||||||
|
"type": "invoiceitem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": 17442,
|
||||||
|
"currency": "usd",
|
||||||
|
"description": "Additional license (Apr 11, 2012 - Jan 2, 2013)",
|
||||||
|
"discountable": false,
|
||||||
|
"id": "ii_1DxdrxGh0CmXqmnwSpeA2crG",
|
||||||
|
"invoice_item": "ii_1DxdrxGh0CmXqmnwSpeA2crG",
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "line_item",
|
||||||
|
"period": {
|
||||||
|
"end": 1357095845,
|
||||||
|
"start": 1334113445
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 3,
|
||||||
|
"subscription": null,
|
||||||
|
"type": "invoiceitem"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"has_more": false,
|
||||||
|
"object": "list",
|
||||||
|
"total_count": 3,
|
||||||
|
"url": "/v1/invoices/in_1DxdryGh0CmXqmnwqSArnOBA/lines"
|
||||||
|
},
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"next_payment_attempt": 1548699962,
|
||||||
|
"number": "81F7A21-0002",
|
||||||
|
"object": "invoice",
|
||||||
|
"paid": false,
|
||||||
|
"period_end": 1548696362,
|
||||||
|
"period_start": 1548696362,
|
||||||
|
"receipt_number": null,
|
||||||
|
"starting_balance": 0,
|
||||||
|
"statement_descriptor": "Zulip Standard",
|
||||||
|
"status": "open",
|
||||||
|
"subscription": null,
|
||||||
|
"subtotal": 96697,
|
||||||
|
"tax": 0,
|
||||||
|
"tax_percent": null,
|
||||||
|
"total": 96697,
|
||||||
|
"webhooks_delivered_at": 1548696362
|
||||||
|
}
|
||||||
211
corporate/tests/stripe_fixtures/invoice_plan:Invoice.list.1.json
Normal file
211
corporate/tests/stripe_fixtures/invoice_plan:Invoice.list.1.json
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
{
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"amount_due": 96697,
|
||||||
|
"amount_paid": 0,
|
||||||
|
"amount_remaining": 96697,
|
||||||
|
"application_fee": null,
|
||||||
|
"attempt_count": 0,
|
||||||
|
"attempted": false,
|
||||||
|
"auto_advance": true,
|
||||||
|
"billing": "charge_automatically",
|
||||||
|
"billing_reason": "manual",
|
||||||
|
"charge": null,
|
||||||
|
"currency": "usd",
|
||||||
|
"custom_fields": null,
|
||||||
|
"customer": "cus_EQUrCdXCP2oqIF",
|
||||||
|
"date": 1548696362,
|
||||||
|
"default_source": null,
|
||||||
|
"description": "",
|
||||||
|
"discount": null,
|
||||||
|
"due_date": 1551288363,
|
||||||
|
"ending_balance": 0,
|
||||||
|
"finalized_at": 1548696363,
|
||||||
|
"footer": null,
|
||||||
|
"hosted_invoice_url": "https://pay.stripe.com/invoice/invst_sT02SUZUJrLO3QmdmKIAQwQi9F",
|
||||||
|
"id": "in_1DxdryGh0CmXqmnwqSArnOBA",
|
||||||
|
"invoice_pdf": "https://pay.stripe.com/invoice/invst_sT02SUZUJrLO3QmdmKIAQwQi9F/pdf",
|
||||||
|
"lines": {
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"amount": 7255,
|
||||||
|
"currency": "usd",
|
||||||
|
"description": "Additional license (Feb 5, 2013 - Jan 2, 2014)",
|
||||||
|
"discountable": false,
|
||||||
|
"id": "ii_1DxdryGh0CmXqmnwXSzdImK3",
|
||||||
|
"invoice_item": "ii_1DxdryGh0CmXqmnwXSzdImK3",
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "line_item",
|
||||||
|
"period": {
|
||||||
|
"end": 1388631845,
|
||||||
|
"start": 1360033445
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 1,
|
||||||
|
"subscription": null,
|
||||||
|
"type": "invoiceitem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": 72000,
|
||||||
|
"currency": "usd",
|
||||||
|
"description": "Zulip Standard - renewal",
|
||||||
|
"discountable": false,
|
||||||
|
"id": "ii_1DxdrxGh0CmXqmnw183j11lw",
|
||||||
|
"invoice_item": "ii_1DxdrxGh0CmXqmnw183j11lw",
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "line_item",
|
||||||
|
"period": {
|
||||||
|
"end": 1388631845,
|
||||||
|
"start": 1357095845
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 9,
|
||||||
|
"subscription": null,
|
||||||
|
"type": "invoiceitem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": 17442,
|
||||||
|
"currency": "usd",
|
||||||
|
"description": "Additional license (Apr 11, 2012 - Jan 2, 2013)",
|
||||||
|
"discountable": false,
|
||||||
|
"id": "ii_1DxdrxGh0CmXqmnwSpeA2crG",
|
||||||
|
"invoice_item": "ii_1DxdrxGh0CmXqmnwSpeA2crG",
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "line_item",
|
||||||
|
"period": {
|
||||||
|
"end": 1357095845,
|
||||||
|
"start": 1334113445
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 3,
|
||||||
|
"subscription": null,
|
||||||
|
"type": "invoiceitem"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"has_more": false,
|
||||||
|
"object": "list",
|
||||||
|
"total_count": 3,
|
||||||
|
"url": "/v1/invoices/in_1DxdryGh0CmXqmnwqSArnOBA/lines"
|
||||||
|
},
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"next_payment_attempt": 1548699962,
|
||||||
|
"number": "81F7A21-0002",
|
||||||
|
"object": "invoice",
|
||||||
|
"paid": false,
|
||||||
|
"period_end": 1548696362,
|
||||||
|
"period_start": 1548696362,
|
||||||
|
"receipt_number": null,
|
||||||
|
"starting_balance": 0,
|
||||||
|
"statement_descriptor": "Zulip Standard",
|
||||||
|
"status": "open",
|
||||||
|
"subscription": null,
|
||||||
|
"subtotal": 96697,
|
||||||
|
"tax": 0,
|
||||||
|
"tax_percent": null,
|
||||||
|
"total": 96697,
|
||||||
|
"webhooks_delivered_at": 1548696362
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount_due": 0,
|
||||||
|
"amount_paid": 0,
|
||||||
|
"amount_remaining": 0,
|
||||||
|
"application_fee": null,
|
||||||
|
"attempt_count": 0,
|
||||||
|
"attempted": true,
|
||||||
|
"auto_advance": false,
|
||||||
|
"billing": "charge_automatically",
|
||||||
|
"billing_reason": "manual",
|
||||||
|
"charge": null,
|
||||||
|
"currency": "usd",
|
||||||
|
"custom_fields": null,
|
||||||
|
"customer": "cus_EQUrCdXCP2oqIF",
|
||||||
|
"date": 1548696360,
|
||||||
|
"default_source": null,
|
||||||
|
"description": "",
|
||||||
|
"discount": null,
|
||||||
|
"due_date": 1551288360,
|
||||||
|
"ending_balance": 0,
|
||||||
|
"finalized_at": 1548696360,
|
||||||
|
"footer": null,
|
||||||
|
"hosted_invoice_url": "https://pay.stripe.com/invoice/invst_QWWFlNhg4YyUdnWxVhUvuDs8TZ",
|
||||||
|
"id": "in_1DxdrwGh0CmXqmnw7x9G2rWd",
|
||||||
|
"invoice_pdf": "https://pay.stripe.com/invoice/invst_QWWFlNhg4YyUdnWxVhUvuDs8TZ/pdf",
|
||||||
|
"lines": {
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"amount": 64000,
|
||||||
|
"currency": "usd",
|
||||||
|
"description": "Zulip Standard",
|
||||||
|
"discountable": false,
|
||||||
|
"id": "ii_1DxdrvGh0CmXqmnwhHM5DcR1",
|
||||||
|
"invoice_item": "ii_1DxdrvGh0CmXqmnwhHM5DcR1",
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "line_item",
|
||||||
|
"period": {
|
||||||
|
"end": 1357095845,
|
||||||
|
"start": 1325473445
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 8,
|
||||||
|
"subscription": null,
|
||||||
|
"type": "invoiceitem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": -64000,
|
||||||
|
"currency": "usd",
|
||||||
|
"description": "Payment (Card ending in 4242)",
|
||||||
|
"discountable": false,
|
||||||
|
"id": "ii_1DxdrvGh0CmXqmnwg0R6ha8n",
|
||||||
|
"invoice_item": "ii_1DxdrvGh0CmXqmnwg0R6ha8n",
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "line_item",
|
||||||
|
"period": {
|
||||||
|
"end": 1548696359,
|
||||||
|
"start": 1548696359
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 1,
|
||||||
|
"subscription": null,
|
||||||
|
"type": "invoiceitem"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"has_more": false,
|
||||||
|
"object": "list",
|
||||||
|
"total_count": 2,
|
||||||
|
"url": "/v1/invoices/in_1DxdrwGh0CmXqmnw7x9G2rWd/lines"
|
||||||
|
},
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"next_payment_attempt": null,
|
||||||
|
"number": "81F7A21-0001",
|
||||||
|
"object": "invoice",
|
||||||
|
"paid": true,
|
||||||
|
"period_end": 1548696360,
|
||||||
|
"period_start": 1548696360,
|
||||||
|
"receipt_number": null,
|
||||||
|
"starting_balance": 0,
|
||||||
|
"statement_descriptor": "Zulip Standard",
|
||||||
|
"status": "paid",
|
||||||
|
"subscription": null,
|
||||||
|
"subtotal": 0,
|
||||||
|
"tax": 0,
|
||||||
|
"tax_percent": null,
|
||||||
|
"total": 0,
|
||||||
|
"webhooks_delivered_at": 1548696360
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"has_more": false,
|
||||||
|
"object": "list",
|
||||||
|
"url": "/v1/invoices"
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"amount": -64000,
|
||||||
|
"currency": "usd",
|
||||||
|
"customer": "cus_EQUrCdXCP2oqIF",
|
||||||
|
"date": 1548696359,
|
||||||
|
"description": "Payment (Card ending in 4242)",
|
||||||
|
"discountable": false,
|
||||||
|
"id": "ii_1DxdrvGh0CmXqmnwg0R6ha8n",
|
||||||
|
"invoice": null,
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "invoiceitem",
|
||||||
|
"period": {
|
||||||
|
"end": 1548696359,
|
||||||
|
"start": 1548696359
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 1,
|
||||||
|
"subscription": null,
|
||||||
|
"unit_amount": -64000
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"amount": 64000,
|
||||||
|
"currency": "usd",
|
||||||
|
"customer": "cus_EQUrCdXCP2oqIF",
|
||||||
|
"date": 1548696359,
|
||||||
|
"description": "Zulip Standard",
|
||||||
|
"discountable": false,
|
||||||
|
"id": "ii_1DxdrvGh0CmXqmnwhHM5DcR1",
|
||||||
|
"invoice": null,
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "invoiceitem",
|
||||||
|
"period": {
|
||||||
|
"end": 1357095845,
|
||||||
|
"start": 1325473445
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 8,
|
||||||
|
"subscription": null,
|
||||||
|
"unit_amount": 8000
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"amount": 17442,
|
||||||
|
"currency": "usd",
|
||||||
|
"customer": "cus_EQUrCdXCP2oqIF",
|
||||||
|
"date": 1548696361,
|
||||||
|
"description": "Additional license (Apr 11, 2012 - Jan 2, 2013)",
|
||||||
|
"discountable": false,
|
||||||
|
"id": "ii_1DxdrxGh0CmXqmnwSpeA2crG",
|
||||||
|
"invoice": null,
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "invoiceitem",
|
||||||
|
"period": {
|
||||||
|
"end": 1357095845,
|
||||||
|
"start": 1334113445
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 3,
|
||||||
|
"subscription": null,
|
||||||
|
"unit_amount": 5814
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"amount": 72000,
|
||||||
|
"currency": "usd",
|
||||||
|
"customer": "cus_EQUrCdXCP2oqIF",
|
||||||
|
"date": 1548696361,
|
||||||
|
"description": "Zulip Standard - renewal",
|
||||||
|
"discountable": false,
|
||||||
|
"id": "ii_1DxdrxGh0CmXqmnw183j11lw",
|
||||||
|
"invoice": null,
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "invoiceitem",
|
||||||
|
"period": {
|
||||||
|
"end": 1388631845,
|
||||||
|
"start": 1357095845
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 9,
|
||||||
|
"subscription": null,
|
||||||
|
"unit_amount": 8000
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"amount": 7255,
|
||||||
|
"currency": "usd",
|
||||||
|
"customer": "cus_EQUrCdXCP2oqIF",
|
||||||
|
"date": 1548696362,
|
||||||
|
"description": "Additional license (Feb 5, 2013 - Jan 2, 2014)",
|
||||||
|
"discountable": false,
|
||||||
|
"id": "ii_1DxdryGh0CmXqmnwXSzdImK3",
|
||||||
|
"invoice": null,
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "invoiceitem",
|
||||||
|
"period": {
|
||||||
|
"end": 1388631845,
|
||||||
|
"start": 1360033445
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 1,
|
||||||
|
"subscription": null,
|
||||||
|
"unit_amount": 7255
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"card": {
|
||||||
|
"address_city": "Pacific",
|
||||||
|
"address_country": "United States",
|
||||||
|
"address_line1": "Under the sea,",
|
||||||
|
"address_line1_check": "unchecked",
|
||||||
|
"address_line2": null,
|
||||||
|
"address_state": null,
|
||||||
|
"address_zip": "33333",
|
||||||
|
"address_zip_check": "unchecked",
|
||||||
|
"brand": "Visa",
|
||||||
|
"country": "US",
|
||||||
|
"cvc_check": "unchecked",
|
||||||
|
"dynamic_last4": null,
|
||||||
|
"exp_month": 3,
|
||||||
|
"exp_year": 2033,
|
||||||
|
"fingerprint": "6dAXT9VZvwro65EK",
|
||||||
|
"funding": "credit",
|
||||||
|
"id": "card_1DxdrtGh0CmXqmnw1LvZ0cL4",
|
||||||
|
"last4": "4242",
|
||||||
|
"metadata": {},
|
||||||
|
"name": "Ada Starr",
|
||||||
|
"object": "card",
|
||||||
|
"tokenization_method": null
|
||||||
|
},
|
||||||
|
"client_ip": "107.202.144.213",
|
||||||
|
"created": 1548696357,
|
||||||
|
"id": "tok_1DxdrtGh0CmXqmnw94EYeDen",
|
||||||
|
"livemode": false,
|
||||||
|
"object": "token",
|
||||||
|
"type": "card",
|
||||||
|
"used": false
|
||||||
|
}
|
||||||
78
corporate/tests/stripe_fixtures/renewal:Charge.create.1.json
Normal file
78
corporate/tests/stripe_fixtures/renewal:Charge.create.1.json
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
{
|
||||||
|
"amount": 64000,
|
||||||
|
"amount_refunded": 0,
|
||||||
|
"application": null,
|
||||||
|
"application_fee": null,
|
||||||
|
"application_fee_amount": null,
|
||||||
|
"balance_transaction": "txn_1DxdeSGh0CmXqmnw9I7ziL6D",
|
||||||
|
"captured": true,
|
||||||
|
"created": 1548695524,
|
||||||
|
"currency": "usd",
|
||||||
|
"customer": "cus_EQUd48LphR5ahk",
|
||||||
|
"description": "Upgrade to Zulip Standard, $80.0 x 8",
|
||||||
|
"destination": null,
|
||||||
|
"dispute": null,
|
||||||
|
"failure_code": null,
|
||||||
|
"failure_message": null,
|
||||||
|
"fraud_details": {},
|
||||||
|
"id": "ch_1DxdeSGh0CmXqmnwsw80Rn8n",
|
||||||
|
"invoice": null,
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "charge",
|
||||||
|
"on_behalf_of": null,
|
||||||
|
"order": null,
|
||||||
|
"outcome": {
|
||||||
|
"network_status": "approved_by_network",
|
||||||
|
"reason": null,
|
||||||
|
"risk_level": "normal",
|
||||||
|
"risk_score": 46,
|
||||||
|
"seller_message": "Payment complete.",
|
||||||
|
"type": "authorized"
|
||||||
|
},
|
||||||
|
"paid": true,
|
||||||
|
"payment_intent": null,
|
||||||
|
"receipt_email": "hamlet@zulip.com",
|
||||||
|
"receipt_number": null,
|
||||||
|
"receipt_url": "https://pay.stripe.com/receipts/acct_1BWYgHGh0CmXqmnw/ch_1DxdeSGh0CmXqmnwsw80Rn8n/rcpt_EQUda9O5I5cYpJL0yxiRbxnPbWZ415D",
|
||||||
|
"refunded": false,
|
||||||
|
"refunds": {
|
||||||
|
"data": [],
|
||||||
|
"has_more": false,
|
||||||
|
"object": "list",
|
||||||
|
"total_count": 0,
|
||||||
|
"url": "/v1/charges/ch_1DxdeSGh0CmXqmnwsw80Rn8n/refunds"
|
||||||
|
},
|
||||||
|
"review": null,
|
||||||
|
"shipping": null,
|
||||||
|
"source": {
|
||||||
|
"address_city": "Pacific",
|
||||||
|
"address_country": "United States",
|
||||||
|
"address_line1": "Under the sea,",
|
||||||
|
"address_line1_check": "pass",
|
||||||
|
"address_line2": null,
|
||||||
|
"address_state": null,
|
||||||
|
"address_zip": "33333",
|
||||||
|
"address_zip_check": "pass",
|
||||||
|
"brand": "Visa",
|
||||||
|
"country": "US",
|
||||||
|
"customer": "cus_EQUd48LphR5ahk",
|
||||||
|
"cvc_check": "pass",
|
||||||
|
"dynamic_last4": null,
|
||||||
|
"exp_month": 3,
|
||||||
|
"exp_year": 2033,
|
||||||
|
"fingerprint": "6dAXT9VZvwro65EK",
|
||||||
|
"funding": "credit",
|
||||||
|
"id": "card_1DxdeRGh0CmXqmnwu3BibWtM",
|
||||||
|
"last4": "4242",
|
||||||
|
"metadata": {},
|
||||||
|
"name": "Ada Starr",
|
||||||
|
"object": "card",
|
||||||
|
"tokenization_method": null
|
||||||
|
},
|
||||||
|
"source_transfer": null,
|
||||||
|
"statement_descriptor": "Zulip Standard",
|
||||||
|
"status": "succeeded",
|
||||||
|
"transfer_data": null,
|
||||||
|
"transfer_group": null
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
{
|
||||||
|
"account_balance": 0,
|
||||||
|
"created": 1548695523,
|
||||||
|
"currency": null,
|
||||||
|
"default_source": "card_1DxdeRGh0CmXqmnwu3BibWtM",
|
||||||
|
"delinquent": false,
|
||||||
|
"description": "zulip (Zulip Dev)",
|
||||||
|
"discount": null,
|
||||||
|
"email": "hamlet@zulip.com",
|
||||||
|
"id": "cus_EQUd48LphR5ahk",
|
||||||
|
"invoice_prefix": "9F53235",
|
||||||
|
"invoice_settings": {
|
||||||
|
"custom_fields": null,
|
||||||
|
"footer": null
|
||||||
|
},
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {
|
||||||
|
"realm_id": "1",
|
||||||
|
"realm_str": "zulip"
|
||||||
|
},
|
||||||
|
"object": "customer",
|
||||||
|
"shipping": null,
|
||||||
|
"sources": {
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"address_city": "Pacific",
|
||||||
|
"address_country": "United States",
|
||||||
|
"address_line1": "Under the sea,",
|
||||||
|
"address_line1_check": "pass",
|
||||||
|
"address_line2": null,
|
||||||
|
"address_state": null,
|
||||||
|
"address_zip": "33333",
|
||||||
|
"address_zip_check": "pass",
|
||||||
|
"brand": "Visa",
|
||||||
|
"country": "US",
|
||||||
|
"customer": "cus_EQUd48LphR5ahk",
|
||||||
|
"cvc_check": "pass",
|
||||||
|
"dynamic_last4": null,
|
||||||
|
"exp_month": 3,
|
||||||
|
"exp_year": 2033,
|
||||||
|
"fingerprint": "6dAXT9VZvwro65EK",
|
||||||
|
"funding": "credit",
|
||||||
|
"id": "card_1DxdeRGh0CmXqmnwu3BibWtM",
|
||||||
|
"last4": "4242",
|
||||||
|
"metadata": {},
|
||||||
|
"name": "Ada Starr",
|
||||||
|
"object": "card",
|
||||||
|
"tokenization_method": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"has_more": false,
|
||||||
|
"object": "list",
|
||||||
|
"total_count": 1,
|
||||||
|
"url": "/v1/customers/cus_EQUd48LphR5ahk/sources"
|
||||||
|
},
|
||||||
|
"subscriptions": {
|
||||||
|
"data": [],
|
||||||
|
"has_more": false,
|
||||||
|
"object": "list",
|
||||||
|
"total_count": 0,
|
||||||
|
"url": "/v1/customers/cus_EQUd48LphR5ahk/subscriptions"
|
||||||
|
},
|
||||||
|
"tax_info": null,
|
||||||
|
"tax_info_verification": null
|
||||||
|
}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
{
|
||||||
|
"amount_due": 0,
|
||||||
|
"amount_paid": 0,
|
||||||
|
"amount_remaining": 0,
|
||||||
|
"application_fee": null,
|
||||||
|
"attempt_count": 0,
|
||||||
|
"attempted": false,
|
||||||
|
"auto_advance": true,
|
||||||
|
"billing": "charge_automatically",
|
||||||
|
"billing_reason": "manual",
|
||||||
|
"charge": null,
|
||||||
|
"currency": "usd",
|
||||||
|
"custom_fields": null,
|
||||||
|
"customer": "cus_EQUd48LphR5ahk",
|
||||||
|
"date": 1548695526,
|
||||||
|
"default_source": null,
|
||||||
|
"description": "",
|
||||||
|
"discount": null,
|
||||||
|
"due_date": null,
|
||||||
|
"ending_balance": null,
|
||||||
|
"finalized_at": null,
|
||||||
|
"footer": null,
|
||||||
|
"hosted_invoice_url": null,
|
||||||
|
"id": "in_1DxdeUGh0CmXqmnwoowtAcQW",
|
||||||
|
"invoice_pdf": null,
|
||||||
|
"lines": {
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"amount": 64000,
|
||||||
|
"currency": "usd",
|
||||||
|
"description": "Zulip Standard",
|
||||||
|
"discountable": false,
|
||||||
|
"id": "ii_1DxdeTGh0CmXqmnw7MfZoBVx",
|
||||||
|
"invoice_item": "ii_1DxdeTGh0CmXqmnw7MfZoBVx",
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "line_item",
|
||||||
|
"period": {
|
||||||
|
"end": 1357095845,
|
||||||
|
"start": 1325473445
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 8,
|
||||||
|
"subscription": null,
|
||||||
|
"type": "invoiceitem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": -64000,
|
||||||
|
"currency": "usd",
|
||||||
|
"description": "Payment (Card ending in 4242)",
|
||||||
|
"discountable": false,
|
||||||
|
"id": "ii_1DxdeTGh0CmXqmnwDYYlalDE",
|
||||||
|
"invoice_item": "ii_1DxdeTGh0CmXqmnwDYYlalDE",
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "line_item",
|
||||||
|
"period": {
|
||||||
|
"end": 1548695525,
|
||||||
|
"start": 1548695525
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 1,
|
||||||
|
"subscription": null,
|
||||||
|
"type": "invoiceitem"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"has_more": false,
|
||||||
|
"object": "list",
|
||||||
|
"total_count": 2,
|
||||||
|
"url": "/v1/invoices/in_1DxdeUGh0CmXqmnwoowtAcQW/lines"
|
||||||
|
},
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"next_payment_attempt": 1548699126,
|
||||||
|
"number": "9F53235-0001",
|
||||||
|
"object": "invoice",
|
||||||
|
"paid": false,
|
||||||
|
"period_end": 1548695526,
|
||||||
|
"period_start": 1548695526,
|
||||||
|
"receipt_number": null,
|
||||||
|
"starting_balance": 0,
|
||||||
|
"statement_descriptor": "Zulip Standard",
|
||||||
|
"status": "draft",
|
||||||
|
"subscription": null,
|
||||||
|
"subtotal": 0,
|
||||||
|
"tax": 0,
|
||||||
|
"tax_percent": null,
|
||||||
|
"total": 0,
|
||||||
|
"webhooks_delivered_at": null
|
||||||
|
}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
{
|
||||||
|
"amount_due": 0,
|
||||||
|
"amount_paid": 0,
|
||||||
|
"amount_remaining": 0,
|
||||||
|
"application_fee": null,
|
||||||
|
"attempt_count": 0,
|
||||||
|
"attempted": true,
|
||||||
|
"auto_advance": false,
|
||||||
|
"billing": "charge_automatically",
|
||||||
|
"billing_reason": "manual",
|
||||||
|
"charge": null,
|
||||||
|
"currency": "usd",
|
||||||
|
"custom_fields": null,
|
||||||
|
"customer": "cus_EQUd48LphR5ahk",
|
||||||
|
"date": 1548695526,
|
||||||
|
"default_source": null,
|
||||||
|
"description": "",
|
||||||
|
"discount": null,
|
||||||
|
"due_date": 1551287527,
|
||||||
|
"ending_balance": 0,
|
||||||
|
"finalized_at": 1548695527,
|
||||||
|
"footer": null,
|
||||||
|
"hosted_invoice_url": "https://pay.stripe.com/invoice/invst_8N3Zw202aBfkZSHzyjUVcv9vrE",
|
||||||
|
"id": "in_1DxdeUGh0CmXqmnwoowtAcQW",
|
||||||
|
"invoice_pdf": "https://pay.stripe.com/invoice/invst_8N3Zw202aBfkZSHzyjUVcv9vrE/pdf",
|
||||||
|
"lines": {
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"amount": 64000,
|
||||||
|
"currency": "usd",
|
||||||
|
"description": "Zulip Standard",
|
||||||
|
"discountable": false,
|
||||||
|
"id": "ii_1DxdeTGh0CmXqmnw7MfZoBVx",
|
||||||
|
"invoice_item": "ii_1DxdeTGh0CmXqmnw7MfZoBVx",
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "line_item",
|
||||||
|
"period": {
|
||||||
|
"end": 1357095845,
|
||||||
|
"start": 1325473445
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 8,
|
||||||
|
"subscription": null,
|
||||||
|
"type": "invoiceitem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amount": -64000,
|
||||||
|
"currency": "usd",
|
||||||
|
"description": "Payment (Card ending in 4242)",
|
||||||
|
"discountable": false,
|
||||||
|
"id": "ii_1DxdeTGh0CmXqmnwDYYlalDE",
|
||||||
|
"invoice_item": "ii_1DxdeTGh0CmXqmnwDYYlalDE",
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "line_item",
|
||||||
|
"period": {
|
||||||
|
"end": 1548695525,
|
||||||
|
"start": 1548695525
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 1,
|
||||||
|
"subscription": null,
|
||||||
|
"type": "invoiceitem"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"has_more": false,
|
||||||
|
"object": "list",
|
||||||
|
"total_count": 2,
|
||||||
|
"url": "/v1/invoices/in_1DxdeUGh0CmXqmnwoowtAcQW/lines"
|
||||||
|
},
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"next_payment_attempt": null,
|
||||||
|
"number": "9F53235-0001",
|
||||||
|
"object": "invoice",
|
||||||
|
"paid": true,
|
||||||
|
"period_end": 1548695526,
|
||||||
|
"period_start": 1548695526,
|
||||||
|
"receipt_number": null,
|
||||||
|
"starting_balance": 0,
|
||||||
|
"statement_descriptor": "Zulip Standard",
|
||||||
|
"status": "paid",
|
||||||
|
"subscription": null,
|
||||||
|
"subtotal": 0,
|
||||||
|
"tax": 0,
|
||||||
|
"tax_percent": null,
|
||||||
|
"total": 0,
|
||||||
|
"webhooks_delivered_at": 1548695526
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"amount": -64000,
|
||||||
|
"currency": "usd",
|
||||||
|
"customer": "cus_EQUd48LphR5ahk",
|
||||||
|
"date": 1548695525,
|
||||||
|
"description": "Payment (Card ending in 4242)",
|
||||||
|
"discountable": false,
|
||||||
|
"id": "ii_1DxdeTGh0CmXqmnwDYYlalDE",
|
||||||
|
"invoice": null,
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "invoiceitem",
|
||||||
|
"period": {
|
||||||
|
"end": 1548695525,
|
||||||
|
"start": 1548695525
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 1,
|
||||||
|
"subscription": null,
|
||||||
|
"unit_amount": -64000
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"amount": 64000,
|
||||||
|
"currency": "usd",
|
||||||
|
"customer": "cus_EQUd48LphR5ahk",
|
||||||
|
"date": 1548695525,
|
||||||
|
"description": "Zulip Standard",
|
||||||
|
"discountable": false,
|
||||||
|
"id": "ii_1DxdeTGh0CmXqmnw7MfZoBVx",
|
||||||
|
"invoice": null,
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "invoiceitem",
|
||||||
|
"period": {
|
||||||
|
"end": 1357095845,
|
||||||
|
"start": 1325473445
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 8,
|
||||||
|
"subscription": null,
|
||||||
|
"unit_amount": 8000
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"amount": 17442,
|
||||||
|
"currency": "usd",
|
||||||
|
"customer": "cus_EQUd48LphR5ahk",
|
||||||
|
"date": 1548695527,
|
||||||
|
"description": "Additional license (Apr 11, 2012 - Jan 2, 2013)",
|
||||||
|
"discountable": false,
|
||||||
|
"id": "ii_1DxdeVGh0CmXqmnwf6cLlEA7",
|
||||||
|
"invoice": null,
|
||||||
|
"livemode": false,
|
||||||
|
"metadata": {},
|
||||||
|
"object": "invoiceitem",
|
||||||
|
"period": {
|
||||||
|
"end": 1357095845,
|
||||||
|
"start": 1334113445
|
||||||
|
},
|
||||||
|
"plan": null,
|
||||||
|
"proration": false,
|
||||||
|
"quantity": 3,
|
||||||
|
"subscription": null,
|
||||||
|
"unit_amount": 5814
|
||||||
|
}
|
||||||
33
corporate/tests/stripe_fixtures/renewal:Token.create.1.json
Normal file
33
corporate/tests/stripe_fixtures/renewal:Token.create.1.json
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"card": {
|
||||||
|
"address_city": "Pacific",
|
||||||
|
"address_country": "United States",
|
||||||
|
"address_line1": "Under the sea,",
|
||||||
|
"address_line1_check": "unchecked",
|
||||||
|
"address_line2": null,
|
||||||
|
"address_state": null,
|
||||||
|
"address_zip": "33333",
|
||||||
|
"address_zip_check": "unchecked",
|
||||||
|
"brand": "Visa",
|
||||||
|
"country": "US",
|
||||||
|
"cvc_check": "unchecked",
|
||||||
|
"dynamic_last4": null,
|
||||||
|
"exp_month": 3,
|
||||||
|
"exp_year": 2033,
|
||||||
|
"fingerprint": "6dAXT9VZvwro65EK",
|
||||||
|
"funding": "credit",
|
||||||
|
"id": "card_1DxdeRGh0CmXqmnwu3BibWtM",
|
||||||
|
"last4": "4242",
|
||||||
|
"metadata": {},
|
||||||
|
"name": "Ada Starr",
|
||||||
|
"object": "card",
|
||||||
|
"tokenization_method": null
|
||||||
|
},
|
||||||
|
"client_ip": "107.202.144.213",
|
||||||
|
"created": 1548695523,
|
||||||
|
"id": "tok_1DxdeRGh0CmXqmnw5X6CeYnC",
|
||||||
|
"livemode": false,
|
||||||
|
"object": "token",
|
||||||
|
"type": "card",
|
||||||
|
"used": false
|
||||||
|
}
|
||||||
@@ -30,7 +30,8 @@ from corporate.lib.stripe import catch_stripe_errors, attach_discount_to_realm,
|
|||||||
add_months, next_month, next_renewal_date, renewal_amount, \
|
add_months, next_month, next_renewal_date, renewal_amount, \
|
||||||
compute_plan_parameters, update_or_create_stripe_customer, \
|
compute_plan_parameters, update_or_create_stripe_customer, \
|
||||||
process_initial_upgrade, add_plan_renewal_to_license_ledger_if_needed, \
|
process_initial_upgrade, add_plan_renewal_to_license_ledger_if_needed, \
|
||||||
update_license_ledger_if_needed, update_license_ledger_for_automanaged_plan
|
update_license_ledger_if_needed, update_license_ledger_for_automanaged_plan, \
|
||||||
|
invoice_plan, invoice_plans_as_needed
|
||||||
from corporate.models import Customer, CustomerPlan, LicenseLedger
|
from corporate.models import Customer, CustomerPlan, LicenseLedger
|
||||||
from corporate.views import payment_method_string
|
from corporate.views import payment_method_string
|
||||||
import corporate.urls
|
import corporate.urls
|
||||||
@@ -1027,3 +1028,127 @@ class LicenseLedgerTest(StripeTestCase):
|
|||||||
(False, self.seat_count + 1, self.seat_count),
|
(False, self.seat_count + 1, self.seat_count),
|
||||||
(False, self.seat_count + 1, self.seat_count + 1),
|
(False, self.seat_count + 1, self.seat_count + 1),
|
||||||
(False, self.seat_count + 1, self.seat_count + 1)])
|
(False, self.seat_count + 1, self.seat_count + 1)])
|
||||||
|
|
||||||
|
class InvoiceTest(StripeTestCase):
|
||||||
|
def test_invoicing_status_is_started(self) -> None:
|
||||||
|
self.local_upgrade(self.seat_count, True, CustomerPlan.ANNUAL, 'token')
|
||||||
|
plan = CustomerPlan.objects.first()
|
||||||
|
plan.invoicing_status = CustomerPlan.STARTED
|
||||||
|
plan.save(update_fields=['invoicing_status'])
|
||||||
|
with self.assertRaises(NotImplementedError):
|
||||||
|
invoice_plan(CustomerPlan.objects.first(), self.now)
|
||||||
|
|
||||||
|
@mock_stripe()
|
||||||
|
def test_invoice_plan(self, *mocks: Mock) -> None:
|
||||||
|
user = self.example_user("hamlet")
|
||||||
|
self.login(user.email)
|
||||||
|
with patch('corporate.lib.stripe.timezone_now', return_value=self.now):
|
||||||
|
self.upgrade()
|
||||||
|
# Increase
|
||||||
|
with patch('corporate.lib.stripe.get_seat_count', return_value=self.seat_count + 3):
|
||||||
|
update_license_ledger_if_needed(get_realm('zulip'), self.now + timedelta(days=100))
|
||||||
|
# Decrease
|
||||||
|
with patch('corporate.lib.stripe.get_seat_count', return_value=self.seat_count):
|
||||||
|
update_license_ledger_if_needed(get_realm('zulip'), self.now + timedelta(days=200))
|
||||||
|
# Increase, but not past high watermark
|
||||||
|
with patch('corporate.lib.stripe.get_seat_count', return_value=self.seat_count + 1):
|
||||||
|
update_license_ledger_if_needed(get_realm('zulip'), self.now + timedelta(days=300))
|
||||||
|
# Increase, but after renewal date, and below last year's high watermark
|
||||||
|
with patch('corporate.lib.stripe.get_seat_count', return_value=self.seat_count + 2):
|
||||||
|
update_license_ledger_if_needed(get_realm('zulip'), self.now + timedelta(days=400))
|
||||||
|
# Increase, but after event_time
|
||||||
|
with patch('corporate.lib.stripe.get_seat_count', return_value=self.seat_count + 3):
|
||||||
|
update_license_ledger_if_needed(get_realm('zulip'), self.now + timedelta(days=500))
|
||||||
|
plan = CustomerPlan.objects.first()
|
||||||
|
invoice_plan(plan, self.now + timedelta(days=400))
|
||||||
|
|
||||||
|
stripe_invoices = [invoice for invoice in stripe.Invoice.list(
|
||||||
|
customer=plan.customer.stripe_customer_id)]
|
||||||
|
self.assertEqual(len(stripe_invoices), 2)
|
||||||
|
self.assertIsNotNone(stripe_invoices[0].finalized_at)
|
||||||
|
stripe_line_items = [item for item in stripe_invoices[0].lines]
|
||||||
|
self.assertEqual(len(stripe_line_items), 3)
|
||||||
|
line_item_params = {
|
||||||
|
'amount': int(8000 * (1 - ((400-366) / 365)) + .5),
|
||||||
|
'description': 'Additional license (Feb 5, 2013 - Jan 2, 2014)',
|
||||||
|
'discountable': False,
|
||||||
|
'period': {
|
||||||
|
'start': datetime_to_timestamp(self.now + timedelta(days=400)),
|
||||||
|
'end': datetime_to_timestamp(self.now + timedelta(days=2*365 + 1))},
|
||||||
|
'quantity': 1}
|
||||||
|
for key, value in line_item_params.items():
|
||||||
|
self.assertEqual(stripe_line_items[0].get(key), value)
|
||||||
|
line_item_params = {
|
||||||
|
'amount': 8000 * (self.seat_count + 1),
|
||||||
|
'description': 'Zulip Standard - renewal',
|
||||||
|
'discountable': False,
|
||||||
|
'period': {
|
||||||
|
'start': datetime_to_timestamp(self.now + timedelta(days=366)),
|
||||||
|
'end': datetime_to_timestamp(self.now + timedelta(days=2*365 + 1))},
|
||||||
|
'quantity': (self.seat_count + 1)}
|
||||||
|
for key, value in line_item_params.items():
|
||||||
|
self.assertEqual(stripe_line_items[1].get(key), value)
|
||||||
|
line_item_params = {
|
||||||
|
'amount': 3 * int(8000 * (366-100) / 366 + .5),
|
||||||
|
'description': 'Additional license (Apr 11, 2012 - Jan 2, 2013)',
|
||||||
|
'discountable': False,
|
||||||
|
'period': {
|
||||||
|
'start': datetime_to_timestamp(self.now + timedelta(days=100)),
|
||||||
|
'end': datetime_to_timestamp(self.now + timedelta(days=366))},
|
||||||
|
'quantity': 3}
|
||||||
|
for key, value in line_item_params.items():
|
||||||
|
self.assertEqual(stripe_line_items[2].get(key), value)
|
||||||
|
|
||||||
|
@mock_stripe()
|
||||||
|
def test_fixed_price_plans(self, *mocks: Mock) -> None:
|
||||||
|
# Also tests charge_automatically=False
|
||||||
|
user = self.example_user("hamlet")
|
||||||
|
self.login(user.email)
|
||||||
|
with patch('corporate.lib.stripe.timezone_now', return_value=self.now):
|
||||||
|
self.upgrade(invoice=True)
|
||||||
|
plan = CustomerPlan.objects.first()
|
||||||
|
plan.fixed_price = 100
|
||||||
|
plan.price_per_license = 0
|
||||||
|
plan.save(update_fields=['fixed_price', 'price_per_license'])
|
||||||
|
invoice_plan(plan, self.next_year)
|
||||||
|
stripe_invoices = [invoice for invoice in stripe.Invoice.list(
|
||||||
|
customer=plan.customer.stripe_customer_id)]
|
||||||
|
self.assertEqual(len(stripe_invoices), 2)
|
||||||
|
self.assertEqual(stripe_invoices[0].billing, 'send_invoice')
|
||||||
|
stripe_line_items = [item for item in stripe_invoices[0].lines]
|
||||||
|
self.assertEqual(len(stripe_line_items), 1)
|
||||||
|
line_item_params = {
|
||||||
|
'amount': 100,
|
||||||
|
'description': 'Zulip Standard - renewal',
|
||||||
|
'discountable': False,
|
||||||
|
'period': {
|
||||||
|
'start': datetime_to_timestamp(self.next_year),
|
||||||
|
'end': datetime_to_timestamp(self.next_year + timedelta(days=365))},
|
||||||
|
'quantity': 1}
|
||||||
|
for key, value in line_item_params.items():
|
||||||
|
self.assertEqual(stripe_line_items[0].get(key), value)
|
||||||
|
|
||||||
|
def test_no_invoice_needed(self) -> None:
|
||||||
|
with patch('corporate.lib.stripe.timezone_now', return_value=self.now):
|
||||||
|
self.local_upgrade(self.seat_count, True, CustomerPlan.ANNUAL, 'token')
|
||||||
|
plan = CustomerPlan.objects.first()
|
||||||
|
self.assertEqual(plan.next_invoice_date, self.next_month)
|
||||||
|
# Test this doesn't make any calls to stripe.Invoice or stripe.InvoiceItem
|
||||||
|
invoice_plan(plan, self.next_month)
|
||||||
|
plan = CustomerPlan.objects.first()
|
||||||
|
# Test that we still update next_invoice_date
|
||||||
|
self.assertEqual(plan.next_invoice_date, self.next_month + timedelta(days=29))
|
||||||
|
|
||||||
|
def test_invoice_plans_as_needed(self) -> None:
|
||||||
|
with patch('corporate.lib.stripe.timezone_now', return_value=self.now):
|
||||||
|
self.local_upgrade(self.seat_count, True, CustomerPlan.ANNUAL, 'token')
|
||||||
|
plan = CustomerPlan.objects.first()
|
||||||
|
self.assertEqual(plan.next_invoice_date, self.next_month)
|
||||||
|
# Test nothing needed to be done
|
||||||
|
with patch('corporate.lib.stripe.invoice_plan') as mocked:
|
||||||
|
invoice_plans_as_needed(self.next_month - timedelta(days=1))
|
||||||
|
mocked.assert_not_called()
|
||||||
|
# Test something needing to be done
|
||||||
|
invoice_plans_as_needed(self.next_month)
|
||||||
|
plan = CustomerPlan.objects.first()
|
||||||
|
self.assertEqual(plan.next_invoice_date, self.next_month + timedelta(days=29))
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ class InvoiceItem:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def create(amount: int=..., currency: str=..., customer: str=..., description: str=...,
|
def create(amount: int=..., currency: str=..., customer: str=..., description: str=...,
|
||||||
discountable: bool=..., period: Dict[str, int]=..., quantity: int=...,
|
discountable: bool=..., period: Dict[str, int]=..., quantity: int=...,
|
||||||
unit_amount: int=...) -> InvoiceItem:
|
unit_amount: int=..., idempotency_key: str=...) -> InvoiceItem:
|
||||||
...
|
...
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|||||||
Reference in New Issue
Block a user