diff --git a/analytics/views/support.py b/analytics/views/support.py index 43d29aea51..7225a768b8 100644 --- a/analytics/views/support.py +++ b/analytics/views/support.py @@ -56,13 +56,13 @@ if settings.BILLING_ENABLED: from corporate.lib.stripe import ( RealmBillingSession, get_latest_seat_count, - switch_realm_from_standard_to_plus_plan, void_all_open_invoices, ) from corporate.lib.support import ( approve_realm_sponsorship, attach_discount_to_realm, get_discount_for_realm, + switch_realm_from_standard_to_plus_plan, update_realm_billing_method, update_realm_sponsorship_status, ) diff --git a/corporate/lib/stripe.py b/corporate/lib/stripe.py index d5fcf3414e..9d55130fed 100644 --- a/corporate/lib/stripe.py +++ b/corporate/lib/stripe.py @@ -616,6 +616,10 @@ class BillingSession(ABC): ) -> UpgradePageSessionTypeSpecificContext: pass + @abstractmethod + def is_valid_plan_tier_switch(self, current_plan_tier: int, new_plan_tier: int) -> bool: + pass + @catch_stripe_errors def create_stripe_customer(self) -> Customer: stripe_customer_data = self.get_data_for_stripe_customer() @@ -1434,6 +1438,86 @@ class BillingSession(ABC): raise JsonableError(_("Nothing to change.")) + def switch_plan_tier(self, current_plan: CustomerPlan, new_plan_tier: int) -> None: + assert current_plan.status == CustomerPlan.SWITCH_PLAN_TIER_NOW + assert current_plan.next_invoice_date is not None + next_billing_cycle = current_plan.next_invoice_date + + current_plan.end_date = next_billing_cycle + current_plan.status = CustomerPlan.ENDED + current_plan.save(update_fields=["status", "end_date"]) + + new_price_per_license = get_price_per_license( + new_plan_tier, current_plan.billing_schedule, current_plan.customer.default_discount + ) + + new_plan_billing_cycle_anchor = current_plan.end_date.replace(microsecond=0) + + new_plan = CustomerPlan.objects.create( + customer=current_plan.customer, + status=CustomerPlan.ACTIVE, + automanage_licenses=current_plan.automanage_licenses, + charge_automatically=current_plan.charge_automatically, + price_per_license=new_price_per_license, + discount=current_plan.customer.default_discount, + billing_schedule=current_plan.billing_schedule, + tier=new_plan_tier, + billing_cycle_anchor=new_plan_billing_cycle_anchor, + invoicing_status=CustomerPlan.INITIAL_INVOICE_TO_BE_SENT, + next_invoice_date=new_plan_billing_cycle_anchor, + ) + + current_plan_last_ledger = ( + LicenseLedger.objects.filter(plan=current_plan).order_by("id").last() + ) + assert current_plan_last_ledger is not None + licenses_for_new_plan = current_plan_last_ledger.licenses_at_next_renewal + assert licenses_for_new_plan is not None + LicenseLedger.objects.create( + plan=new_plan, + is_renewal=True, + event_time=new_plan_billing_cycle_anchor, + licenses=licenses_for_new_plan, + licenses_at_next_renewal=licenses_for_new_plan, + ) + + def do_change_plan_to_new_tier(self, new_plan_tier: int) -> None: + customer = self.get_customer() + assert customer is not None + current_plan = get_current_plan_by_customer(customer) + + if not current_plan or current_plan.status != CustomerPlan.ACTIVE: + raise BillingError("Organization does not have an active plan") + + if not current_plan.customer.stripe_customer_id: + raise BillingError("Organization missing Stripe customer.") + + if not self.is_valid_plan_tier_switch(current_plan.tier, new_plan_tier): + raise BillingError("Invalid change of customer plan tier.") + + plan_switch_time = timezone_now() + + current_plan.status = CustomerPlan.SWITCH_PLAN_TIER_NOW + current_plan.next_invoice_date = plan_switch_time + current_plan.save(update_fields=["status", "next_invoice_date"]) + + self.do_change_plan_type(tier=new_plan_tier) + + amount_to_credit_for_early_termination = get_amount_to_credit_for_plan_tier_change( + current_plan, plan_switch_time + ) + stripe.Customer.create_balance_transaction( + current_plan.customer.stripe_customer_id, + amount=-1 * amount_to_credit_for_early_termination, + currency="usd", + description="Credit from early termination of active plan", + ) + self.switch_plan_tier(current_plan, new_plan_tier) + invoice_plan(current_plan, plan_switch_time) + new_plan = get_current_plan_by_customer(customer) + assert new_plan is not None # for mypy + invoice_plan(new_plan, plan_switch_time) + class RealmBillingSession(BillingSession): def __init__( @@ -1666,6 +1750,14 @@ class RealmBillingSession(BillingSession): is_self_hosting=False, ) + @override + def is_valid_plan_tier_switch(self, current_plan_tier: int, new_plan_tier: int) -> bool: + if current_plan_tier == CustomerPlan.STANDARD: + return new_plan_tier == CustomerPlan.PLUS + else: # nocoverage, not currently implemented + assert current_plan_tier == CustomerPlan.PLUS + return new_plan_tier == CustomerPlan.STANDARD + class RemoteRealmBillingSession(BillingSession): # nocoverage def __init__( @@ -1854,6 +1946,11 @@ class RemoteRealmBillingSession(BillingSession): # nocoverage plan.status = CustomerPlan.ENDED plan.save(update_fields=["status"]) + @override + def is_valid_plan_tier_switch(self, current_plan_tier: int, new_plan_tier: int) -> bool: + # TBD + return False + class RemoteServerBillingSession(BillingSession): # nocoverage """Billing session for pre-8.0 servers that do not yet support @@ -2035,6 +2132,11 @@ class RemoteServerBillingSession(BillingSession): # nocoverage is_self_hosting=True, ) + @override + def is_valid_plan_tier_switch(self, current_plan_tier: int, new_plan_tier: int) -> bool: + # TBD + return False + def stripe_customer_has_credit_card_as_default_payment_method( stripe_customer: stripe.Customer, @@ -2449,86 +2551,3 @@ def downgrade_small_realms_behind_on_payments_as_needed() -> None: else: if customer_has_last_n_invoices_open(customer, 1): void_all_open_invoices(realm) - - -def switch_plan_tier(current_plan: CustomerPlan, new_plan_tier: int) -> None: - assert current_plan.status == CustomerPlan.SWITCH_PLAN_TIER_NOW - assert current_plan.next_invoice_date is not None - next_billing_cycle = current_plan.next_invoice_date - - # TODO: When moved to BillingSession, create child class validation - # for valid CustomerPlan tier changes. - assert current_plan.tier != new_plan_tier - assert current_plan.tier == CustomerPlan.STANDARD - assert new_plan_tier == CustomerPlan.PLUS - - current_plan.end_date = next_billing_cycle - current_plan.status = CustomerPlan.ENDED - current_plan.save(update_fields=["status", "end_date"]) - - new_price_per_license = get_price_per_license( - new_plan_tier, current_plan.billing_schedule, current_plan.customer.default_discount - ) - - new_plan_billing_cycle_anchor = current_plan.end_date.replace(microsecond=0) - - new_plan = CustomerPlan.objects.create( - customer=current_plan.customer, - status=CustomerPlan.ACTIVE, - automanage_licenses=current_plan.automanage_licenses, - charge_automatically=current_plan.charge_automatically, - price_per_license=new_price_per_license, - discount=current_plan.customer.default_discount, - billing_schedule=current_plan.billing_schedule, - tier=new_plan_tier, - billing_cycle_anchor=new_plan_billing_cycle_anchor, - invoicing_status=CustomerPlan.INITIAL_INVOICE_TO_BE_SENT, - next_invoice_date=new_plan_billing_cycle_anchor, - ) - - current_plan_last_ledger = LicenseLedger.objects.filter(plan=current_plan).order_by("id").last() - assert current_plan_last_ledger is not None - licenses_for_new_plan = current_plan_last_ledger.licenses_at_next_renewal - assert licenses_for_new_plan is not None - LicenseLedger.objects.create( - plan=new_plan, - is_renewal=True, - event_time=new_plan_billing_cycle_anchor, - licenses=licenses_for_new_plan, - licenses_at_next_renewal=licenses_for_new_plan, - ) - - -def switch_realm_from_standard_to_plus_plan(realm: Realm) -> None: - standard_plan = get_current_plan_by_realm(realm) - - if not standard_plan or standard_plan.status != CustomerPlan.ACTIVE: - raise BillingError("Organization does not have an active plan") - - if not standard_plan.customer.stripe_customer_id: - raise BillingError("Organization missing Stripe customer.") - - plan_switch_time = timezone_now() - - standard_plan.status = CustomerPlan.SWITCH_PLAN_TIER_NOW - standard_plan.next_invoice_date = plan_switch_time - standard_plan.save(update_fields=["status", "next_invoice_date"]) - - from zerver.actions.realm_settings import do_change_realm_plan_type - - do_change_realm_plan_type(realm, Realm.PLAN_TYPE_PLUS, acting_user=None) - - amount_to_credit_back_to_realm = get_amount_to_credit_for_plan_tier_change( - standard_plan, plan_switch_time - ) - stripe.Customer.create_balance_transaction( - standard_plan.customer.stripe_customer_id, - amount=-1 * amount_to_credit_back_to_realm, - currency="usd", - description="Credit from early termination of active plan", - ) - switch_plan_tier(standard_plan, CustomerPlan.PLUS) - invoice_plan(standard_plan, plan_switch_time) - plus_plan = get_current_plan_by_realm(realm) - assert plus_plan is not None # for mypy - invoice_plan(plus_plan, plan_switch_time) diff --git a/corporate/lib/support.py b/corporate/lib/support.py index 087eb37b19..d4ce653b70 100644 --- a/corporate/lib/support.py +++ b/corporate/lib/support.py @@ -6,7 +6,7 @@ from django.conf import settings from django.urls import reverse from corporate.lib.stripe import RealmBillingSession -from corporate.models import get_customer_by_realm +from corporate.models import CustomerPlan, get_customer_by_realm from zerver.models import Realm, UserProfile, get_realm @@ -48,3 +48,8 @@ def update_realm_billing_method( ) -> None: billing_session = RealmBillingSession(acting_user, realm, support_session=True) billing_session.update_billing_method_of_current_plan(charge_automatically) + + +def switch_realm_from_standard_to_plus_plan(realm: Realm) -> None: + billing_session = RealmBillingSession(realm=realm) + billing_session.do_change_plan_to_new_tier(new_plan_tier=CustomerPlan.PLUS) diff --git a/corporate/tests/stripe_fixtures/change_plan_tier_from_standard_to_plus--Customer.create.1.json b/corporate/tests/stripe_fixtures/change_plan_tier_from_standard_to_plus--Customer.create.1.json new file mode 100644 index 0000000000..d5466efbf5 --- /dev/null +++ b/corporate/tests/stripe_fixtures/change_plan_tier_from_standard_to_plus--Customer.create.1.json @@ -0,0 +1,33 @@ +{ + "address": null, + "balance": 0, + "created": 1000000000, + "currency": null, + "default_currency": null, + "default_source": null, + "delinquent": false, + "description": "lear (Lear & Co.)", + "discount": null, + "email": "king@lear.org", + "id": "cus_NORMALIZED0001", + "invoice_prefix": "NORMA01", + "invoice_settings": { + "custom_fields": null, + "default_payment_method": null, + "footer": null, + "rendering_options": null + }, + "livemode": false, + "metadata": { + "realm_id": "1", + "realm_str": "lear" + }, + "name": null, + "next_invoice_sequence": 1, + "object": "customer", + "phone": null, + "preferred_locales": [], + "shipping": null, + "tax_exempt": "none", + "test_clock": null +} diff --git a/corporate/tests/stripe_fixtures/change_plan_tier_from_standard_to_plus--Customer.create_balance_transaction.1.json b/corporate/tests/stripe_fixtures/change_plan_tier_from_standard_to_plus--Customer.create_balance_transaction.1.json new file mode 100644 index 0000000000..8617999fcf --- /dev/null +++ b/corporate/tests/stripe_fixtures/change_plan_tier_from_standard_to_plus--Customer.create_balance_transaction.1.json @@ -0,0 +1,15 @@ +{ + "amount": -7200, + "created": 1000000000, + "credit_note": null, + "currency": "usd", + "customer": "cus_NORMALIZED0001", + "description": "Credit from early termination of active plan", + "ending_balance": -7200, + "id": "cbtxn_NORMALIZED00000000000001", + "invoice": null, + "livemode": false, + "metadata": {}, + "object": "customer_balance_transaction", + "type": "adjustment" +} diff --git a/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Customer.list_balance_transactions.1.json b/corporate/tests/stripe_fixtures/change_plan_tier_from_standard_to_plus--Customer.list_balance_transactions.1.json similarity index 100% rename from corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Customer.list_balance_transactions.1.json rename to corporate/tests/stripe_fixtures/change_plan_tier_from_standard_to_plus--Customer.list_balance_transactions.1.json diff --git a/corporate/tests/stripe_fixtures/change_plan_tier_from_standard_to_plus--Invoice.create.1.json b/corporate/tests/stripe_fixtures/change_plan_tier_from_standard_to_plus--Invoice.create.1.json new file mode 100644 index 0000000000..018781b959 --- /dev/null +++ b/corporate/tests/stripe_fixtures/change_plan_tier_from_standard_to_plus--Invoice.create.1.json @@ -0,0 +1,158 @@ +{ + "account_country": "US", + "account_name": "Kandra Labs, Inc.", + "account_tax_ids": null, + "amount_due": 7200, + "amount_paid": 0, + "amount_remaining": 7200, + "amount_shipping": 0, + "application": null, + "application_fee_amount": null, + "attempt_count": 0, + "attempted": false, + "auto_advance": true, + "automatic_tax": { + "enabled": false, + "status": null + }, + "billing_reason": "manual", + "charge": null, + "collection_method": "send_invoice", + "created": 1000000000, + "currency": "usd", + "custom_fields": null, + "customer": "cus_NORMALIZED0001", + "customer_address": null, + "customer_email": "king@lear.org", + "customer_name": null, + "customer_phone": null, + "customer_shipping": null, + "customer_tax_exempt": "none", + "customer_tax_ids": [], + "default_payment_method": null, + "default_source": null, + "default_tax_rates": [], + "description": null, + "discount": null, + "discounts": [], + "due_date": 1000000000, + "effective_at": null, + "ending_balance": null, + "footer": null, + "from_invoice": null, + "hosted_invoice_url": null, + "id": "in_NORMALIZED00000000000001", + "invoice_pdf": null, + "last_finalization_error": null, + "latest_revision": null, + "lines": { + "data": [ + { + "amount": 14400, + "amount_excluding_tax": 14400, + "currency": "usd", + "description": "Zulip Plus - renewal", + "discount_amounts": [], + "discountable": false, + "discounts": [], + "id": "il_NORMALIZED00000000000001", + "invoice_item": "ii_NORMALIZED00000000000001", + "livemode": false, + "metadata": {}, + "object": "line_item", + "period": { + "end": 1000000000, + "start": 1000000000 + }, + "plan": null, + "price": { + "active": false, + "billing_scheme": "per_unit", + "created": 1000000000, + "currency": "usd", + "custom_unit_amount": null, + "id": "price_NORMALIZED00000000000001", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_NORMALIZED0001", + "recurring": null, + "tax_behavior": "unspecified", + "tiers_mode": null, + "transform_quantity": null, + "type": "one_time", + "unit_amount": 1600, + "unit_amount_decimal": "1600" + }, + "proration": false, + "proration_details": { + "credited_items": null + }, + "quantity": 9, + "subscription": null, + "tax_amounts": [], + "tax_rates": [], + "type": "invoiceitem", + "unit_amount_excluding_tax": "1600" + } + ], + "has_more": false, + "object": "list", + "total_count": 1, + "url": "/v1/invoices/in_NORMALIZED00000000000001/lines" + }, + "livemode": false, + "metadata": {}, + "next_payment_attempt": null, + "number": null, + "object": "invoice", + "on_behalf_of": null, + "paid": false, + "paid_out_of_band": false, + "payment_intent": null, + "payment_settings": { + "default_mandate": null, + "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, + "quote": null, + "receipt_number": null, + "rendering": { + "amount_tax_display": null, + "pdf": { + "page_size": "auto" + } + }, + "rendering_options": null, + "shipping_cost": null, + "shipping_details": null, + "starting_balance": -7200, + "statement_descriptor": "Zulip Plus", + "status": "draft", + "status_transitions": { + "finalized_at": null, + "marked_uncollectible_at": null, + "paid_at": null, + "voided_at": null + }, + "subscription": null, + "subscription_details": { + "metadata": null + }, + "subtotal": 14400, + "subtotal_excluding_tax": 14400, + "tax": null, + "test_clock": null, + "total": 14400, + "total_discount_amounts": [], + "total_excluding_tax": 14400, + "total_tax_amounts": [], + "transfer_data": null, + "webhooks_delivered_at": null +} diff --git a/corporate/tests/stripe_fixtures/change_plan_tier_from_standard_to_plus--Invoice.finalize_invoice.1.json b/corporate/tests/stripe_fixtures/change_plan_tier_from_standard_to_plus--Invoice.finalize_invoice.1.json new file mode 100644 index 0000000000..c496fa4780 --- /dev/null +++ b/corporate/tests/stripe_fixtures/change_plan_tier_from_standard_to_plus--Invoice.finalize_invoice.1.json @@ -0,0 +1,158 @@ +{ + "account_country": "US", + "account_name": "Kandra Labs, Inc.", + "account_tax_ids": null, + "amount_due": 7200, + "amount_paid": 0, + "amount_remaining": 7200, + "amount_shipping": 0, + "application": null, + "application_fee_amount": null, + "attempt_count": 0, + "attempted": false, + "auto_advance": true, + "automatic_tax": { + "enabled": false, + "status": null + }, + "billing_reason": "manual", + "charge": null, + "collection_method": "send_invoice", + "created": 1000000000, + "currency": "usd", + "custom_fields": null, + "customer": "cus_NORMALIZED0001", + "customer_address": null, + "customer_email": "king@lear.org", + "customer_name": null, + "customer_phone": null, + "customer_shipping": null, + "customer_tax_exempt": "none", + "customer_tax_ids": [], + "default_payment_method": null, + "default_source": null, + "default_tax_rates": [], + "description": null, + "discount": null, + "discounts": [], + "due_date": 1000000000, + "effective_at": 1000000000, + "ending_balance": 0, + "footer": null, + "from_invoice": null, + "hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QM2RWVEFzekZPQzhpS2pLRUUwdUtHZFdYSFR6elVuLDkxMjYxMDk50200glANUnat?s=ap", + "id": "in_NORMALIZED00000000000001", + "invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QM2RWVEFzekZPQzhpS2pLRUUwdUtHZFdYSFR6elVuLDkxMjYxMDk50200glANUnat/pdf?s=ap", + "last_finalization_error": null, + "latest_revision": null, + "lines": { + "data": [ + { + "amount": 14400, + "amount_excluding_tax": 14400, + "currency": "usd", + "description": "Zulip Plus - renewal", + "discount_amounts": [], + "discountable": false, + "discounts": [], + "id": "il_NORMALIZED00000000000001", + "invoice_item": "ii_NORMALIZED00000000000001", + "livemode": false, + "metadata": {}, + "object": "line_item", + "period": { + "end": 1000000000, + "start": 1000000000 + }, + "plan": null, + "price": { + "active": false, + "billing_scheme": "per_unit", + "created": 1000000000, + "currency": "usd", + "custom_unit_amount": null, + "id": "price_NORMALIZED00000000000001", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_NORMALIZED0001", + "recurring": null, + "tax_behavior": "unspecified", + "tiers_mode": null, + "transform_quantity": null, + "type": "one_time", + "unit_amount": 1600, + "unit_amount_decimal": "1600" + }, + "proration": false, + "proration_details": { + "credited_items": null + }, + "quantity": 9, + "subscription": null, + "tax_amounts": [], + "tax_rates": [], + "type": "invoiceitem", + "unit_amount_excluding_tax": "1600" + } + ], + "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", + "on_behalf_of": null, + "paid": false, + "paid_out_of_band": false, + "payment_intent": "pi_NORMALIZED00000000000001", + "payment_settings": { + "default_mandate": null, + "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, + "quote": null, + "receipt_number": null, + "rendering": { + "amount_tax_display": null, + "pdf": { + "page_size": "letter" + } + }, + "rendering_options": null, + "shipping_cost": null, + "shipping_details": null, + "starting_balance": -7200, + "statement_descriptor": "Zulip Plus", + "status": "open", + "status_transitions": { + "finalized_at": 1000000000, + "marked_uncollectible_at": null, + "paid_at": null, + "voided_at": null + }, + "subscription": null, + "subscription_details": { + "metadata": null + }, + "subtotal": 14400, + "subtotal_excluding_tax": 14400, + "tax": null, + "test_clock": null, + "total": 14400, + "total_discount_amounts": [], + "total_excluding_tax": 14400, + "total_tax_amounts": [], + "transfer_data": null, + "webhooks_delivered_at": null +} diff --git a/corporate/tests/stripe_fixtures/change_plan_tier_from_standard_to_plus--Invoice.list.1.json b/corporate/tests/stripe_fixtures/change_plan_tier_from_standard_to_plus--Invoice.list.1.json new file mode 100644 index 0000000000..9ffc0b76a9 --- /dev/null +++ b/corporate/tests/stripe_fixtures/change_plan_tier_from_standard_to_plus--Invoice.list.1.json @@ -0,0 +1,165 @@ +{ + "data": [ + { + "account_country": "US", + "account_name": "Kandra Labs, Inc.", + "account_tax_ids": null, + "amount_due": 7200, + "amount_paid": 0, + "amount_remaining": 7200, + "amount_shipping": 0, + "application": null, + "application_fee_amount": null, + "attempt_count": 0, + "attempted": false, + "auto_advance": true, + "automatic_tax": { + "enabled": false, + "status": null + }, + "billing_reason": "manual", + "charge": null, + "collection_method": "send_invoice", + "created": 1000000000, + "currency": "usd", + "custom_fields": null, + "customer": "cus_NORMALIZED0001", + "customer_address": null, + "customer_email": "king@lear.org", + "customer_name": null, + "customer_phone": null, + "customer_shipping": null, + "customer_tax_exempt": "none", + "customer_tax_ids": [], + "default_payment_method": null, + "default_source": null, + "default_tax_rates": [], + "description": null, + "discount": null, + "discounts": [], + "due_date": 1000000000, + "effective_at": 1000000000, + "ending_balance": 0, + "footer": null, + "from_invoice": null, + "hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QM2RWVEFzekZPQzhpS2pLRUUwdUtHZFdYSFR6elVuLDkxMjYxMTAw0200IAw0qFPB?s=ap", + "id": "in_NORMALIZED00000000000001", + "invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QM2RWVEFzekZPQzhpS2pLRUUwdUtHZFdYSFR6elVuLDkxMjYxMTAw0200IAw0qFPB/pdf?s=ap", + "last_finalization_error": null, + "latest_revision": null, + "lines": { + "data": [ + { + "amount": 14400, + "amount_excluding_tax": 14400, + "currency": "usd", + "description": "Zulip Plus - renewal", + "discount_amounts": [], + "discountable": false, + "discounts": [], + "id": "il_NORMALIZED00000000000001", + "invoice_item": "ii_NORMALIZED00000000000001", + "livemode": false, + "metadata": {}, + "object": "line_item", + "period": { + "end": 1000000000, + "start": 1000000000 + }, + "plan": null, + "price": { + "active": false, + "billing_scheme": "per_unit", + "created": 1000000000, + "currency": "usd", + "custom_unit_amount": null, + "id": "price_NORMALIZED00000000000001", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_NORMALIZED0001", + "recurring": null, + "tax_behavior": "unspecified", + "tiers_mode": null, + "transform_quantity": null, + "type": "one_time", + "unit_amount": 1600, + "unit_amount_decimal": "1600" + }, + "proration": false, + "proration_details": { + "credited_items": null + }, + "quantity": 9, + "subscription": null, + "tax_amounts": [], + "tax_rates": [], + "type": "invoiceitem", + "unit_amount_excluding_tax": "1600" + } + ], + "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", + "on_behalf_of": null, + "paid": false, + "paid_out_of_band": false, + "payment_intent": "pi_NORMALIZED00000000000001", + "payment_settings": { + "default_mandate": null, + "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, + "quote": null, + "receipt_number": null, + "rendering": { + "amount_tax_display": null, + "pdf": { + "page_size": "letter" + } + }, + "rendering_options": null, + "shipping_cost": null, + "shipping_details": null, + "starting_balance": -7200, + "statement_descriptor": "Zulip Plus", + "status": "open", + "status_transitions": { + "finalized_at": 1000000000, + "marked_uncollectible_at": null, + "paid_at": null, + "voided_at": null + }, + "subscription": null, + "subscription_details": { + "metadata": null + }, + "subtotal": 14400, + "subtotal_excluding_tax": 14400, + "tax": null, + "test_clock": null, + "total": 14400, + "total_discount_amounts": [], + "total_excluding_tax": 14400, + "total_tax_amounts": [], + "transfer_data": null, + "webhooks_delivered_at": null + } + ], + "has_more": false, + "object": "list", + "url": "/v1/invoices" +} diff --git a/corporate/tests/stripe_fixtures/change_plan_tier_from_standard_to_plus--InvoiceItem.create.1.json b/corporate/tests/stripe_fixtures/change_plan_tier_from_standard_to_plus--InvoiceItem.create.1.json new file mode 100644 index 0000000000..71d7befb71 --- /dev/null +++ b/corporate/tests/stripe_fixtures/change_plan_tier_from_standard_to_plus--InvoiceItem.create.1.json @@ -0,0 +1,47 @@ +{ + "amount": 14400, + "currency": "usd", + "customer": "cus_NORMALIZED0001", + "date": 1000000000, + "description": "Zulip Plus - renewal", + "discountable": false, + "discounts": [], + "id": "ii_NORMALIZED00000000000001", + "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", + "custom_unit_amount": null, + "id": "price_NORMALIZED00000000000001", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_NORMALIZED0001", + "recurring": null, + "tax_behavior": "unspecified", + "tiers_mode": null, + "transform_quantity": null, + "type": "one_time", + "unit_amount": 1600, + "unit_amount_decimal": "1600" + }, + "proration": false, + "quantity": 9, + "subscription": null, + "tax_rates": [], + "test_clock": null, + "unit_amount": 1600, + "unit_amount_decimal": "1600" +} diff --git a/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Customer.create.1.json b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Customer.create.1.json index d5466efbf5..593a07ed0c 100644 --- a/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Customer.create.1.json +++ b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Customer.create.1.json @@ -6,9 +6,9 @@ "default_currency": null, "default_source": null, "delinquent": false, - "description": "lear (Lear & Co.)", + "description": "zulip (Zulip Dev)", "discount": null, - "email": "king@lear.org", + "email": "hamlet@zulip.com", "id": "cus_NORMALIZED0001", "invoice_prefix": "NORMA01", "invoice_settings": { @@ -20,7 +20,7 @@ "livemode": false, "metadata": { "realm_id": "1", - "realm_str": "lear" + "realm_str": "zulip" }, "name": null, "next_invoice_sequence": 1, diff --git a/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Customer.create_balance_transaction.1.json b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Customer.create_balance_transaction.1.json index 8617999fcf..3e518b3376 100644 --- a/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Customer.create_balance_transaction.1.json +++ b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Customer.create_balance_transaction.1.json @@ -1,11 +1,11 @@ { - "amount": -7200, + "amount": -437, "created": 1000000000, "credit_note": null, "currency": "usd", "customer": "cus_NORMALIZED0001", "description": "Credit from early termination of active plan", - "ending_balance": -7200, + "ending_balance": -437, "id": "cbtxn_NORMALIZED00000000000001", "invoice": null, "livemode": false, diff --git a/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Customer.modify.1.json b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Customer.modify.1.json new file mode 100644 index 0000000000..5f99feb771 --- /dev/null +++ b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Customer.modify.1.json @@ -0,0 +1,33 @@ +{ + "address": null, + "balance": 0, + "created": 1000000000, + "currency": null, + "default_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, + "default_payment_method": "pm_1OFWD8DEQaroqDjsbeQean1W", + "footer": null, + "rendering_options": null + }, + "livemode": false, + "metadata": { + "realm_id": "1", + "realm_str": "zulip" + }, + "name": null, + "next_invoice_sequence": 1, + "object": "customer", + "phone": null, + "preferred_locales": [], + "shipping": null, + "tax_exempt": "none", + "test_clock": null +} diff --git a/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Customer.retrieve.1.json b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Customer.retrieve.1.json new file mode 100644 index 0000000000..f436712fbd --- /dev/null +++ b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Customer.retrieve.1.json @@ -0,0 +1,79 @@ +{ + "address": null, + "balance": 0, + "created": 1000000000, + "currency": null, + "default_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, + "default_payment_method": { + "billing_details": { + "address": { + "city": null, + "country": null, + "line1": null, + "line2": null, + "postal_code": null, + "state": null + }, + "email": null, + "name": null, + "phone": null + }, + "card": { + "brand": "visa", + "checks": { + "address_line1_check": null, + "address_postal_code_check": null, + "cvc_check": "pass" + }, + "country": "US", + "exp_month": 11, + "exp_year": 2024, + "fingerprint": "NORMALIZED000001", + "funding": "credit", + "generated_from": null, + "last4": "4242", + "networks": { + "available": [ + "visa" + ], + "preferred": null + }, + "three_d_secure_usage": { + "supported": true + }, + "wallet": null + }, + "created": 1000000000, + "customer": "cus_NORMALIZED0001", + "id": "pm_1OFWD8DEQaroqDjsbeQean1W", + "livemode": false, + "metadata": {}, + "object": "payment_method", + "type": "card" + }, + "footer": null, + "rendering_options": null + }, + "livemode": false, + "metadata": { + "realm_id": "1", + "realm_str": "zulip" + }, + "name": null, + "next_invoice_sequence": 1, + "object": "customer", + "phone": null, + "preferred_locales": [], + "shipping": null, + "tax_exempt": "none", + "test_clock": null +} diff --git a/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Customer.retrieve.2.json b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Customer.retrieve.2.json new file mode 100644 index 0000000000..f436712fbd --- /dev/null +++ b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Customer.retrieve.2.json @@ -0,0 +1,79 @@ +{ + "address": null, + "balance": 0, + "created": 1000000000, + "currency": null, + "default_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, + "default_payment_method": { + "billing_details": { + "address": { + "city": null, + "country": null, + "line1": null, + "line2": null, + "postal_code": null, + "state": null + }, + "email": null, + "name": null, + "phone": null + }, + "card": { + "brand": "visa", + "checks": { + "address_line1_check": null, + "address_postal_code_check": null, + "cvc_check": "pass" + }, + "country": "US", + "exp_month": 11, + "exp_year": 2024, + "fingerprint": "NORMALIZED000001", + "funding": "credit", + "generated_from": null, + "last4": "4242", + "networks": { + "available": [ + "visa" + ], + "preferred": null + }, + "three_d_secure_usage": { + "supported": true + }, + "wallet": null + }, + "created": 1000000000, + "customer": "cus_NORMALIZED0001", + "id": "pm_1OFWD8DEQaroqDjsbeQean1W", + "livemode": false, + "metadata": {}, + "object": "payment_method", + "type": "card" + }, + "footer": null, + "rendering_options": null + }, + "livemode": false, + "metadata": { + "realm_id": "1", + "realm_str": "zulip" + }, + "name": null, + "next_invoice_sequence": 1, + "object": "customer", + "phone": null, + "preferred_locales": [], + "shipping": null, + "tax_exempt": "none", + "test_clock": null +} diff --git a/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Customer.retrieve.3.json b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Customer.retrieve.3.json new file mode 100644 index 0000000000..f436712fbd --- /dev/null +++ b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Customer.retrieve.3.json @@ -0,0 +1,79 @@ +{ + "address": null, + "balance": 0, + "created": 1000000000, + "currency": null, + "default_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, + "default_payment_method": { + "billing_details": { + "address": { + "city": null, + "country": null, + "line1": null, + "line2": null, + "postal_code": null, + "state": null + }, + "email": null, + "name": null, + "phone": null + }, + "card": { + "brand": "visa", + "checks": { + "address_line1_check": null, + "address_postal_code_check": null, + "cvc_check": "pass" + }, + "country": "US", + "exp_month": 11, + "exp_year": 2024, + "fingerprint": "NORMALIZED000001", + "funding": "credit", + "generated_from": null, + "last4": "4242", + "networks": { + "available": [ + "visa" + ], + "preferred": null + }, + "three_d_secure_usage": { + "supported": true + }, + "wallet": null + }, + "created": 1000000000, + "customer": "cus_NORMALIZED0001", + "id": "pm_1OFWD8DEQaroqDjsbeQean1W", + "livemode": false, + "metadata": {}, + "object": "payment_method", + "type": "card" + }, + "footer": null, + "rendering_options": null + }, + "livemode": false, + "metadata": { + "realm_id": "1", + "realm_str": "zulip" + }, + "name": null, + "next_invoice_sequence": 1, + "object": "customer", + "phone": null, + "preferred_locales": [], + "shipping": null, + "tax_exempt": "none", + "test_clock": null +} diff --git a/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Customer.retrieve.4.json b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Customer.retrieve.4.json new file mode 100644 index 0000000000..f436712fbd --- /dev/null +++ b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Customer.retrieve.4.json @@ -0,0 +1,79 @@ +{ + "address": null, + "balance": 0, + "created": 1000000000, + "currency": null, + "default_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, + "default_payment_method": { + "billing_details": { + "address": { + "city": null, + "country": null, + "line1": null, + "line2": null, + "postal_code": null, + "state": null + }, + "email": null, + "name": null, + "phone": null + }, + "card": { + "brand": "visa", + "checks": { + "address_line1_check": null, + "address_postal_code_check": null, + "cvc_check": "pass" + }, + "country": "US", + "exp_month": 11, + "exp_year": 2024, + "fingerprint": "NORMALIZED000001", + "funding": "credit", + "generated_from": null, + "last4": "4242", + "networks": { + "available": [ + "visa" + ], + "preferred": null + }, + "three_d_secure_usage": { + "supported": true + }, + "wallet": null + }, + "created": 1000000000, + "customer": "cus_NORMALIZED0001", + "id": "pm_1OFWD8DEQaroqDjsbeQean1W", + "livemode": false, + "metadata": {}, + "object": "payment_method", + "type": "card" + }, + "footer": null, + "rendering_options": null + }, + "livemode": false, + "metadata": { + "realm_id": "1", + "realm_str": "zulip" + }, + "name": null, + "next_invoice_sequence": 1, + "object": "customer", + "phone": null, + "preferred_locales": [], + "shipping": null, + "tax_exempt": "none", + "test_clock": null +} diff --git a/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Event.list.1.json b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Event.list.1.json new file mode 100644 index 0000000000..d1459afec5 --- /dev/null +++ b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Event.list.1.json @@ -0,0 +1,60 @@ +{ + "data": [ + { + "api_version": "2020-08-27", + "created": 1000000000, + "data": { + "object": { + "address": null, + "balance": 0, + "created": 1000000000, + "currency": null, + "default_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, + "default_payment_method": "pm_1OFWD8DEQaroqDjsbeQean1W", + "footer": null, + "rendering_options": null + }, + "livemode": false, + "metadata": { + "realm_id": "1", + "realm_str": "zulip" + }, + "name": null, + "next_invoice_sequence": 1, + "object": "customer", + "phone": null, + "preferred_locales": [], + "shipping": null, + "tax_exempt": "none", + "test_clock": null + }, + "previous_attributes": { + "invoice_settings": { + "default_payment_method": null + } + } + }, + "id": "evt_1OFWD9DEQaroqDjsPiDL0AYg", + "livemode": false, + "object": "event", + "pending_webhooks": 0, + "request": { + "id": "req_NORMALIZED0001", + "idempotency_key": "e61003eb-2742-4e21-bded-f552701754aa" + }, + "type": "customer.updated" + } + ], + "has_more": true, + "object": "list", + "url": "/v1/events" +} diff --git a/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Event.list.2.json b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Event.list.2.json new file mode 100644 index 0000000000..690c69811a --- /dev/null +++ b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Event.list.2.json @@ -0,0 +1,146 @@ +{ + "data": [ + { + "api_version": "2020-08-27", + "created": 1000000000, + "data": { + "object": { + "amount": 48000, + "amount_captured": 48000, + "amount_refunded": 0, + "application": null, + "application_fee": null, + "application_fee_amount": null, + "balance_transaction": "txn_NORMALIZED00000000000002", + "billing_details": { + "address": { + "city": null, + "country": null, + "line1": null, + "line2": null, + "postal_code": null, + "state": null + }, + "email": null, + "name": null, + "phone": null + }, + "calculated_statement_descriptor": "ZULIP CLOUD STANDARD", + "captured": true, + "created": 1000000000, + "currency": "usd", + "customer": "cus_NORMALIZED0001", + "description": "Upgrade to Zulip Cloud Standard, $80.0 x 6", + "destination": null, + "dispute": null, + "disputed": false, + "failure_balance_transaction": null, + "failure_code": null, + "failure_message": null, + "fraud_details": {}, + "id": "ch_NORMALIZED00000000000001", + "invoice": null, + "livemode": false, + "metadata": { + "billing_modality": "charge_automatically", + "billing_schedule": "1", + "license_management": "automatic", + "licenses": "6", + "price_per_license": "8000", + "realm_id": "1", + "realm_str": "zulip", + "seat_count": "6", + "type": "upgrade", + "user_email": "hamlet@zulip.com", + "user_id": "10" + }, + "object": "charge", + "on_behalf_of": null, + "order": null, + "outcome": { + "network_status": "approved_by_network", + "reason": null, + "risk_level": "normal", + "risk_score": 0, + "seller_message": "Payment complete.", + "type": "authorized" + }, + "paid": true, + "payment_intent": "pi_NORMALIZED00000000000001", + "payment_method": "pm_1OFWD8DEQaroqDjsbeQean1W", + "payment_method_details": { + "card": { + "amount_authorized": 48000, + "brand": "visa", + "checks": { + "address_line1_check": null, + "address_postal_code_check": null, + "cvc_check": "pass" + }, + "country": "US", + "exp_month": 11, + "exp_year": 2024, + "extended_authorization": { + "status": "disabled" + }, + "fingerprint": "NORMALIZED000001", + "funding": "credit", + "incremental_authorization": { + "status": "unavailable" + }, + "installments": null, + "last4": "4242", + "mandate": null, + "multicapture": { + "status": "unavailable" + }, + "network": "visa", + "network_token": { + "used": false + }, + "overcapture": { + "maximum_amount_capturable": 48000, + "status": "unavailable" + }, + "three_d_secure": null, + "wallet": null + }, + "type": "card" + }, + "receipt_email": "hamlet@zulip.com", + "receipt_number": null, + "receipt_url": "https://pay.stripe.com/receipts/payment/CAcaFwoVYWNjdF8xN3ZUa3dERVFhcm9xRGpzKL7c-6oGMgaz9Tos8P86LBZda7Ck6q7bxLFnyx0j-_4qTLgbSiIZSdGlLELq1aTRX1AJTgPBN5Omy_hU", + "refunded": false, + "refunds": { + "data": [], + "has_more": false, + "object": "list", + "total_count": 0, + "url": "/v1/charges/ch_NORMALIZED00000000000001/refunds" + }, + "review": null, + "shipping": null, + "source": null, + "source_transfer": null, + "statement_descriptor": "Zulip Cloud Standard", + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "id": "evt_3OFWDBDEQaroqDjs0XubEkJk", + "livemode": false, + "object": "event", + "pending_webhooks": 2, + "request": { + "id": "req_NORMALIZED0002", + "idempotency_key": "79a21870-d329-42b9-a7dd-816c7227626e" + }, + "type": "charge.succeeded" + } + ], + "has_more": false, + "object": "list", + "url": "/v1/events" +} diff --git a/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Event.list.3.json b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Event.list.3.json new file mode 100644 index 0000000000..64207362b2 --- /dev/null +++ b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Event.list.3.json @@ -0,0 +1,219 @@ +{ + "data": [ + { + "api_version": "2020-08-27", + "created": 1000000000, + "data": { + "object": { + "amount": 48000, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 48000, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": null, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "charges": { + "data": [ + { + "amount": 48000, + "amount_captured": 48000, + "amount_refunded": 0, + "application": null, + "application_fee": null, + "application_fee_amount": null, + "balance_transaction": "txn_NORMALIZED00000000000002", + "billing_details": { + "address": { + "city": null, + "country": null, + "line1": null, + "line2": null, + "postal_code": null, + "state": null + }, + "email": null, + "name": null, + "phone": null + }, + "calculated_statement_descriptor": "ZULIP CLOUD STANDARD", + "captured": true, + "created": 1000000000, + "currency": "usd", + "customer": "cus_NORMALIZED0001", + "description": "Upgrade to Zulip Cloud Standard, $80.0 x 6", + "destination": null, + "dispute": null, + "disputed": false, + "failure_balance_transaction": null, + "failure_code": null, + "failure_message": null, + "fraud_details": {}, + "id": "ch_NORMALIZED00000000000001", + "invoice": null, + "livemode": false, + "metadata": { + "billing_modality": "charge_automatically", + "billing_schedule": "1", + "license_management": "automatic", + "licenses": "6", + "price_per_license": "8000", + "realm_id": "1", + "realm_str": "zulip", + "seat_count": "6", + "type": "upgrade", + "user_email": "hamlet@zulip.com", + "user_id": "10" + }, + "object": "charge", + "on_behalf_of": null, + "order": null, + "outcome": { + "network_status": "approved_by_network", + "reason": null, + "risk_level": "normal", + "risk_score": 0, + "seller_message": "Payment complete.", + "type": "authorized" + }, + "paid": true, + "payment_intent": "pi_NORMALIZED00000000000001", + "payment_method": "pm_1OFWD8DEQaroqDjsbeQean1W", + "payment_method_details": { + "card": { + "amount_authorized": 48000, + "brand": "visa", + "checks": { + "address_line1_check": null, + "address_postal_code_check": null, + "cvc_check": "pass" + }, + "country": "US", + "exp_month": 11, + "exp_year": 2024, + "extended_authorization": { + "status": "disabled" + }, + "fingerprint": "NORMALIZED000001", + "funding": "credit", + "incremental_authorization": { + "status": "unavailable" + }, + "installments": null, + "last4": "4242", + "mandate": null, + "multicapture": { + "status": "unavailable" + }, + "network": "visa", + "network_token": { + "used": false + }, + "overcapture": { + "maximum_amount_capturable": 48000, + "status": "unavailable" + }, + "three_d_secure": null, + "wallet": null + }, + "type": "card" + }, + "receipt_email": "hamlet@zulip.com", + "receipt_number": null, + "receipt_url": "https://pay.stripe.com/receipts/payment/CAcaFwoVYWNjdF8xN3ZUa3dERVFhcm9xRGpzKL7c-6oGMgb-QbX6aKA6LBYvTD5qCJyj_oSzU9nmowj0xxKoo9gSyPhS1Az-XVSPbh2EaRTuTUSFhSOd", + "refunded": false, + "refunds": { + "data": [], + "has_more": false, + "object": "list", + "total_count": 0, + "url": "/v1/charges/ch_NORMALIZED00000000000001/refunds" + }, + "review": null, + "shipping": null, + "source": null, + "source_transfer": null, + "statement_descriptor": "Zulip Cloud Standard", + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + ], + "has_more": false, + "object": "list", + "total_count": 1, + "url": "/v1/charges?payment_intent=pi_NORMALIZED00000000000001" + }, + "client_secret": "pi_NORMALIZED00000000000001_secret_8LrrfmEMVbU1QNd1Y1e4LW91d", + "confirmation_method": "automatic", + "created": 1000000000, + "currency": "usd", + "customer": "cus_NORMALIZED0001", + "description": "Upgrade to Zulip Cloud Standard, $80.0 x 6", + "id": "pi_NORMALIZED00000000000001", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_NORMALIZED00000000000001", + "livemode": false, + "metadata": { + "billing_modality": "charge_automatically", + "billing_schedule": "1", + "license_management": "automatic", + "licenses": "6", + "price_per_license": "8000", + "realm_id": "1", + "realm_str": "zulip", + "seat_count": "6", + "type": "upgrade", + "user_email": "hamlet@zulip.com", + "user_id": "10" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OFWD8DEQaroqDjsbeQean1W", + "payment_method_configuration_details": null, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + } + }, + "payment_method_types": [ + "card" + ], + "processing": null, + "receipt_email": "hamlet@zulip.com", + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": "Zulip Cloud Standard", + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "id": "evt_3OFWDBDEQaroqDjs0cRcGUju", + "livemode": false, + "object": "event", + "pending_webhooks": 0, + "request": { + "id": "req_NORMALIZED0002", + "idempotency_key": "79a21870-d329-42b9-a7dd-816c7227626e" + }, + "type": "payment_intent.succeeded" + } + ], + "has_more": false, + "object": "list", + "url": "/v1/events" +} diff --git a/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Event.list.4.json b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Event.list.4.json new file mode 100644 index 0000000000..10674cdf3b --- /dev/null +++ b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Event.list.4.json @@ -0,0 +1,406 @@ +{ + "data": [ + { + "api_version": "2020-08-27", + "created": 1000000000, + "data": { + "object": { + "account_country": "US", + "account_name": "Kandra Labs, Inc.", + "account_tax_ids": null, + "amount_due": 0, + "amount_paid": 0, + "amount_remaining": 0, + "amount_shipping": 0, + "application": null, + "application_fee_amount": null, + "attempt_count": 0, + "attempted": false, + "auto_advance": true, + "automatic_tax": { + "enabled": false, + "status": null + }, + "billing_reason": "manual", + "charge": null, + "collection_method": "charge_automatically", + "created": 1000000000, + "currency": "usd", + "custom_fields": null, + "customer": "cus_NORMALIZED0001", + "customer_address": null, + "customer_email": "hamlet@zulip.com", + "customer_name": null, + "customer_phone": null, + "customer_shipping": null, + "customer_tax_exempt": "none", + "customer_tax_ids": [], + "default_payment_method": null, + "default_source": null, + "default_tax_rates": [], + "description": null, + "discount": null, + "discounts": [], + "due_date": null, + "effective_at": null, + "ending_balance": null, + "footer": null, + "from_invoice": null, + "hosted_invoice_url": null, + "id": "in_NORMALIZED00000000000001", + "invoice_pdf": null, + "last_finalization_error": null, + "latest_revision": null, + "lines": { + "data": [ + { + "amount": 48000, + "amount_excluding_tax": 48000, + "currency": "usd", + "description": "Zulip Cloud Standard", + "discount_amounts": [], + "discountable": false, + "discounts": [], + "id": "il_NORMALIZED00000000000001", + "invoice_item": "ii_NORMALIZED00000000000001", + "livemode": false, + "metadata": {}, + "object": "line_item", + "period": { + "end": 1357095845, + "start": 1325473445 + }, + "plan": null, + "price": { + "active": false, + "billing_scheme": "per_unit", + "created": 1000000000, + "currency": "usd", + "custom_unit_amount": null, + "id": "price_NORMALIZED00000000000001", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_NORMALIZED0001", + "recurring": null, + "tax_behavior": "unspecified", + "tiers_mode": null, + "transform_quantity": null, + "type": "one_time", + "unit_amount": 8000, + "unit_amount_decimal": "8000" + }, + "proration": false, + "proration_details": { + "credited_items": null + }, + "quantity": 6, + "subscription": null, + "tax_amounts": [], + "tax_rates": [], + "type": "invoiceitem", + "unit_amount_excluding_tax": "8000" + }, + { + "amount": -48000, + "amount_excluding_tax": -48000, + "currency": "usd", + "description": "Payment (Card ending in 4242)", + "discount_amounts": [], + "discountable": false, + "discounts": [], + "id": "il_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", + "custom_unit_amount": null, + "id": "price_NORMALIZED00000000000002", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_NORMALIZED0002", + "recurring": null, + "tax_behavior": "unspecified", + "tiers_mode": null, + "transform_quantity": null, + "type": "one_time", + "unit_amount": -48000, + "unit_amount_decimal": "-48000" + }, + "proration": false, + "proration_details": { + "credited_items": null + }, + "quantity": 1, + "subscription": null, + "tax_amounts": [], + "tax_rates": [], + "type": "invoiceitem", + "unit_amount_excluding_tax": "-48000" + } + ], + "has_more": false, + "object": "list", + "total_count": 2, + "url": "/v1/invoices/in_NORMALIZED00000000000001/lines" + }, + "livemode": false, + "metadata": {}, + "next_payment_attempt": 1000000000, + "number": null, + "object": "invoice", + "on_behalf_of": null, + "paid": false, + "paid_out_of_band": false, + "payment_intent": null, + "payment_settings": { + "default_mandate": null, + "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, + "quote": null, + "receipt_number": null, + "rendering": { + "amount_tax_display": null, + "pdf": { + "page_size": "auto" + } + }, + "rendering_options": null, + "shipping_cost": null, + "shipping_details": null, + "starting_balance": 0, + "statement_descriptor": "Zulip Cloud Standard", + "status": "draft", + "status_transitions": { + "finalized_at": null, + "marked_uncollectible_at": null, + "paid_at": null, + "voided_at": null + }, + "subscription": null, + "subscription_details": { + "metadata": null + }, + "subtotal": 0, + "subtotal_excluding_tax": 0, + "tax": null, + "test_clock": null, + "total": 0, + "total_discount_amounts": [], + "total_excluding_tax": 0, + "total_tax_amounts": [], + "transfer_data": null, + "webhooks_delivered_at": null + } + }, + "id": "evt_1OFWDDDEQaroqDjsyi5CLur2", + "livemode": false, + "object": "event", + "pending_webhooks": 0, + "request": { + "id": "req_NORMALIZED0003", + "idempotency_key": "c0e24090-817c-4cf1-9a64-f49233a13da5" + }, + "type": "invoice.created" + }, + { + "api_version": "2020-08-27", + "created": 1000000000, + "data": { + "object": { + "amount": 48000, + "currency": "usd", + "customer": "cus_NORMALIZED0001", + "date": 1000000000, + "description": "Zulip Cloud Standard", + "discountable": false, + "discounts": [], + "id": "ii_NORMALIZED00000000000001", + "invoice": null, + "livemode": false, + "metadata": {}, + "object": "invoiceitem", + "period": { + "end": 1357095845, + "start": 1325473445 + }, + "plan": null, + "price": { + "active": false, + "billing_scheme": "per_unit", + "created": 1000000000, + "currency": "usd", + "custom_unit_amount": null, + "id": "price_NORMALIZED00000000000001", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_NORMALIZED0001", + "recurring": null, + "tax_behavior": "unspecified", + "tiers_mode": null, + "transform_quantity": null, + "type": "one_time", + "unit_amount": 8000, + "unit_amount_decimal": "8000" + }, + "proration": false, + "quantity": 6, + "subscription": null, + "tax_rates": [], + "test_clock": null, + "unit_amount": 8000, + "unit_amount_decimal": "8000" + } + }, + "id": "evt_1OFWDDDEQaroqDjs8IeJM6Pb", + "livemode": false, + "object": "event", + "pending_webhooks": 0, + "request": { + "id": "req_NORMALIZED0004", + "idempotency_key": "80161211-807b-49a8-a243-9a970f71f0e8" + }, + "type": "invoiceitem.created" + }, + { + "api_version": "2020-08-27", + "created": 1000000000, + "data": { + "object": { + "amount": -48000, + "currency": "usd", + "customer": "cus_NORMALIZED0001", + "date": 1000000000, + "description": "Payment (Card ending in 4242)", + "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", + "custom_unit_amount": null, + "id": "price_NORMALIZED00000000000002", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_NORMALIZED0002", + "recurring": null, + "tax_behavior": "unspecified", + "tiers_mode": null, + "transform_quantity": null, + "type": "one_time", + "unit_amount": -48000, + "unit_amount_decimal": "-48000" + }, + "proration": false, + "quantity": 1, + "subscription": null, + "tax_rates": [], + "test_clock": null, + "unit_amount": -48000, + "unit_amount_decimal": "-48000" + } + }, + "id": "evt_1OFWDDDEQaroqDjst4NM9zRA", + "livemode": false, + "object": "event", + "pending_webhooks": 0, + "request": { + "id": "req_NORMALIZED0005", + "idempotency_key": "c8fbf319-f723-48d1-9c38-5d8e68fd74ca" + }, + "type": "invoiceitem.created" + }, + { + "api_version": "2020-08-27", + "created": 1000000000, + "data": { + "object": { + "address": null, + "balance": 0, + "created": 1000000000, + "currency": "usd", + "default_currency": "usd", + "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, + "default_payment_method": "pm_1OFWD8DEQaroqDjsbeQean1W", + "footer": null, + "rendering_options": null + }, + "livemode": false, + "metadata": { + "realm_id": "1", + "realm_str": "zulip" + }, + "name": null, + "next_invoice_sequence": 1, + "object": "customer", + "phone": null, + "preferred_locales": [], + "shipping": null, + "tax_exempt": "none", + "test_clock": null + }, + "previous_attributes": { + "currency": null, + "default_currency": null + } + }, + "id": "evt_1OFWDDDEQaroqDjsa6HU7in0", + "livemode": false, + "object": "event", + "pending_webhooks": 0, + "request": { + "id": "req_NORMALIZED0005", + "idempotency_key": "c8fbf319-f723-48d1-9c38-5d8e68fd74ca" + }, + "type": "customer.updated" + } + ], + "has_more": false, + "object": "list", + "url": "/v1/events" +} diff --git a/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Event.list.5.json b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Event.list.5.json new file mode 100644 index 0000000000..92bafcfaa1 --- /dev/null +++ b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Event.list.5.json @@ -0,0 +1,474 @@ +{ + "data": [ + { + "api_version": "2020-08-27", + "created": 1000000000, + "data": { + "object": { + "account_country": "US", + "account_name": "Kandra Labs, Inc.", + "account_tax_ids": null, + "amount_due": 0, + "amount_paid": 0, + "amount_remaining": 0, + "amount_shipping": 0, + "application": null, + "application_fee_amount": null, + "attempt_count": 0, + "attempted": true, + "auto_advance": false, + "automatic_tax": { + "enabled": false, + "status": null + }, + "billing_reason": "manual", + "charge": null, + "collection_method": "charge_automatically", + "created": 1000000000, + "currency": "usd", + "custom_fields": null, + "customer": "cus_NORMALIZED0001", + "customer_address": null, + "customer_email": "hamlet@zulip.com", + "customer_name": null, + "customer_phone": null, + "customer_shipping": null, + "customer_tax_exempt": "none", + "customer_tax_ids": [], + "default_payment_method": null, + "default_source": null, + "default_tax_rates": [], + "description": null, + "discount": null, + "discounts": [], + "due_date": null, + "effective_at": 1000000000, + "ending_balance": 0, + "footer": null, + "from_invoice": null, + "hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QM2RVSjJZbEx3bGZ5TnV6ZGQ2MEd1aTYwQjRuUElRLDkxMjYwOTky02007zWYSruV?s=ap", + "id": "in_NORMALIZED00000000000001", + "invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QM2RVSjJZbEx3bGZ5TnV6ZGQ2MEd1aTYwQjRuUElRLDkxMjYwOTky02007zWYSruV/pdf?s=ap", + "last_finalization_error": null, + "latest_revision": null, + "lines": { + "data": [ + { + "amount": 48000, + "amount_excluding_tax": 48000, + "currency": "usd", + "description": "Zulip Cloud Standard", + "discount_amounts": [], + "discountable": false, + "discounts": [], + "id": "il_NORMALIZED00000000000001", + "invoice_item": "ii_NORMALIZED00000000000001", + "livemode": false, + "metadata": {}, + "object": "line_item", + "period": { + "end": 1357095845, + "start": 1325473445 + }, + "plan": null, + "price": { + "active": false, + "billing_scheme": "per_unit", + "created": 1000000000, + "currency": "usd", + "custom_unit_amount": null, + "id": "price_NORMALIZED00000000000001", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_NORMALIZED0001", + "recurring": null, + "tax_behavior": "unspecified", + "tiers_mode": null, + "transform_quantity": null, + "type": "one_time", + "unit_amount": 8000, + "unit_amount_decimal": "8000" + }, + "proration": false, + "proration_details": { + "credited_items": null + }, + "quantity": 6, + "subscription": null, + "tax_amounts": [], + "tax_rates": [], + "type": "invoiceitem", + "unit_amount_excluding_tax": "8000" + }, + { + "amount": -48000, + "amount_excluding_tax": -48000, + "currency": "usd", + "description": "Payment (Card ending in 4242)", + "discount_amounts": [], + "discountable": false, + "discounts": [], + "id": "il_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", + "custom_unit_amount": null, + "id": "price_NORMALIZED00000000000002", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_NORMALIZED0002", + "recurring": null, + "tax_behavior": "unspecified", + "tiers_mode": null, + "transform_quantity": null, + "type": "one_time", + "unit_amount": -48000, + "unit_amount_decimal": "-48000" + }, + "proration": false, + "proration_details": { + "credited_items": null + }, + "quantity": 1, + "subscription": null, + "tax_amounts": [], + "tax_rates": [], + "type": "invoiceitem", + "unit_amount_excluding_tax": "-48000" + } + ], + "has_more": false, + "object": "list", + "total_count": 2, + "url": "/v1/invoices/in_NORMALIZED00000000000001/lines" + }, + "livemode": false, + "metadata": {}, + "next_payment_attempt": null, + "number": "NORMALI-0001", + "object": "invoice", + "on_behalf_of": null, + "paid": true, + "paid_out_of_band": false, + "payment_intent": null, + "payment_settings": { + "default_mandate": null, + "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, + "quote": null, + "receipt_number": null, + "rendering": { + "amount_tax_display": null, + "pdf": { + "page_size": "letter" + } + }, + "rendering_options": null, + "shipping_cost": null, + "shipping_details": null, + "starting_balance": 0, + "statement_descriptor": "Zulip Cloud Standard", + "status": "paid", + "status_transitions": { + "finalized_at": 1000000000, + "marked_uncollectible_at": null, + "paid_at": 1000000000, + "voided_at": null + }, + "subscription": null, + "subscription_details": { + "metadata": null + }, + "subtotal": 0, + "subtotal_excluding_tax": 0, + "tax": null, + "test_clock": null, + "total": 0, + "total_discount_amounts": [], + "total_excluding_tax": 0, + "total_tax_amounts": [], + "transfer_data": null, + "webhooks_delivered_at": null + } + }, + "id": "evt_1OFWDEDEQaroqDjsaUeU2jsL", + "livemode": false, + "object": "event", + "pending_webhooks": 2, + "request": { + "id": "req_NORMALIZED0006", + "idempotency_key": "e461b87c-d52e-4af6-a76e-c7717b66e633" + }, + "type": "invoice.finalized" + }, + { + "api_version": "2020-08-27", + "created": 1000000000, + "data": { + "object": { + "account_country": "US", + "account_name": "Kandra Labs, Inc.", + "account_tax_ids": null, + "amount_due": 0, + "amount_paid": 0, + "amount_remaining": 0, + "amount_shipping": 0, + "application": null, + "application_fee_amount": null, + "attempt_count": 0, + "attempted": true, + "auto_advance": false, + "automatic_tax": { + "enabled": false, + "status": null + }, + "billing_reason": "manual", + "charge": null, + "collection_method": "charge_automatically", + "created": 1000000000, + "currency": "usd", + "custom_fields": null, + "customer": "cus_NORMALIZED0001", + "customer_address": null, + "customer_email": "hamlet@zulip.com", + "customer_name": null, + "customer_phone": null, + "customer_shipping": null, + "customer_tax_exempt": "none", + "customer_tax_ids": [], + "default_payment_method": null, + "default_source": null, + "default_tax_rates": [], + "description": null, + "discount": null, + "discounts": [], + "due_date": null, + "effective_at": 1000000000, + "ending_balance": 0, + "footer": null, + "from_invoice": null, + "hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QM2RVSjJZbEx3bGZ5TnV6ZGQ2MEd1aTYwQjRuUElRLDkxMjYwOTky02007zWYSruV?s=ap", + "id": "in_NORMALIZED00000000000001", + "invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QM2RVSjJZbEx3bGZ5TnV6ZGQ2MEd1aTYwQjRuUElRLDkxMjYwOTky02007zWYSruV/pdf?s=ap", + "last_finalization_error": null, + "latest_revision": null, + "lines": { + "data": [ + { + "amount": 48000, + "amount_excluding_tax": 48000, + "currency": "usd", + "description": "Zulip Cloud Standard", + "discount_amounts": [], + "discountable": false, + "discounts": [], + "id": "il_NORMALIZED00000000000001", + "invoice_item": "ii_NORMALIZED00000000000001", + "livemode": false, + "metadata": {}, + "object": "line_item", + "period": { + "end": 1357095845, + "start": 1325473445 + }, + "plan": null, + "price": { + "active": false, + "billing_scheme": "per_unit", + "created": 1000000000, + "currency": "usd", + "custom_unit_amount": null, + "id": "price_NORMALIZED00000000000001", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_NORMALIZED0001", + "recurring": null, + "tax_behavior": "unspecified", + "tiers_mode": null, + "transform_quantity": null, + "type": "one_time", + "unit_amount": 8000, + "unit_amount_decimal": "8000" + }, + "proration": false, + "proration_details": { + "credited_items": null + }, + "quantity": 6, + "subscription": null, + "tax_amounts": [], + "tax_rates": [], + "type": "invoiceitem", + "unit_amount_excluding_tax": "8000" + }, + { + "amount": -48000, + "amount_excluding_tax": -48000, + "currency": "usd", + "description": "Payment (Card ending in 4242)", + "discount_amounts": [], + "discountable": false, + "discounts": [], + "id": "il_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", + "custom_unit_amount": null, + "id": "price_NORMALIZED00000000000002", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_NORMALIZED0002", + "recurring": null, + "tax_behavior": "unspecified", + "tiers_mode": null, + "transform_quantity": null, + "type": "one_time", + "unit_amount": -48000, + "unit_amount_decimal": "-48000" + }, + "proration": false, + "proration_details": { + "credited_items": null + }, + "quantity": 1, + "subscription": null, + "tax_amounts": [], + "tax_rates": [], + "type": "invoiceitem", + "unit_amount_excluding_tax": "-48000" + } + ], + "has_more": false, + "object": "list", + "total_count": 2, + "url": "/v1/invoices/in_NORMALIZED00000000000001/lines" + }, + "livemode": false, + "metadata": {}, + "next_payment_attempt": null, + "number": "NORMALI-0001", + "object": "invoice", + "on_behalf_of": null, + "paid": true, + "paid_out_of_band": false, + "payment_intent": null, + "payment_settings": { + "default_mandate": null, + "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, + "quote": null, + "receipt_number": null, + "rendering": { + "amount_tax_display": null, + "pdf": { + "page_size": "letter" + } + }, + "rendering_options": null, + "shipping_cost": null, + "shipping_details": null, + "starting_balance": 0, + "statement_descriptor": "Zulip Cloud Standard", + "status": "paid", + "status_transitions": { + "finalized_at": 1000000000, + "marked_uncollectible_at": null, + "paid_at": 1000000000, + "voided_at": null + }, + "subscription": null, + "subscription_details": { + "metadata": null + }, + "subtotal": 0, + "subtotal_excluding_tax": 0, + "tax": null, + "test_clock": null, + "total": 0, + "total_discount_amounts": [], + "total_excluding_tax": 0, + "total_tax_amounts": [], + "transfer_data": null, + "webhooks_delivered_at": null + }, + "previous_attributes": { + "attempted": false, + "auto_advance": true, + "effective_at": null, + "ending_balance": null, + "hosted_invoice_url": null, + "invoice_pdf": null, + "next_payment_attempt": 1000000000, + "number": null, + "paid": false, + "rendering": { + "pdf": { + "page_size": "auto" + } + }, + "status": "draft", + "status_transitions": { + "finalized_at": null, + "paid_at": null + } + } + }, + "id": "evt_1OFWDEDEQaroqDjsKMHv3Jvl", + "livemode": false, + "object": "event", + "pending_webhooks": 0, + "request": { + "id": "req_NORMALIZED0006", + "idempotency_key": "e461b87c-d52e-4af6-a76e-c7717b66e633" + }, + "type": "invoice.updated" + } + ], + "has_more": false, + "object": "list", + "url": "/v1/events" +} diff --git a/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Event.list.6.json b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Event.list.6.json new file mode 100644 index 0000000000..353abe9b85 --- /dev/null +++ b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Event.list.6.json @@ -0,0 +1,230 @@ +{ + "data": [ + { + "api_version": "2020-08-27", + "created": 1000000000, + "data": { + "object": { + "account_country": "US", + "account_name": "Kandra Labs, Inc.", + "account_tax_ids": null, + "amount_due": 0, + "amount_paid": 0, + "amount_remaining": 0, + "amount_shipping": 0, + "application": null, + "application_fee_amount": null, + "attempt_count": 0, + "attempted": true, + "auto_advance": false, + "automatic_tax": { + "enabled": false, + "status": null + }, + "billing_reason": "manual", + "charge": null, + "collection_method": "charge_automatically", + "created": 1000000000, + "currency": "usd", + "custom_fields": null, + "customer": "cus_NORMALIZED0001", + "customer_address": null, + "customer_email": "hamlet@zulip.com", + "customer_name": null, + "customer_phone": null, + "customer_shipping": null, + "customer_tax_exempt": "none", + "customer_tax_ids": [], + "default_payment_method": null, + "default_source": null, + "default_tax_rates": [], + "description": null, + "discount": null, + "discounts": [], + "due_date": null, + "effective_at": 1000000000, + "ending_balance": 0, + "footer": null, + "from_invoice": null, + "hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QM2RVSjJZbEx3bGZ5TnV6ZGQ2MEd1aTYwQjRuUElRLDkxMjYwOTky02007zWYSruV?s=ap", + "id": "in_NORMALIZED00000000000001", + "invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QM2RVSjJZbEx3bGZ5TnV6ZGQ2MEd1aTYwQjRuUElRLDkxMjYwOTky02007zWYSruV/pdf?s=ap", + "last_finalization_error": null, + "latest_revision": null, + "lines": { + "data": [ + { + "amount": 48000, + "amount_excluding_tax": 48000, + "currency": "usd", + "description": "Zulip Cloud Standard", + "discount_amounts": [], + "discountable": false, + "discounts": [], + "id": "il_NORMALIZED00000000000001", + "invoice_item": "ii_NORMALIZED00000000000001", + "livemode": false, + "metadata": {}, + "object": "line_item", + "period": { + "end": 1357095845, + "start": 1325473445 + }, + "plan": null, + "price": { + "active": false, + "billing_scheme": "per_unit", + "created": 1000000000, + "currency": "usd", + "custom_unit_amount": null, + "id": "price_NORMALIZED00000000000001", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_NORMALIZED0001", + "recurring": null, + "tax_behavior": "unspecified", + "tiers_mode": null, + "transform_quantity": null, + "type": "one_time", + "unit_amount": 8000, + "unit_amount_decimal": "8000" + }, + "proration": false, + "proration_details": { + "credited_items": null + }, + "quantity": 6, + "subscription": null, + "tax_amounts": [], + "tax_rates": [], + "type": "invoiceitem", + "unit_amount_excluding_tax": "8000" + }, + { + "amount": -48000, + "amount_excluding_tax": -48000, + "currency": "usd", + "description": "Payment (Card ending in 4242)", + "discount_amounts": [], + "discountable": false, + "discounts": [], + "id": "il_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", + "custom_unit_amount": null, + "id": "price_NORMALIZED00000000000002", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_NORMALIZED0002", + "recurring": null, + "tax_behavior": "unspecified", + "tiers_mode": null, + "transform_quantity": null, + "type": "one_time", + "unit_amount": -48000, + "unit_amount_decimal": "-48000" + }, + "proration": false, + "proration_details": { + "credited_items": null + }, + "quantity": 1, + "subscription": null, + "tax_amounts": [], + "tax_rates": [], + "type": "invoiceitem", + "unit_amount_excluding_tax": "-48000" + } + ], + "has_more": false, + "object": "list", + "total_count": 2, + "url": "/v1/invoices/in_NORMALIZED00000000000001/lines" + }, + "livemode": false, + "metadata": {}, + "next_payment_attempt": null, + "number": "NORMALI-0001", + "object": "invoice", + "on_behalf_of": null, + "paid": true, + "paid_out_of_band": false, + "payment_intent": null, + "payment_settings": { + "default_mandate": null, + "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, + "quote": null, + "receipt_number": null, + "rendering": { + "amount_tax_display": null, + "pdf": { + "page_size": "letter" + } + }, + "rendering_options": null, + "shipping_cost": null, + "shipping_details": null, + "starting_balance": 0, + "statement_descriptor": "Zulip Cloud Standard", + "status": "paid", + "status_transitions": { + "finalized_at": 1000000000, + "marked_uncollectible_at": null, + "paid_at": 1000000000, + "voided_at": null + }, + "subscription": null, + "subscription_details": { + "metadata": null + }, + "subtotal": 0, + "subtotal_excluding_tax": 0, + "tax": null, + "test_clock": null, + "total": 0, + "total_discount_amounts": [], + "total_excluding_tax": 0, + "total_tax_amounts": [], + "transfer_data": null, + "webhooks_delivered_at": null + } + }, + "id": "evt_1OFWDEDEQaroqDjs66EoHBLc", + "livemode": false, + "object": "event", + "pending_webhooks": 2, + "request": { + "id": "req_NORMALIZED0006", + "idempotency_key": "e461b87c-d52e-4af6-a76e-c7717b66e633" + }, + "type": "invoice.paid" + } + ], + "has_more": false, + "object": "list", + "url": "/v1/events" +} diff --git a/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Event.list.7.json b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Event.list.7.json new file mode 100644 index 0000000000..adc35e9a41 --- /dev/null +++ b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Event.list.7.json @@ -0,0 +1,230 @@ +{ + "data": [ + { + "api_version": "2020-08-27", + "created": 1000000000, + "data": { + "object": { + "account_country": "US", + "account_name": "Kandra Labs, Inc.", + "account_tax_ids": null, + "amount_due": 0, + "amount_paid": 0, + "amount_remaining": 0, + "amount_shipping": 0, + "application": null, + "application_fee_amount": null, + "attempt_count": 0, + "attempted": true, + "auto_advance": false, + "automatic_tax": { + "enabled": false, + "status": null + }, + "billing_reason": "manual", + "charge": null, + "collection_method": "charge_automatically", + "created": 1000000000, + "currency": "usd", + "custom_fields": null, + "customer": "cus_NORMALIZED0001", + "customer_address": null, + "customer_email": "hamlet@zulip.com", + "customer_name": null, + "customer_phone": null, + "customer_shipping": null, + "customer_tax_exempt": "none", + "customer_tax_ids": [], + "default_payment_method": null, + "default_source": null, + "default_tax_rates": [], + "description": null, + "discount": null, + "discounts": [], + "due_date": null, + "effective_at": 1000000000, + "ending_balance": 0, + "footer": null, + "from_invoice": null, + "hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QM2RVSjJZbEx3bGZ5TnV6ZGQ2MEd1aTYwQjRuUElRLDkxMjYwOTky02007zWYSruV?s=ap", + "id": "in_NORMALIZED00000000000001", + "invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QM2RVSjJZbEx3bGZ5TnV6ZGQ2MEd1aTYwQjRuUElRLDkxMjYwOTky02007zWYSruV/pdf?s=ap", + "last_finalization_error": null, + "latest_revision": null, + "lines": { + "data": [ + { + "amount": 48000, + "amount_excluding_tax": 48000, + "currency": "usd", + "description": "Zulip Cloud Standard", + "discount_amounts": [], + "discountable": false, + "discounts": [], + "id": "il_NORMALIZED00000000000001", + "invoice_item": "ii_NORMALIZED00000000000001", + "livemode": false, + "metadata": {}, + "object": "line_item", + "period": { + "end": 1357095845, + "start": 1325473445 + }, + "plan": null, + "price": { + "active": false, + "billing_scheme": "per_unit", + "created": 1000000000, + "currency": "usd", + "custom_unit_amount": null, + "id": "price_NORMALIZED00000000000001", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_NORMALIZED0001", + "recurring": null, + "tax_behavior": "unspecified", + "tiers_mode": null, + "transform_quantity": null, + "type": "one_time", + "unit_amount": 8000, + "unit_amount_decimal": "8000" + }, + "proration": false, + "proration_details": { + "credited_items": null + }, + "quantity": 6, + "subscription": null, + "tax_amounts": [], + "tax_rates": [], + "type": "invoiceitem", + "unit_amount_excluding_tax": "8000" + }, + { + "amount": -48000, + "amount_excluding_tax": -48000, + "currency": "usd", + "description": "Payment (Card ending in 4242)", + "discount_amounts": [], + "discountable": false, + "discounts": [], + "id": "il_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", + "custom_unit_amount": null, + "id": "price_NORMALIZED00000000000002", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_NORMALIZED0002", + "recurring": null, + "tax_behavior": "unspecified", + "tiers_mode": null, + "transform_quantity": null, + "type": "one_time", + "unit_amount": -48000, + "unit_amount_decimal": "-48000" + }, + "proration": false, + "proration_details": { + "credited_items": null + }, + "quantity": 1, + "subscription": null, + "tax_amounts": [], + "tax_rates": [], + "type": "invoiceitem", + "unit_amount_excluding_tax": "-48000" + } + ], + "has_more": false, + "object": "list", + "total_count": 2, + "url": "/v1/invoices/in_NORMALIZED00000000000001/lines" + }, + "livemode": false, + "metadata": {}, + "next_payment_attempt": null, + "number": "NORMALI-0001", + "object": "invoice", + "on_behalf_of": null, + "paid": true, + "paid_out_of_band": false, + "payment_intent": null, + "payment_settings": { + "default_mandate": null, + "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, + "quote": null, + "receipt_number": null, + "rendering": { + "amount_tax_display": null, + "pdf": { + "page_size": "letter" + } + }, + "rendering_options": null, + "shipping_cost": null, + "shipping_details": null, + "starting_balance": 0, + "statement_descriptor": "Zulip Cloud Standard", + "status": "paid", + "status_transitions": { + "finalized_at": 1000000000, + "marked_uncollectible_at": null, + "paid_at": 1000000000, + "voided_at": null + }, + "subscription": null, + "subscription_details": { + "metadata": null + }, + "subtotal": 0, + "subtotal_excluding_tax": 0, + "tax": null, + "test_clock": null, + "total": 0, + "total_discount_amounts": [], + "total_excluding_tax": 0, + "total_tax_amounts": [], + "transfer_data": null, + "webhooks_delivered_at": null + } + }, + "id": "evt_1OFWDEDEQaroqDjsXU4t3ECE", + "livemode": false, + "object": "event", + "pending_webhooks": 1, + "request": { + "id": "req_NORMALIZED0006", + "idempotency_key": "e461b87c-d52e-4af6-a76e-c7717b66e633" + }, + "type": "invoice.payment_succeeded" + } + ], + "has_more": false, + "object": "list", + "url": "/v1/events" +} diff --git a/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Event.list.8.json b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Event.list.8.json new file mode 100644 index 0000000000..6d922067af --- /dev/null +++ b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Event.list.8.json @@ -0,0 +1,6 @@ +{ + "data": [], + "has_more": false, + "object": "list", + "url": "/v1/events" +} diff --git a/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Invoice.create.1.json b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Invoice.create.1.json index 018781b959..ee4c6393e4 100644 --- a/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Invoice.create.1.json +++ b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Invoice.create.1.json @@ -2,9 +2,9 @@ "account_country": "US", "account_name": "Kandra Labs, Inc.", "account_tax_ids": null, - "amount_due": 7200, + "amount_due": 0, "amount_paid": 0, - "amount_remaining": 7200, + "amount_remaining": 0, "amount_shipping": 0, "application": null, "application_fee_amount": null, @@ -17,13 +17,13 @@ }, "billing_reason": "manual", "charge": null, - "collection_method": "send_invoice", + "collection_method": "charge_automatically", "created": 1000000000, "currency": "usd", "custom_fields": null, "customer": "cus_NORMALIZED0001", "customer_address": null, - "customer_email": "king@lear.org", + "customer_email": "hamlet@zulip.com", "customer_name": null, "customer_phone": null, "customer_shipping": null, @@ -35,7 +35,7 @@ "description": null, "discount": null, "discounts": [], - "due_date": 1000000000, + "due_date": null, "effective_at": null, "ending_balance": null, "footer": null, @@ -48,10 +48,10 @@ "lines": { "data": [ { - "amount": 14400, - "amount_excluding_tax": 14400, + "amount": 48000, + "amount_excluding_tax": 48000, "currency": "usd", - "description": "Zulip Plus - renewal", + "description": "Zulip Cloud Standard", "discount_amounts": [], "discountable": false, "discounts": [], @@ -61,8 +61,8 @@ "metadata": {}, "object": "line_item", "period": { - "end": 1000000000, - "start": 1000000000 + "end": 1357095845, + "start": 1325473445 }, "plan": null, "price": { @@ -83,29 +83,79 @@ "tiers_mode": null, "transform_quantity": null, "type": "one_time", - "unit_amount": 1600, - "unit_amount_decimal": "1600" + "unit_amount": 8000, + "unit_amount_decimal": "8000" }, "proration": false, "proration_details": { "credited_items": null }, - "quantity": 9, + "quantity": 6, "subscription": null, "tax_amounts": [], "tax_rates": [], "type": "invoiceitem", - "unit_amount_excluding_tax": "1600" + "unit_amount_excluding_tax": "8000" + }, + { + "amount": -48000, + "amount_excluding_tax": -48000, + "currency": "usd", + "description": "Payment (Card ending in 4242)", + "discount_amounts": [], + "discountable": false, + "discounts": [], + "id": "il_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", + "custom_unit_amount": null, + "id": "price_NORMALIZED00000000000002", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_NORMALIZED0002", + "recurring": null, + "tax_behavior": "unspecified", + "tiers_mode": null, + "transform_quantity": null, + "type": "one_time", + "unit_amount": -48000, + "unit_amount_decimal": "-48000" + }, + "proration": false, + "proration_details": { + "credited_items": null + }, + "quantity": 1, + "subscription": null, + "tax_amounts": [], + "tax_rates": [], + "type": "invoiceitem", + "unit_amount_excluding_tax": "-48000" } ], "has_more": false, "object": "list", - "total_count": 1, + "total_count": 2, "url": "/v1/invoices/in_NORMALIZED00000000000001/lines" }, "livemode": false, "metadata": {}, - "next_payment_attempt": null, + "next_payment_attempt": 1000000000, "number": null, "object": "invoice", "on_behalf_of": null, @@ -132,8 +182,8 @@ "rendering_options": null, "shipping_cost": null, "shipping_details": null, - "starting_balance": -7200, - "statement_descriptor": "Zulip Plus", + "starting_balance": 0, + "statement_descriptor": "Zulip Cloud Standard", "status": "draft", "status_transitions": { "finalized_at": null, @@ -145,13 +195,13 @@ "subscription_details": { "metadata": null }, - "subtotal": 14400, - "subtotal_excluding_tax": 14400, + "subtotal": 0, + "subtotal_excluding_tax": 0, "tax": null, "test_clock": null, - "total": 14400, + "total": 0, "total_discount_amounts": [], - "total_excluding_tax": 14400, + "total_excluding_tax": 0, "total_tax_amounts": [], "transfer_data": null, "webhooks_delivered_at": null diff --git a/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Invoice.create.2.json b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Invoice.create.2.json new file mode 100644 index 0000000000..a8b483910d --- /dev/null +++ b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Invoice.create.2.json @@ -0,0 +1,158 @@ +{ + "account_country": "US", + "account_name": "Kandra Labs, Inc.", + "account_tax_ids": null, + "amount_due": 95563, + "amount_paid": 0, + "amount_remaining": 95563, + "amount_shipping": 0, + "application": null, + "application_fee_amount": null, + "attempt_count": 0, + "attempted": false, + "auto_advance": true, + "automatic_tax": { + "enabled": false, + "status": null + }, + "billing_reason": "manual", + "charge": null, + "collection_method": "charge_automatically", + "created": 1000000000, + "currency": "usd", + "custom_fields": null, + "customer": "cus_NORMALIZED0001", + "customer_address": null, + "customer_email": "hamlet@zulip.com", + "customer_name": null, + "customer_phone": null, + "customer_shipping": null, + "customer_tax_exempt": "none", + "customer_tax_ids": [], + "default_payment_method": null, + "default_source": null, + "default_tax_rates": [], + "description": null, + "discount": null, + "discounts": [], + "due_date": null, + "effective_at": null, + "ending_balance": null, + "footer": null, + "from_invoice": null, + "hosted_invoice_url": null, + "id": "in_NORMALIZED00000000000002", + "invoice_pdf": null, + "last_finalization_error": null, + "latest_revision": null, + "lines": { + "data": [ + { + "amount": 96000, + "amount_excluding_tax": 96000, + "currency": "usd", + "description": "Zulip Plus - renewal", + "discount_amounts": [], + "discountable": false, + "discounts": [], + "id": "il_NORMALIZED00000000000003", + "invoice_item": "ii_NORMALIZED00000000000003", + "livemode": false, + "metadata": {}, + "object": "line_item", + "period": { + "end": 1000000000, + "start": 1000000000 + }, + "plan": null, + "price": { + "active": false, + "billing_scheme": "per_unit", + "created": 1000000000, + "currency": "usd", + "custom_unit_amount": null, + "id": "price_NORMALIZED00000000000003", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_NORMALIZED0003", + "recurring": null, + "tax_behavior": "unspecified", + "tiers_mode": null, + "transform_quantity": null, + "type": "one_time", + "unit_amount": 16000, + "unit_amount_decimal": "16000" + }, + "proration": false, + "proration_details": { + "credited_items": null + }, + "quantity": 6, + "subscription": null, + "tax_amounts": [], + "tax_rates": [], + "type": "invoiceitem", + "unit_amount_excluding_tax": "16000" + } + ], + "has_more": false, + "object": "list", + "total_count": 1, + "url": "/v1/invoices/in_NORMALIZED00000000000002/lines" + }, + "livemode": false, + "metadata": {}, + "next_payment_attempt": 1000000000, + "number": null, + "object": "invoice", + "on_behalf_of": null, + "paid": false, + "paid_out_of_band": false, + "payment_intent": null, + "payment_settings": { + "default_mandate": null, + "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, + "quote": null, + "receipt_number": null, + "rendering": { + "amount_tax_display": null, + "pdf": { + "page_size": "auto" + } + }, + "rendering_options": null, + "shipping_cost": null, + "shipping_details": null, + "starting_balance": -437, + "statement_descriptor": "Zulip Plus", + "status": "draft", + "status_transitions": { + "finalized_at": null, + "marked_uncollectible_at": null, + "paid_at": null, + "voided_at": null + }, + "subscription": null, + "subscription_details": { + "metadata": null + }, + "subtotal": 96000, + "subtotal_excluding_tax": 96000, + "tax": null, + "test_clock": null, + "total": 96000, + "total_discount_amounts": [], + "total_excluding_tax": 96000, + "total_tax_amounts": [], + "transfer_data": null, + "webhooks_delivered_at": null +} diff --git a/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Invoice.finalize_invoice.1.json b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Invoice.finalize_invoice.1.json index 414a984985..1fef87cfc0 100644 --- a/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Invoice.finalize_invoice.1.json +++ b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Invoice.finalize_invoice.1.json @@ -2,28 +2,28 @@ "account_country": "US", "account_name": "Kandra Labs, Inc.", "account_tax_ids": null, - "amount_due": 7200, + "amount_due": 0, "amount_paid": 0, - "amount_remaining": 7200, + "amount_remaining": 0, "amount_shipping": 0, "application": null, "application_fee_amount": null, "attempt_count": 0, - "attempted": false, - "auto_advance": true, + "attempted": true, + "auto_advance": false, "automatic_tax": { "enabled": false, "status": null }, "billing_reason": "manual", "charge": null, - "collection_method": "send_invoice", + "collection_method": "charge_automatically", "created": 1000000000, "currency": "usd", "custom_fields": null, "customer": "cus_NORMALIZED0001", "customer_address": null, - "customer_email": "king@lear.org", + "customer_email": "hamlet@zulip.com", "customer_name": null, "customer_phone": null, "customer_shipping": null, @@ -35,23 +35,23 @@ "description": null, "discount": null, "discounts": [], - "due_date": 1000000000, + "due_date": null, "effective_at": 1000000000, "ending_balance": 0, "footer": null, "from_invoice": null, - "hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QMWNxUW43THg4NGxpYkp1WlBGYkc1aEVYWWZuRnBULDkwNzk3MzMw0200l6cI0Ln4?s=ap", + "hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QM2RVSjJZbEx3bGZ5TnV6ZGQ2MEd1aTYwQjRuUElRLDkxMjYwOTky02007zWYSruV?s=ap", "id": "in_NORMALIZED00000000000001", - "invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QMWNxUW43THg4NGxpYkp1WlBGYkc1aEVYWWZuRnBULDkwNzk3MzMw0200l6cI0Ln4/pdf?s=ap", + "invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QM2RVSjJZbEx3bGZ5TnV6ZGQ2MEd1aTYwQjRuUElRLDkxMjYwOTky02007zWYSruV/pdf?s=ap", "last_finalization_error": null, "latest_revision": null, "lines": { "data": [ { - "amount": 14400, - "amount_excluding_tax": 14400, + "amount": 48000, + "amount_excluding_tax": 48000, "currency": "usd", - "description": "Zulip Plus - renewal", + "description": "Zulip Cloud Standard", "discount_amounts": [], "discountable": false, "discounts": [], @@ -61,8 +61,8 @@ "metadata": {}, "object": "line_item", "period": { - "end": 1000000000, - "start": 1000000000 + "end": 1357095845, + "start": 1325473445 }, "plan": null, "price": { @@ -83,24 +83,74 @@ "tiers_mode": null, "transform_quantity": null, "type": "one_time", - "unit_amount": 1600, - "unit_amount_decimal": "1600" + "unit_amount": 8000, + "unit_amount_decimal": "8000" }, "proration": false, "proration_details": { "credited_items": null }, - "quantity": 9, + "quantity": 6, "subscription": null, "tax_amounts": [], "tax_rates": [], "type": "invoiceitem", - "unit_amount_excluding_tax": "1600" + "unit_amount_excluding_tax": "8000" + }, + { + "amount": -48000, + "amount_excluding_tax": -48000, + "currency": "usd", + "description": "Payment (Card ending in 4242)", + "discount_amounts": [], + "discountable": false, + "discounts": [], + "id": "il_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", + "custom_unit_amount": null, + "id": "price_NORMALIZED00000000000002", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_NORMALIZED0002", + "recurring": null, + "tax_behavior": "unspecified", + "tiers_mode": null, + "transform_quantity": null, + "type": "one_time", + "unit_amount": -48000, + "unit_amount_decimal": "-48000" + }, + "proration": false, + "proration_details": { + "credited_items": null + }, + "quantity": 1, + "subscription": null, + "tax_amounts": [], + "tax_rates": [], + "type": "invoiceitem", + "unit_amount_excluding_tax": "-48000" } ], "has_more": false, "object": "list", - "total_count": 1, + "total_count": 2, "url": "/v1/invoices/in_NORMALIZED00000000000001/lines" }, "livemode": false, @@ -109,9 +159,9 @@ "number": "NORMALI-0001", "object": "invoice", "on_behalf_of": null, - "paid": false, + "paid": true, "paid_out_of_band": false, - "payment_intent": "pi_NORMALIZED00000000000001", + "payment_intent": null, "payment_settings": { "default_mandate": null, "payment_method_options": null, @@ -132,26 +182,26 @@ "rendering_options": null, "shipping_cost": null, "shipping_details": null, - "starting_balance": -7200, - "statement_descriptor": "Zulip Plus", - "status": "open", + "starting_balance": 0, + "statement_descriptor": "Zulip Cloud Standard", + "status": "paid", "status_transitions": { "finalized_at": 1000000000, "marked_uncollectible_at": null, - "paid_at": null, + "paid_at": 1000000000, "voided_at": null }, "subscription": null, "subscription_details": { "metadata": null }, - "subtotal": 14400, - "subtotal_excluding_tax": 14400, + "subtotal": 0, + "subtotal_excluding_tax": 0, "tax": null, "test_clock": null, - "total": 14400, + "total": 0, "total_discount_amounts": [], - "total_excluding_tax": 14400, + "total_excluding_tax": 0, "total_tax_amounts": [], "transfer_data": null, "webhooks_delivered_at": null diff --git a/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Invoice.finalize_invoice.2.json b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Invoice.finalize_invoice.2.json new file mode 100644 index 0000000000..45e6665898 --- /dev/null +++ b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Invoice.finalize_invoice.2.json @@ -0,0 +1,158 @@ +{ + "account_country": "US", + "account_name": "Kandra Labs, Inc.", + "account_tax_ids": null, + "amount_due": 95563, + "amount_paid": 0, + "amount_remaining": 95563, + "amount_shipping": 0, + "application": null, + "application_fee_amount": null, + "attempt_count": 0, + "attempted": false, + "auto_advance": true, + "automatic_tax": { + "enabled": false, + "status": null + }, + "billing_reason": "manual", + "charge": null, + "collection_method": "charge_automatically", + "created": 1000000000, + "currency": "usd", + "custom_fields": null, + "customer": "cus_NORMALIZED0001", + "customer_address": null, + "customer_email": "hamlet@zulip.com", + "customer_name": null, + "customer_phone": null, + "customer_shipping": null, + "customer_tax_exempt": "none", + "customer_tax_ids": [], + "default_payment_method": null, + "default_source": null, + "default_tax_rates": [], + "description": null, + "discount": null, + "discounts": [], + "due_date": null, + "effective_at": 1000000000, + "ending_balance": 0, + "footer": null, + "from_invoice": null, + "hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QM2RVWjh6dWt1bmR6dGpDeGZob3ZJRFVFTDc0NFJlLDkxMjYwOTk00200hq2OrGJy?s=ap", + "id": "in_NORMALIZED00000000000002", + "invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QM2RVWjh6dWt1bmR6dGpDeGZob3ZJRFVFTDc0NFJlLDkxMjYwOTk00200hq2OrGJy/pdf?s=ap", + "last_finalization_error": null, + "latest_revision": null, + "lines": { + "data": [ + { + "amount": 96000, + "amount_excluding_tax": 96000, + "currency": "usd", + "description": "Zulip Plus - renewal", + "discount_amounts": [], + "discountable": false, + "discounts": [], + "id": "il_NORMALIZED00000000000003", + "invoice_item": "ii_NORMALIZED00000000000003", + "livemode": false, + "metadata": {}, + "object": "line_item", + "period": { + "end": 1000000000, + "start": 1000000000 + }, + "plan": null, + "price": { + "active": false, + "billing_scheme": "per_unit", + "created": 1000000000, + "currency": "usd", + "custom_unit_amount": null, + "id": "price_NORMALIZED00000000000003", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_NORMALIZED0003", + "recurring": null, + "tax_behavior": "unspecified", + "tiers_mode": null, + "transform_quantity": null, + "type": "one_time", + "unit_amount": 16000, + "unit_amount_decimal": "16000" + }, + "proration": false, + "proration_details": { + "credited_items": null + }, + "quantity": 6, + "subscription": null, + "tax_amounts": [], + "tax_rates": [], + "type": "invoiceitem", + "unit_amount_excluding_tax": "16000" + } + ], + "has_more": false, + "object": "list", + "total_count": 1, + "url": "/v1/invoices/in_NORMALIZED00000000000002/lines" + }, + "livemode": false, + "metadata": {}, + "next_payment_attempt": 1000000000, + "number": "NORMALI-0002", + "object": "invoice", + "on_behalf_of": null, + "paid": false, + "paid_out_of_band": false, + "payment_intent": "pi_NORMALIZED00000000000002", + "payment_settings": { + "default_mandate": null, + "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, + "quote": null, + "receipt_number": null, + "rendering": { + "amount_tax_display": null, + "pdf": { + "page_size": "letter" + } + }, + "rendering_options": null, + "shipping_cost": null, + "shipping_details": null, + "starting_balance": -437, + "statement_descriptor": "Zulip Plus", + "status": "open", + "status_transitions": { + "finalized_at": 1000000000, + "marked_uncollectible_at": null, + "paid_at": null, + "voided_at": null + }, + "subscription": null, + "subscription_details": { + "metadata": null + }, + "subtotal": 96000, + "subtotal_excluding_tax": 96000, + "tax": null, + "test_clock": null, + "total": 96000, + "total_discount_amounts": [], + "total_excluding_tax": 96000, + "total_tax_amounts": [], + "transfer_data": null, + "webhooks_delivered_at": null +} diff --git a/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Invoice.list.1.json b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Invoice.list.1.json index 98610a3348..e39960ab72 100644 --- a/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Invoice.list.1.json +++ b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--Invoice.list.1.json @@ -1,164 +1,5 @@ { - "data": [ - { - "account_country": "US", - "account_name": "Kandra Labs, Inc.", - "account_tax_ids": null, - "amount_due": 7200, - "amount_paid": 0, - "amount_remaining": 7200, - "amount_shipping": 0, - "application": null, - "application_fee_amount": null, - "attempt_count": 0, - "attempted": false, - "auto_advance": true, - "automatic_tax": { - "enabled": false, - "status": null - }, - "billing_reason": "manual", - "charge": null, - "collection_method": "send_invoice", - "created": 1000000000, - "currency": "usd", - "custom_fields": null, - "customer": "cus_NORMALIZED0001", - "customer_address": null, - "customer_email": "king@lear.org", - "customer_name": null, - "customer_phone": null, - "customer_shipping": null, - "customer_tax_exempt": "none", - "customer_tax_ids": [], - "default_payment_method": null, - "default_source": null, - "default_tax_rates": [], - "description": null, - "discount": null, - "discounts": [], - "due_date": 1000000000, - "effective_at": 1000000000, - "ending_balance": 0, - "footer": null, - "from_invoice": null, - "hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QMWNxUW43THg4NGxpYkp1WlBGYkc1aEVYWWZuRnBULDkwNzk3MzMw0200l6cI0Ln4?s=ap", - "id": "in_NORMALIZED00000000000001", - "invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED000001/test_NORMALIZED01a3dERVFhcm9xRGpzLF9QMWNxUW43THg4NGxpYkp1WlBGYkc1aEVYWWZuRnBULDkwNzk3MzMw0200l6cI0Ln4/pdf?s=ap", - "last_finalization_error": null, - "latest_revision": null, - "lines": { - "data": [ - { - "amount": 14400, - "amount_excluding_tax": 14400, - "currency": "usd", - "description": "Zulip Plus - renewal", - "discount_amounts": [], - "discountable": false, - "discounts": [], - "id": "il_NORMALIZED00000000000001", - "invoice_item": "ii_NORMALIZED00000000000001", - "livemode": false, - "metadata": {}, - "object": "line_item", - "period": { - "end": 1000000000, - "start": 1000000000 - }, - "plan": null, - "price": { - "active": false, - "billing_scheme": "per_unit", - "created": 1000000000, - "currency": "usd", - "custom_unit_amount": null, - "id": "price_NORMALIZED00000000000001", - "livemode": false, - "lookup_key": null, - "metadata": {}, - "nickname": null, - "object": "price", - "product": "prod_NORMALIZED0001", - "recurring": null, - "tax_behavior": "unspecified", - "tiers_mode": null, - "transform_quantity": null, - "type": "one_time", - "unit_amount": 1600, - "unit_amount_decimal": "1600" - }, - "proration": false, - "proration_details": { - "credited_items": null - }, - "quantity": 9, - "subscription": null, - "tax_amounts": [], - "tax_rates": [], - "type": "invoiceitem", - "unit_amount_excluding_tax": "1600" - } - ], - "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", - "on_behalf_of": null, - "paid": false, - "paid_out_of_band": false, - "payment_intent": "pi_NORMALIZED00000000000001", - "payment_settings": { - "default_mandate": null, - "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, - "quote": null, - "receipt_number": null, - "rendering": { - "amount_tax_display": null, - "pdf": { - "page_size": "letter" - } - }, - "rendering_options": null, - "shipping_cost": null, - "shipping_details": null, - "starting_balance": -7200, - "statement_descriptor": "Zulip Plus", - "status": "open", - "status_transitions": { - "finalized_at": 1000000000, - "marked_uncollectible_at": null, - "paid_at": null, - "voided_at": null - }, - "subscription": null, - "subscription_details": { - "metadata": null - }, - "subtotal": 14400, - "subtotal_excluding_tax": 14400, - "tax": null, - "test_clock": null, - "total": 14400, - "total_discount_amounts": [], - "total_excluding_tax": 14400, - "total_tax_amounts": [], - "transfer_data": null, - "webhooks_delivered_at": null - } - ], + "data": [], "has_more": false, "object": "list", "url": "/v1/invoices" diff --git a/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--InvoiceItem.create.1.json b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--InvoiceItem.create.1.json index 71d7befb71..fcb1c3c2e9 100644 --- a/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--InvoiceItem.create.1.json +++ b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--InvoiceItem.create.1.json @@ -1,12 +1,12 @@ { - "amount": 14400, + "amount": -48000, "currency": "usd", "customer": "cus_NORMALIZED0001", "date": 1000000000, - "description": "Zulip Plus - renewal", + "description": "Payment (Card ending in 4242)", "discountable": false, "discounts": [], - "id": "ii_NORMALIZED00000000000001", + "id": "ii_NORMALIZED00000000000002", "invoice": null, "livemode": false, "metadata": {}, @@ -22,26 +22,26 @@ "created": 1000000000, "currency": "usd", "custom_unit_amount": null, - "id": "price_NORMALIZED00000000000001", + "id": "price_NORMALIZED00000000000002", "livemode": false, "lookup_key": null, "metadata": {}, "nickname": null, "object": "price", - "product": "prod_NORMALIZED0001", + "product": "prod_NORMALIZED0002", "recurring": null, "tax_behavior": "unspecified", "tiers_mode": null, "transform_quantity": null, "type": "one_time", - "unit_amount": 1600, - "unit_amount_decimal": "1600" + "unit_amount": -48000, + "unit_amount_decimal": "-48000" }, "proration": false, - "quantity": 9, + "quantity": 1, "subscription": null, "tax_rates": [], "test_clock": null, - "unit_amount": 1600, - "unit_amount_decimal": "1600" + "unit_amount": -48000, + "unit_amount_decimal": "-48000" } diff --git a/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--InvoiceItem.create.2.json b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--InvoiceItem.create.2.json new file mode 100644 index 0000000000..11622f30a7 --- /dev/null +++ b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--InvoiceItem.create.2.json @@ -0,0 +1,47 @@ +{ + "amount": 48000, + "currency": "usd", + "customer": "cus_NORMALIZED0001", + "date": 1000000000, + "description": "Zulip Cloud Standard", + "discountable": false, + "discounts": [], + "id": "ii_NORMALIZED00000000000001", + "invoice": null, + "livemode": false, + "metadata": {}, + "object": "invoiceitem", + "period": { + "end": 1357095845, + "start": 1325473445 + }, + "plan": null, + "price": { + "active": false, + "billing_scheme": "per_unit", + "created": 1000000000, + "currency": "usd", + "custom_unit_amount": null, + "id": "price_NORMALIZED00000000000001", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_NORMALIZED0001", + "recurring": null, + "tax_behavior": "unspecified", + "tiers_mode": null, + "transform_quantity": null, + "type": "one_time", + "unit_amount": 8000, + "unit_amount_decimal": "8000" + }, + "proration": false, + "quantity": 6, + "subscription": null, + "tax_rates": [], + "test_clock": null, + "unit_amount": 8000, + "unit_amount_decimal": "8000" +} diff --git a/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--InvoiceItem.create.3.json b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--InvoiceItem.create.3.json new file mode 100644 index 0000000000..5b9f96e06e --- /dev/null +++ b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--InvoiceItem.create.3.json @@ -0,0 +1,47 @@ +{ + "amount": 96000, + "currency": "usd", + "customer": "cus_NORMALIZED0001", + "date": 1000000000, + "description": "Zulip Plus - renewal", + "discountable": false, + "discounts": [], + "id": "ii_NORMALIZED00000000000003", + "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", + "custom_unit_amount": null, + "id": "price_NORMALIZED00000000000003", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_NORMALIZED0003", + "recurring": null, + "tax_behavior": "unspecified", + "tiers_mode": null, + "transform_quantity": null, + "type": "one_time", + "unit_amount": 16000, + "unit_amount_decimal": "16000" + }, + "proration": false, + "quantity": 6, + "subscription": null, + "tax_rates": [], + "test_clock": null, + "unit_amount": 16000, + "unit_amount_decimal": "16000" +} diff --git a/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--PaymentIntent.create.1.json b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--PaymentIntent.create.1.json new file mode 100644 index 0000000000..06083e646b --- /dev/null +++ b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--PaymentIntent.create.1.json @@ -0,0 +1,197 @@ +{ + "amount": 48000, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 48000, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": null, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "charges": { + "data": [ + { + "amount": 48000, + "amount_captured": 48000, + "amount_refunded": 0, + "application": null, + "application_fee": null, + "application_fee_amount": null, + "balance_transaction": "txn_NORMALIZED00000000000002", + "billing_details": { + "address": { + "city": null, + "country": null, + "line1": null, + "line2": null, + "postal_code": null, + "state": null + }, + "email": null, + "name": null, + "phone": null + }, + "calculated_statement_descriptor": "ZULIP CLOUD STANDARD", + "captured": true, + "created": 1000000000, + "currency": "usd", + "customer": "cus_NORMALIZED0001", + "description": "Upgrade to Zulip Cloud Standard, $80.0 x 6", + "destination": null, + "dispute": null, + "disputed": false, + "failure_balance_transaction": null, + "failure_code": null, + "failure_message": null, + "fraud_details": {}, + "id": "ch_NORMALIZED00000000000001", + "invoice": null, + "livemode": false, + "metadata": { + "billing_modality": "charge_automatically", + "billing_schedule": "1", + "license_management": "automatic", + "licenses": "6", + "price_per_license": "8000", + "realm_id": "1", + "realm_str": "zulip", + "seat_count": "6", + "type": "upgrade", + "user_email": "hamlet@zulip.com", + "user_id": "10" + }, + "object": "charge", + "on_behalf_of": null, + "order": null, + "outcome": { + "network_status": "approved_by_network", + "reason": null, + "risk_level": "normal", + "risk_score": 0, + "seller_message": "Payment complete.", + "type": "authorized" + }, + "paid": true, + "payment_intent": "pi_NORMALIZED00000000000001", + "payment_method": "pm_1OFWD8DEQaroqDjsbeQean1W", + "payment_method_details": { + "card": { + "amount_authorized": 48000, + "brand": "visa", + "checks": { + "address_line1_check": null, + "address_postal_code_check": null, + "cvc_check": "pass" + }, + "country": "US", + "exp_month": 11, + "exp_year": 2024, + "extended_authorization": { + "status": "disabled" + }, + "fingerprint": "NORMALIZED000001", + "funding": "credit", + "incremental_authorization": { + "status": "unavailable" + }, + "installments": null, + "last4": "4242", + "mandate": null, + "multicapture": { + "status": "unavailable" + }, + "network": "visa", + "network_token": { + "used": false + }, + "overcapture": { + "maximum_amount_capturable": 48000, + "status": "unavailable" + }, + "three_d_secure": null, + "wallet": null + }, + "type": "card" + }, + "receipt_email": "hamlet@zulip.com", + "receipt_number": null, + "receipt_url": "https://pay.stripe.com/receipts/payment/CAcaFwoVYWNjdF8xN3ZUa3dERVFhcm9xRGpzKL7c-6oGMgaYBsyBLkU6LBY06AqW4sG6Nuedb6GO0h-2XftyTbkGsSZgOqR7dVByEEd6Kg45YU78TWSi", + "refunded": false, + "refunds": { + "data": [], + "has_more": false, + "object": "list", + "total_count": 0, + "url": "/v1/charges/ch_NORMALIZED00000000000001/refunds" + }, + "review": null, + "shipping": null, + "source": null, + "source_transfer": null, + "statement_descriptor": "Zulip Cloud Standard", + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + ], + "has_more": false, + "object": "list", + "total_count": 1, + "url": "/v1/charges?payment_intent=pi_NORMALIZED00000000000001" + }, + "client_secret": "pi_NORMALIZED00000000000001_secret_8LrrfmEMVbU1QNd1Y1e4LW91d", + "confirmation_method": "automatic", + "created": 1000000000, + "currency": "usd", + "customer": "cus_NORMALIZED0001", + "description": "Upgrade to Zulip Cloud Standard, $80.0 x 6", + "id": "pi_NORMALIZED00000000000001", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_NORMALIZED00000000000001", + "livemode": false, + "metadata": { + "billing_modality": "charge_automatically", + "billing_schedule": "1", + "license_management": "automatic", + "licenses": "6", + "price_per_license": "8000", + "realm_id": "1", + "realm_str": "zulip", + "seat_count": "6", + "type": "upgrade", + "user_email": "hamlet@zulip.com", + "user_id": "10" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OFWD8DEQaroqDjsbeQean1W", + "payment_method_configuration_details": null, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + } + }, + "payment_method_types": [ + "card" + ], + "processing": null, + "receipt_email": "hamlet@zulip.com", + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": "Zulip Cloud Standard", + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null +} diff --git a/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--SetupIntent.create.1.json b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--SetupIntent.create.1.json new file mode 100644 index 0000000000..fe85b57a67 --- /dev/null +++ b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--SetupIntent.create.1.json @@ -0,0 +1,34 @@ +{ + "application": null, + "automatic_payment_methods": null, + "cancellation_reason": null, + "client_secret": "seti_1OFWD8DEQaroqDjsu3EeopFr_secret_P3dUrWNNNJDJda9CTGTiu6kWd7e78Hc", + "created": 1000000000, + "customer": "cus_NORMALIZED0001", + "description": null, + "flow_directions": null, + "id": "seti_1OFWD8DEQaroqDjsu3EeopFr", + "last_setup_error": null, + "latest_attempt": "setatt_1OFWD8DEQaroqDjs0k9wJgDn", + "livemode": false, + "mandate": null, + "metadata": {}, + "next_action": null, + "object": "setup_intent", + "on_behalf_of": null, + "payment_method": "pm_1OFWD8DEQaroqDjsbeQean1W", + "payment_method_configuration_details": null, + "payment_method_options": { + "card": { + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + } + }, + "payment_method_types": [ + "card" + ], + "single_use_mandate": null, + "status": "succeeded", + "usage": "off_session" +} diff --git a/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--SetupIntent.list.1.json b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--SetupIntent.list.1.json new file mode 100644 index 0000000000..1e562bacfa --- /dev/null +++ b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--SetupIntent.list.1.json @@ -0,0 +1,41 @@ +{ + "data": [ + { + "application": null, + "automatic_payment_methods": null, + "cancellation_reason": null, + "client_secret": "seti_1OFWD6DEQaroqDjs3zCoSlTZ_secret_P3dUwq68OPuVM1iVvU4GAg9oUOC6CxQ", + "created": 1000000000, + "customer": "cus_NORMALIZED0001", + "description": null, + "flow_directions": null, + "id": "seti_1OFWD6DEQaroqDjs3zCoSlTZ", + "last_setup_error": null, + "latest_attempt": null, + "livemode": false, + "mandate": null, + "metadata": {}, + "next_action": null, + "object": "setup_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": null, + "payment_method_options": { + "card": { + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + } + }, + "payment_method_types": [ + "card" + ], + "single_use_mandate": null, + "status": "requires_payment_method", + "usage": "off_session" + } + ], + "has_more": true, + "object": "list", + "url": "/v1/setup_intents" +} diff --git a/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--SetupIntent.retrieve.1.json b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--SetupIntent.retrieve.1.json new file mode 100644 index 0000000000..fe85b57a67 --- /dev/null +++ b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--SetupIntent.retrieve.1.json @@ -0,0 +1,34 @@ +{ + "application": null, + "automatic_payment_methods": null, + "cancellation_reason": null, + "client_secret": "seti_1OFWD8DEQaroqDjsu3EeopFr_secret_P3dUrWNNNJDJda9CTGTiu6kWd7e78Hc", + "created": 1000000000, + "customer": "cus_NORMALIZED0001", + "description": null, + "flow_directions": null, + "id": "seti_1OFWD8DEQaroqDjsu3EeopFr", + "last_setup_error": null, + "latest_attempt": "setatt_1OFWD8DEQaroqDjs0k9wJgDn", + "livemode": false, + "mandate": null, + "metadata": {}, + "next_action": null, + "object": "setup_intent", + "on_behalf_of": null, + "payment_method": "pm_1OFWD8DEQaroqDjsbeQean1W", + "payment_method_configuration_details": null, + "payment_method_options": { + "card": { + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + } + }, + "payment_method_types": [ + "card" + ], + "single_use_mandate": null, + "status": "succeeded", + "usage": "off_session" +} diff --git a/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--checkout.Session.create.1.json b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--checkout.Session.create.1.json new file mode 100644 index 0000000000..91331fe43d --- /dev/null +++ b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--checkout.Session.create.1.json @@ -0,0 +1,73 @@ +{ + "after_expiration": null, + "allow_promotion_codes": null, + "amount_subtotal": null, + "amount_total": null, + "automatic_tax": { + "enabled": false, + "status": null + }, + "billing_address_collection": null, + "cancel_url": "http://zulip.testserver/upgrade/", + "client_reference_id": null, + "client_secret": null, + "consent": null, + "consent_collection": null, + "created": 1000000000, + "currency": null, + "currency_conversion": null, + "custom_fields": [], + "custom_text": { + "shipping_address": null, + "submit": null, + "terms_of_service_acceptance": null + }, + "customer": "cus_NORMALIZED0001", + "customer_creation": null, + "customer_details": { + "address": null, + "email": "hamlet@zulip.com", + "name": null, + "phone": null, + "tax_exempt": null, + "tax_ids": null + }, + "customer_email": null, + "expires_at": 1000000000, + "id": "cs_test_NORMALIZED02G79EQYyYv79XCeVMX78daZGkrG0fTQA9XJtnRTLvJd6WzC", + "invoice": null, + "invoice_creation": null, + "livemode": false, + "locale": null, + "metadata": { + "type": "card_update", + "user_id": "10" + }, + "mode": "setup", + "object": "checkout.session", + "payment_intent": null, + "payment_link": null, + "payment_method_collection": "always", + "payment_method_configuration_details": null, + "payment_method_options": {}, + "payment_method_types": [ + "card" + ], + "payment_status": "no_payment_required", + "phone_number_collection": { + "enabled": false + }, + "recovered_from": null, + "setup_intent": "seti_1OFWD6DEQaroqDjs3zCoSlTZ", + "shipping": null, + "shipping_address_collection": null, + "shipping_options": [], + "shipping_rate": null, + "status": "open", + "submit_type": null, + "subscription": null, + "success_url": "http://zulip.testserver/billing/event_status?stripe_session_id={CHECKOUT_SESSION_ID}", + "total_details": null, + "ui_mode": "hosted", + "url": "https://checkout.stripe.com/c/pay/cs_test_NORMALIZED02G79EQYyYv79XCeVMX78daZGkrG0fTQA9XJtnRTLvJd6WzC#fidkdWxOYHwnPyd1blpxYHZxWl1UZjFOczZJXUE2PUpzUWNPV2ZpdlFzUCcpJ2N3amhWYHdzYHcnP3F3cGApJ2lkfGpwcVF8dWAnPyd2bGtiaWBaZmppcGhrJyknYGtkZ2lgVWlkZmBtamlhYHd2Jz9xd3BgeCUl" +} diff --git a/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--checkout.Session.list.1.json b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--checkout.Session.list.1.json new file mode 100644 index 0000000000..58057b3884 --- /dev/null +++ b/corporate/tests/stripe_fixtures/switch_realm_from_standard_to_plus_plan--checkout.Session.list.1.json @@ -0,0 +1,80 @@ +{ + "data": [ + { + "after_expiration": null, + "allow_promotion_codes": null, + "amount_subtotal": null, + "amount_total": null, + "automatic_tax": { + "enabled": false, + "status": null + }, + "billing_address_collection": null, + "cancel_url": "http://zulip.testserver/upgrade/", + "client_reference_id": null, + "client_secret": null, + "consent": null, + "consent_collection": null, + "created": 1000000000, + "currency": null, + "currency_conversion": null, + "custom_fields": [], + "custom_text": { + "shipping_address": null, + "submit": null, + "terms_of_service_acceptance": null + }, + "customer": "cus_NORMALIZED0001", + "customer_creation": null, + "customer_details": { + "address": null, + "email": "hamlet@zulip.com", + "name": null, + "phone": null, + "tax_exempt": null, + "tax_ids": null + }, + "customer_email": null, + "expires_at": 1000000000, + "id": "cs_test_NORMALIZED02G79EQYyYv79XCeVMX78daZGkrG0fTQA9XJtnRTLvJd6WzC", + "invoice": null, + "invoice_creation": null, + "livemode": false, + "locale": null, + "metadata": { + "type": "card_update", + "user_id": "10" + }, + "mode": "setup", + "object": "checkout.session", + "payment_intent": null, + "payment_link": null, + "payment_method_collection": "always", + "payment_method_configuration_details": null, + "payment_method_options": {}, + "payment_method_types": [ + "card" + ], + "payment_status": "no_payment_required", + "phone_number_collection": { + "enabled": false + }, + "recovered_from": null, + "setup_intent": "seti_1OFWD6DEQaroqDjs3zCoSlTZ", + "shipping": null, + "shipping_address_collection": null, + "shipping_options": [], + "shipping_rate": null, + "status": "open", + "submit_type": null, + "subscription": null, + "success_url": "http://zulip.testserver/billing/event_status?stripe_session_id={CHECKOUT_SESSION_ID}", + "total_details": null, + "ui_mode": "hosted", + "url": "https://checkout.stripe.com/c/pay/cs_test_NORMALIZED02G79EQYyYv79XCeVMX78daZGkrG0fTQA9XJtnRTLvJd6WzC#fidkdWxOYHwnPyd1blpxYHZxWl1UZjFOczZJXUE2PUpzUWNPV2ZpdlFzUCcpJ2N3amhWYHdzYHcnP3F3cGApJ2lkfGpwcVF8dWAnPyd2bGtiaWBaZmppcGhrJyknYGtkZ2lgVWlkZmBtamlhYHd2Jz9xd3BgeCUl" + } + ], + "has_more": true, + "object": "list", + "url": "/v1/checkout/sessions" +} diff --git a/corporate/tests/test_stripe.py b/corporate/tests/test_stripe.py index 483028d28c..f6ae872a3d 100644 --- a/corporate/tests/test_stripe.py +++ b/corporate/tests/test_stripe.py @@ -67,7 +67,6 @@ from corporate.lib.stripe import ( sign_string, stripe_customer_has_credit_card_as_default_payment_method, stripe_get_customer, - switch_realm_from_standard_to_plus_plan, unsign_string, update_license_ledger_for_automanaged_plan, update_license_ledger_for_manual_plan, @@ -78,6 +77,7 @@ from corporate.lib.support import ( approve_realm_sponsorship, attach_discount_to_realm, get_discount_for_realm, + switch_realm_from_standard_to_plus_plan, update_realm_billing_method, update_realm_sponsorship_status, ) @@ -3508,13 +3508,15 @@ class StripeTest(StripeTestCase): self.assertEqual(row.email_expected_to_be_sent, email_found) @mock_stripe() - def test_switch_realm_from_standard_to_plus_plan(self, *mock: Mock) -> None: + def test_change_plan_tier_from_standard_to_plus(self, *mock: Mock) -> None: iago = self.example_user("iago") realm = iago.realm + iago_billing_session = RealmBillingSession(iago) + iago_billing_session.update_or_create_customer() # Test upgrading to Plus when realm has no active subscription with self.assertRaises(BillingError) as billing_context: - switch_realm_from_standard_to_plus_plan(realm) + iago_billing_session.do_change_plan_to_new_tier(CustomerPlan.PLUS) self.assertEqual( "Organization does not have an active plan", billing_context.exception.error_description, @@ -3525,14 +3527,15 @@ class StripeTest(StripeTestCase): ) # Test upgrading to Plus when realm has no stripe_customer_id with self.assertRaises(BillingError) as billing_context: - switch_realm_from_standard_to_plus_plan(realm) + iago_billing_session.do_change_plan_to_new_tier(CustomerPlan.PLUS) self.assertEqual( "Organization missing Stripe customer.", billing_context.exception.error_description ) king = self.lear_user("king") realm = king.realm - customer = RealmBillingSession(king).update_or_create_stripe_customer() + king_billing_session = RealmBillingSession(king) + customer = king_billing_session.update_or_create_stripe_customer() plan = CustomerPlan.objects.create( customer=customer, automanage_licenses=True, @@ -3553,7 +3556,13 @@ class StripeTest(StripeTestCase): plan.price_per_license = get_price_per_license(CustomerPlan.STANDARD, CustomerPlan.MONTHLY) plan.save(update_fields=["invoiced_through", "price_per_license"]) - switch_realm_from_standard_to_plus_plan(realm) + with self.assertRaises(BillingError) as billing_context: + king_billing_session.do_change_plan_to_new_tier(CustomerPlan.STANDARD) + self.assertEqual( + "Invalid change of customer plan tier.", billing_context.exception.error_description + ) + + king_billing_session.do_change_plan_to_new_tier(CustomerPlan.PLUS) plan.refresh_from_db() self.assertEqual(plan.status, CustomerPlan.ENDED) @@ -4838,3 +4847,20 @@ class TestSupportBillingHelpers(StripeTestCase): expected_extra_data = {"charge_automatically": plan.charge_automatically} self.assertEqual(realm_audit_log.acting_user, iago) self.assertEqual(realm_audit_log.extra_data, expected_extra_data) + + @mock_stripe() + def test_switch_realm_from_standard_to_plus_plan(self, *mocks: Mock) -> None: + user = self.example_user("hamlet") + self.login_user(user) + self.add_card_and_upgrade(user) + customer = get_customer_by_realm(user.realm) + assert customer is not None + original_plan = get_current_plan_by_customer(customer) + assert original_plan is not None + self.assertEqual(original_plan.tier, CustomerPlan.STANDARD) + + switch_realm_from_standard_to_plus_plan(user.realm) + customer.refresh_from_db() + new_plan = get_current_plan_by_customer(customer) + assert new_plan is not None + self.assertEqual(new_plan.tier, CustomerPlan.PLUS) diff --git a/zilencer/management/commands/switch_realm_from_standard_to_plus_plan.py b/zilencer/management/commands/switch_realm_from_standard_to_plus_plan.py index c11f553a10..6536e31751 100644 --- a/zilencer/management/commands/switch_realm_from_standard_to_plus_plan.py +++ b/zilencer/management/commands/switch_realm_from_standard_to_plus_plan.py @@ -7,7 +7,8 @@ from typing_extensions import override from zerver.lib.management import ZulipBaseCommand if settings.BILLING_ENABLED: - from corporate.lib.stripe import switch_realm_from_standard_to_plus_plan + from corporate.lib.stripe import RealmBillingSession + from corporate.models import CustomerPlan class Command(ZulipBaseCommand): @@ -23,4 +24,5 @@ class Command(ZulipBaseCommand): raise CommandError("No realm found.") if settings.BILLING_ENABLED: - switch_realm_from_standard_to_plus_plan(realm) + billing_session = RealmBillingSession(realm=realm) + billing_session.do_change_plan_to_new_tier(new_plan_tier=CustomerPlan.PLUS)