diff --git a/corporate/lib/stripe.py b/corporate/lib/stripe.py index 3ab45d4629..b2075d56aa 100644 --- a/corporate/lib/stripe.py +++ b/corporate/lib/stripe.py @@ -1613,9 +1613,9 @@ class BillingSession(ABC): } plan.next_invoice_date = new_end_date # We send a reminder email 2 months before the end date of - # remote server and remote realm fixed-price plans so that - # billing support can follow-up about continuing service. - # Reset it when we are extending the end_date. + # fixed-price plans so that billing support can follow-up + # about continuing service. Reset it when we are extending + # the end_date. reminder_to_review_plan_email_sent_changed_extra_data = None if ( plan.reminder_to_review_plan_email_sent @@ -5389,29 +5389,29 @@ def invoice_plans_as_needed(event_time: datetime | None = None) -> None: assert plan.next_invoice_date is not None # for mypy - if remote_server: - if ( - plan.fixed_price is not None - and not plan.reminder_to_review_plan_email_sent - and plan.end_date is not None # for mypy - # The max gap between two months is 62 days. (1 Jul - 1 Sep) - and plan.end_date - plan.next_invoice_date <= timedelta(days=62) - ): - context = { - "billing_entity": billing_session.billing_entity_display_name, - "end_date": plan.end_date.strftime("%Y-%m-%d"), - "support_url": billing_session.support_url(), - "notice_reason": "fixed_price_plan_ends_soon", - } - send_email( - "zerver/emails/internal_billing_notice", - to_emails=[BILLING_SUPPORT_EMAIL], - from_address=FromAddress.tokenized_no_reply_address(), - context=context, - ) - plan.reminder_to_review_plan_email_sent = True - plan.save(update_fields=["reminder_to_review_plan_email_sent"]) + if ( + plan.fixed_price is not None + and not plan.reminder_to_review_plan_email_sent + and plan.end_date is not None # for mypy + # The max gap between two months is 62 days. (1 Jul - 1 Sep) + and plan.end_date - plan.next_invoice_date <= timedelta(days=62) + ): + context = { + "billing_entity": billing_session.billing_entity_display_name, + "end_date": plan.end_date.strftime("%Y-%m-%d"), + "support_url": billing_session.support_url(), + "notice_reason": "fixed_price_plan_ends_soon", + } + send_email( + "zerver/emails/internal_billing_notice", + to_emails=[BILLING_SUPPORT_EMAIL], + from_address=FromAddress.tokenized_no_reply_address(), + context=context, + ) + plan.reminder_to_review_plan_email_sent = True + plan.save(update_fields=["reminder_to_review_plan_email_sent"]) + if remote_server: free_plan_with_no_next_plan = ( not plan.is_a_paid_plan() and plan.status == CustomerPlan.ACTIVE ) diff --git a/corporate/lib/stripe_event_handler.py b/corporate/lib/stripe_event_handler.py index 54e8882730..cb7f6b1fb0 100644 --- a/corporate/lib/stripe_event_handler.py +++ b/corporate/lib/stripe_event_handler.py @@ -87,15 +87,17 @@ def stripe_event_handler_decorator( def get_billing_session_for_stripe_webhook( customer: Customer, user_id: str | None ) -> RealmBillingSession | RemoteRealmBillingSession | RemoteServerBillingSession: - if customer.remote_realm is not None: # nocoverage + if customer.remote_realm is not None: return RemoteRealmBillingSession(customer.remote_realm) - elif customer.remote_server is not None: # nocoverage + elif customer.remote_server is not None: return RemoteServerBillingSession(customer.remote_server) else: - assert user_id is not None assert customer.realm is not None - user = get_active_user_profile_by_id_in_realm(int(user_id), customer.realm) - return RealmBillingSession(user) + if user_id: + user = get_active_user_profile_by_id_in_realm(int(user_id), customer.realm) + return RealmBillingSession(user) + else: + return RealmBillingSession(user=None, realm=customer.realm) # nocoverage @stripe_event_handler_decorator diff --git a/corporate/models.py b/corporate/models.py index 7ec678d115..4d36c10ee8 100644 --- a/corporate/models.py +++ b/corporate/models.py @@ -283,6 +283,8 @@ class CustomerPlanOffer(AbstractCustomerPlan): audit purpose with status=PROCESSED. """ + TIER_CLOUD_STANDARD = 1 + TIER_CLOUD_PLUS = 2 TIER_SELF_HOSTED_BASIC = 103 TIER_SELF_HOSTED_BUSINESS = 104 tier = models.SmallIntegerField() @@ -310,6 +312,8 @@ class CustomerPlanOffer(AbstractCustomerPlan): @staticmethod def name_from_tier(tier: int) -> str: return { + CustomerPlanOffer.TIER_CLOUD_STANDARD: "Zulip Cloud Standard", + CustomerPlanOffer.TIER_CLOUD_PLUS: "Zulip Cloud Plus", CustomerPlanOffer.TIER_SELF_HOSTED_BASIC: "Zulip Basic", CustomerPlanOffer.TIER_SELF_HOSTED_BUSINESS: "Zulip Business", }[tier] diff --git a/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--Customer.create.1.json b/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--Customer.create.1.json new file mode 100644 index 0000000000..bac0693536 --- /dev/null +++ b/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--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": "zulip (Zulip Dev)", + "discount": null, + "email": "hamlet@zulip.com", + "id": "upgrade_to_fixed_price_plus_plan--Customer.create.1.json", + "invoice_prefix": "NORMALIZED", + "invoice_settings": { + "custom_fields": null, + "default_payment_method": null, + "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/upgrade_to_fixed_price_plus_plan--Customer.retrieve.1.json b/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--Customer.retrieve.1.json new file mode 100644 index 0000000000..bac0693536 --- /dev/null +++ b/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--Customer.retrieve.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": "upgrade_to_fixed_price_plus_plan--Customer.create.1.json", + "invoice_prefix": "NORMALIZED", + "invoice_settings": { + "custom_fields": null, + "default_payment_method": null, + "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/upgrade_to_fixed_price_plus_plan--Customer.retrieve.2.json b/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--Customer.retrieve.2.json new file mode 100644 index 0000000000..b2b5bcbac4 --- /dev/null +++ b/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--Customer.retrieve.2.json @@ -0,0 +1,33 @@ +{ + "address": null, + "balance": 0, + "created": 1000000000, + "currency": "usd", + "default_currency": "usd", + "default_source": "src_NORMALIZED", + "delinquent": false, + "description": "zulip (Zulip Dev)", + "discount": null, + "email": "hamlet@zulip.com", + "id": "upgrade_to_fixed_price_plus_plan--Customer.create.1.json", + "invoice_prefix": "NORMALIZED", + "invoice_settings": { + "custom_fields": null, + "default_payment_method": null, + "footer": null, + "rendering_options": null + }, + "livemode": false, + "metadata": { + "realm_id": "1", + "realm_str": "zulip" + }, + "name": null, + "next_invoice_sequence": 3, + "object": "customer", + "phone": null, + "preferred_locales": [], + "shipping": null, + "tax_exempt": "none", + "test_clock": null +} diff --git a/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--Event.list.1.json b/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--Event.list.1.json new file mode 100644 index 0000000000..73ca7349c0 --- /dev/null +++ b/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--Event.list.1.json @@ -0,0 +1,191 @@ +{ + "data": [ + { + "api_version": "2020-08-27", + "created": 1000000000, + "data": { + "object": { + "account_country": "US", + "account_name": "Kandra Labs, Inc.", + "account_tax_ids": null, + "amount_due": 36000, + "amount_paid": 0, + "amount_remaining": 36000, + "amount_shipping": 0, + "application": null, + "application_fee_amount": null, + "attempt_count": 0, + "attempted": false, + "auto_advance": true, + "automatic_tax": { + "disabled_reason": null, + "enabled": false, + "liability": null, + "status": null + }, + "automatically_finalizes_at": null, + "billing_reason": "manual", + "charge": null, + "collection_method": "send_invoice", + "created": 1000000000, + "currency": "usd", + "custom_fields": null, + "customer": "cus_NORMALIZED", + "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": 1000000000, + "effective_at": 1000000000, + "ending_balance": 0, + "footer": null, + "from_invoice": null, + "hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED/test_NORMALIZED?s=ap", + "id": "upgrade_to_fixed_price_plus_plan--Event.list.1.json", + "invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED/test_NORMALIZED/pdf?s=ap", + "issuer": { + "type": "self" + }, + "last_finalization_error": null, + "latest_revision": null, + "lines": { + "data": [ + { + "amount": 36000, + "amount_excluding_tax": 36000, + "currency": "usd", + "description": "Zulip Cloud Plus - renewal", + "discount_amounts": [], + "discountable": false, + "discounts": [], + "id": "upgrade_to_fixed_price_plus_plan--Event.list.1.json", + "invoice": "upgrade_to_fixed_price_plus_plan--Event.list.1.json", + "invoice_item": "ii_NORMALIZED", + "livemode": false, + "metadata": {}, + "object": "line_item", + "period": { + "end": 1388620800, + "start": 1357084800 + }, + "plan": null, + "pretax_credit_amounts": [], + "price": { + "active": false, + "billing_scheme": "per_unit", + "created": 1000000000, + "currency": "usd", + "custom_unit_amount": null, + "id": "upgrade_to_fixed_price_plus_plan--Event.list.1.json", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_NORMALIZED", + "recurring": null, + "tax_behavior": "unspecified", + "tiers_mode": null, + "transform_quantity": null, + "type": "one_time", + "unit_amount": 36000, + "unit_amount_decimal": "36000" + }, + "proration": false, + "proration_details": { + "credited_items": null + }, + "quantity": 1, + "subscription": null, + "tax_amounts": [], + "tax_rates": [], + "type": "invoiceitem", + "unit_amount_excluding_tax": "36000" + } + ], + "has_more": false, + "object": "list", + "total_count": 1, + "url": "/v1/invoices/upgrade_to_fixed_price_plus_plan--Event.list.1.json/lines" + }, + "livemode": false, + "metadata": {}, + "next_payment_attempt": null, + "number": "NORMALIZED", + "object": "invoice", + "on_behalf_of": null, + "paid": false, + "paid_out_of_band": false, + "payment_intent": "pi_NORMALIZED", + "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" + }, + "template": null, + "template_version": null + }, + "rendering_options": null, + "shipping_cost": null, + "shipping_details": null, + "starting_balance": 0, + "statement_descriptor": "Zulip Cloud 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": 36000, + "subtotal_excluding_tax": 36000, + "tax": null, + "test_clock": null, + "total": 36000, + "total_discount_amounts": [], + "total_excluding_tax": 36000, + "total_pretax_credit_amounts": [], + "total_tax_amounts": [], + "transfer_data": null, + "webhooks_delivered_at": null + } + }, + "id": "upgrade_to_fixed_price_plus_plan--Event.list.1.json", + "livemode": false, + "object": "event", + "pending_webhooks": 0, + "request": { + "id": "upgrade_to_fixed_price_plus_plan--Event.list.1.json", + "idempotency_key": "00000000-0000-0000-0000-000000000000" + }, + "type": "invoice.finalized" + } + ], + "has_more": true, + "object": "list", + "url": "/v1/events" +} diff --git a/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--Event.list.2.json b/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--Event.list.2.json new file mode 100644 index 0000000000..8d03006844 --- /dev/null +++ b/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--Event.list.2.json @@ -0,0 +1,1039 @@ +{ + "data": [ + { + "api_version": "2020-08-27", + "created": 1000000000, + "data": { + "object": { + "amount": 984000, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": null, + "canceled_at": 1000000000, + "cancellation_reason": "requested_by_customer", + "capture_method": "automatic", + "charges": { + "data": [], + "has_more": false, + "object": "list", + "total_count": 0, + "url": "/v1/charges?payment_intent=upgrade_to_fixed_price_plus_plan--Event.list.2.json" + }, + "client_secret": "NORMALIZED", + "confirmation_method": "automatic", + "created": 1000000000, + "currency": "usd", + "customer": "upgrade_to_fixed_price_plus_plan--Customer.create.1.json", + "description": "Payment for Invoice", + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "invoice": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": {}, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": null, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "cashapp": {}, + "wechat_pay": { + "app_id": null, + "client": null + } + }, + "payment_method_types": [ + "ach_credit_transfer", + "card", + "cashapp", + "wechat_pay" + ], + "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": "canceled", + "transfer_data": null, + "transfer_group": null + } + }, + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "livemode": false, + "object": "event", + "pending_webhooks": 0, + "request": { + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "idempotency_key": "00000000-0000-0000-0000-000000000000" + }, + "type": "payment_intent.canceled" + }, + { + "api_version": "2020-08-27", + "created": 1000000000, + "data": { + "object": { + "ach_credit_transfer": { + "account_number": "test_NORMALIZED", + "bank_name": "TEST BANK", + "fingerprint": "NORMALIZED", + "refund_account_holder_name": null, + "refund_account_holder_type": null, + "refund_routing_number": null, + "routing_number": "110000000", + "swift_code": "TSTEZ122" + }, + "amount": null, + "client_secret": "NORMALIZED", + "created": 1000000000, + "currency": "usd", + "customer": "upgrade_to_fixed_price_plus_plan--Customer.create.1.json", + "flow": "receiver", + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "livemode": false, + "metadata": {}, + "object": "source", + "owner": { + "address": null, + "email": "amount_0@stripe.com", + "name": null, + "phone": null, + "verified_address": null, + "verified_email": null, + "verified_name": null, + "verified_phone": null + }, + "receiver": { + "address": "000000000-test_NORMALIZED", + "amount_charged": 0, + "amount_received": 0, + "amount_returned": 0, + "refund_attributes_method": "email", + "refund_attributes_status": "missing" + }, + "statement_descriptor": null, + "status": "pending", + "type": "ach_credit_transfer", + "usage": "reusable" + } + }, + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "livemode": false, + "object": "event", + "pending_webhooks": 0, + "request": { + "id": null, + "idempotency_key": "00000000-0000-0000-0000-000000000000" + }, + "type": "customer.source.created" + }, + { + "api_version": "2020-08-27", + "created": 1000000000, + "data": { + "object": { + "address": null, + "balance": 0, + "created": 1000000000, + "currency": "usd", + "default_currency": "usd", + "default_source": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "delinquent": false, + "description": "zulip (Zulip Dev)", + "discount": null, + "email": "hamlet@zulip.com", + "id": "upgrade_to_fixed_price_plus_plan--Customer.create.1.json", + "invoice_prefix": "NORMALIZED", + "invoice_settings": { + "custom_fields": null, + "default_payment_method": null, + "footer": null, + "rendering_options": null + }, + "livemode": false, + "metadata": { + "realm_id": "1", + "realm_str": "zulip" + }, + "name": null, + "next_invoice_sequence": 2, + "object": "customer", + "phone": null, + "preferred_locales": [], + "shipping": null, + "tax_exempt": "none", + "test_clock": null + }, + "previous_attributes": { + "default_source": null + } + }, + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "livemode": false, + "object": "event", + "pending_webhooks": 0, + "request": { + "id": null, + "idempotency_key": "00000000-0000-0000-0000-000000000000" + }, + "type": "customer.updated" + }, + { + "api_version": "2020-08-27", + "created": 1000000000, + "data": { + "object": { + "account_country": "US", + "account_name": "Kandra Labs, Inc.", + "account_tax_ids": null, + "amount_due": 984000, + "amount_paid": 0, + "amount_remaining": 984000, + "amount_shipping": 0, + "application": null, + "application_fee_amount": null, + "attempt_count": 0, + "attempted": false, + "auto_advance": true, + "automatic_tax": { + "disabled_reason": null, + "enabled": false, + "liability": null, + "status": null + }, + "automatically_finalizes_at": null, + "billing_reason": "manual", + "charge": null, + "collection_method": "send_invoice", + "created": 1000000000, + "currency": "usd", + "custom_fields": null, + "customer": "upgrade_to_fixed_price_plus_plan--Customer.create.1.json", + "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": 1000000000, + "effective_at": 1000000000, + "ending_balance": 0, + "footer": null, + "from_invoice": null, + "hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED/test_NORMALIZED?s=ap", + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED/test_NORMALIZED/pdf?s=ap", + "issuer": { + "type": "self" + }, + "last_finalization_error": null, + "latest_revision": null, + "lines": { + "data": [ + { + "amount": 984000, + "amount_excluding_tax": 984000, + "currency": "usd", + "description": "Zulip Cloud Standard", + "discount_amounts": [], + "discountable": false, + "discounts": [], + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "invoice": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "invoice_item": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "livemode": false, + "metadata": {}, + "object": "line_item", + "period": { + "end": 1357095845, + "start": 1325473445 + }, + "plan": null, + "pretax_credit_amounts": [], + "price": { + "active": false, + "billing_scheme": "per_unit", + "created": 1000000000, + "currency": "usd", + "custom_unit_amount": null, + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_NORMALIZED", + "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": 123, + "subscription": null, + "tax_amounts": [], + "tax_rates": [], + "type": "invoiceitem", + "unit_amount_excluding_tax": "8000" + } + ], + "has_more": false, + "object": "list", + "total_count": 1, + "url": "/v1/invoices/upgrade_to_fixed_price_plus_plan--Event.list.2.json/lines" + }, + "livemode": false, + "metadata": { + "billing_schedule": "1", + "current_plan_id": "None", + "license_management": "manual", + "licenses": "123", + "on_free_trial": "False", + "plan_tier": "1", + "user_id": "10" + }, + "next_payment_attempt": null, + "number": "NORMALIZED-0001", + "object": "invoice", + "on_behalf_of": null, + "paid": false, + "paid_out_of_band": false, + "payment_intent": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "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" + }, + "template": null, + "template_version": null + }, + "rendering_options": null, + "shipping_cost": null, + "shipping_details": null, + "starting_balance": 0, + "statement_descriptor": "Zulip Cloud Standard", + "status": "open", + "status_transitions": { + "finalized_at": 1000000000, + "marked_uncollectible_at": null, + "paid_at": null, + "voided_at": null + }, + "subscription": null, + "subscription_details": { + "metadata": null + }, + "subtotal": 984000, + "subtotal_excluding_tax": 984000, + "tax": null, + "test_clock": null, + "total": 984000, + "total_discount_amounts": [], + "total_excluding_tax": 984000, + "total_pretax_credit_amounts": [], + "total_tax_amounts": [], + "transfer_data": null, + "webhooks_delivered_at": null + } + }, + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "livemode": false, + "object": "event", + "pending_webhooks": 0, + "request": { + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "idempotency_key": "00000000-0000-0000-0000-000000000000" + }, + "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": 984000, + "amount_paid": 0, + "amount_remaining": 984000, + "amount_shipping": 0, + "application": null, + "application_fee_amount": null, + "attempt_count": 0, + "attempted": false, + "auto_advance": true, + "automatic_tax": { + "disabled_reason": null, + "enabled": false, + "liability": null, + "status": null + }, + "automatically_finalizes_at": null, + "billing_reason": "manual", + "charge": null, + "collection_method": "send_invoice", + "created": 1000000000, + "currency": "usd", + "custom_fields": null, + "customer": "upgrade_to_fixed_price_plus_plan--Customer.create.1.json", + "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": 1000000000, + "effective_at": 1000000000, + "ending_balance": 0, + "footer": null, + "from_invoice": null, + "hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED/test_NORMALIZED?s=ap", + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED/test_NORMALIZED/pdf?s=ap", + "issuer": { + "type": "self" + }, + "last_finalization_error": null, + "latest_revision": null, + "lines": { + "data": [ + { + "amount": 984000, + "amount_excluding_tax": 984000, + "currency": "usd", + "description": "Zulip Cloud Standard", + "discount_amounts": [], + "discountable": false, + "discounts": [], + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "invoice": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "invoice_item": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "livemode": false, + "metadata": {}, + "object": "line_item", + "period": { + "end": 1357095845, + "start": 1325473445 + }, + "plan": null, + "pretax_credit_amounts": [], + "price": { + "active": false, + "billing_scheme": "per_unit", + "created": 1000000000, + "currency": "usd", + "custom_unit_amount": null, + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_NORMALIZED", + "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": 123, + "subscription": null, + "tax_amounts": [], + "tax_rates": [], + "type": "invoiceitem", + "unit_amount_excluding_tax": "8000" + } + ], + "has_more": false, + "object": "list", + "total_count": 1, + "url": "/v1/invoices/upgrade_to_fixed_price_plus_plan--Event.list.2.json/lines" + }, + "livemode": false, + "metadata": { + "billing_schedule": "1", + "current_plan_id": "None", + "license_management": "manual", + "licenses": "123", + "on_free_trial": "False", + "plan_tier": "1", + "user_id": "10" + }, + "next_payment_attempt": null, + "number": "NORMALIZED-0001", + "object": "invoice", + "on_behalf_of": null, + "paid": false, + "paid_out_of_band": false, + "payment_intent": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "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" + }, + "template": null, + "template_version": null + }, + "rendering_options": null, + "shipping_cost": null, + "shipping_details": null, + "starting_balance": 0, + "statement_descriptor": "Zulip Cloud Standard", + "status": "open", + "status_transitions": { + "finalized_at": 1000000000, + "marked_uncollectible_at": null, + "paid_at": null, + "voided_at": null + }, + "subscription": null, + "subscription_details": { + "metadata": null + }, + "subtotal": 984000, + "subtotal_excluding_tax": 984000, + "tax": null, + "test_clock": null, + "total": 984000, + "total_discount_amounts": [], + "total_excluding_tax": 984000, + "total_pretax_credit_amounts": [], + "total_tax_amounts": [], + "transfer_data": null, + "webhooks_delivered_at": null + }, + "previous_attributes": { + "automatically_finalizes_at": 1000000000, + "effective_at": null, + "ending_balance": null, + "hosted_invoice_url": null, + "invoice_pdf": null, + "number": null, + "payment_intent": null, + "rendering": { + "pdf": { + "page_size": "auto" + } + }, + "status": "draft", + "status_transitions": { + "finalized_at": null + } + } + }, + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "livemode": false, + "object": "event", + "pending_webhooks": 0, + "request": { + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "idempotency_key": "00000000-0000-0000-0000-000000000000" + }, + "type": "invoice.updated" + }, + { + "api_version": "2020-08-27", + "created": 1000000000, + "data": { + "object": { + "amount": 984000, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": null, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "charges": { + "data": [], + "has_more": false, + "object": "list", + "total_count": 0, + "url": "/v1/charges?payment_intent=upgrade_to_fixed_price_plus_plan--Event.list.2.json" + }, + "client_secret": "NORMALIZED", + "confirmation_method": "automatic", + "created": 1000000000, + "currency": "usd", + "customer": "upgrade_to_fixed_price_plus_plan--Customer.create.1.json", + "description": "Payment for Invoice", + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "invoice": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": {}, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": null, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "cashapp": {}, + "wechat_pay": { + "app_id": null, + "client": null + } + }, + "payment_method_types": [ + "ach_credit_transfer", + "card", + "cashapp", + "wechat_pay" + ], + "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": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "livemode": false, + "object": "event", + "pending_webhooks": 0, + "request": { + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "idempotency_key": "00000000-0000-0000-0000-000000000000" + }, + "type": "payment_intent.created" + }, + { + "api_version": "2020-08-27", + "created": 1000000000, + "data": { + "object": { + "account_country": "US", + "account_name": "Kandra Labs, Inc.", + "account_tax_ids": null, + "amount_due": 984000, + "amount_paid": 0, + "amount_remaining": 984000, + "amount_shipping": 0, + "application": null, + "application_fee_amount": null, + "attempt_count": 0, + "attempted": false, + "auto_advance": true, + "automatic_tax": { + "disabled_reason": null, + "enabled": false, + "liability": null, + "status": null + }, + "automatically_finalizes_at": 1000000000, + "billing_reason": "manual", + "charge": null, + "collection_method": "send_invoice", + "created": 1000000000, + "currency": "usd", + "custom_fields": null, + "customer": "upgrade_to_fixed_price_plus_plan--Customer.create.1.json", + "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": 1000000000, + "effective_at": null, + "ending_balance": null, + "footer": null, + "from_invoice": null, + "hosted_invoice_url": null, + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "invoice_pdf": null, + "issuer": { + "type": "self" + }, + "last_finalization_error": null, + "latest_revision": null, + "lines": { + "data": [ + { + "amount": 984000, + "amount_excluding_tax": 984000, + "currency": "usd", + "description": "Zulip Cloud Standard", + "discount_amounts": [], + "discountable": false, + "discounts": [], + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "invoice": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "invoice_item": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "livemode": false, + "metadata": {}, + "object": "line_item", + "period": { + "end": 1357095845, + "start": 1325473445 + }, + "plan": null, + "pretax_credit_amounts": [], + "price": { + "active": false, + "billing_scheme": "per_unit", + "created": 1000000000, + "currency": "usd", + "custom_unit_amount": null, + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_NORMALIZED", + "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": 123, + "subscription": null, + "tax_amounts": [], + "tax_rates": [], + "type": "invoiceitem", + "unit_amount_excluding_tax": "8000" + } + ], + "has_more": false, + "object": "list", + "total_count": 1, + "url": "/v1/invoices/upgrade_to_fixed_price_plus_plan--Event.list.2.json/lines" + }, + "livemode": false, + "metadata": { + "billing_schedule": "1", + "current_plan_id": "None", + "license_management": "manual", + "licenses": "123", + "on_free_trial": "False", + "plan_tier": "1", + "user_id": "10" + }, + "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" + }, + "template": null, + "template_version": null + }, + "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": 984000, + "subtotal_excluding_tax": 984000, + "tax": null, + "test_clock": null, + "total": 984000, + "total_discount_amounts": [], + "total_excluding_tax": 984000, + "total_pretax_credit_amounts": [], + "total_tax_amounts": [], + "transfer_data": null, + "webhooks_delivered_at": null + } + }, + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "livemode": false, + "object": "event", + "pending_webhooks": 0, + "request": { + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "idempotency_key": "00000000-0000-0000-0000-000000000000" + }, + "type": "invoice.created" + }, + { + "api_version": "2020-08-27", + "created": 1000000000, + "data": { + "object": { + "amount": 984000, + "currency": "usd", + "customer": "upgrade_to_fixed_price_plus_plan--Customer.create.1.json", + "date": 1000000000, + "description": "Zulip Cloud Standard", + "discountable": false, + "discounts": [], + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "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": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_NORMALIZED", + "recurring": null, + "tax_behavior": "unspecified", + "tiers_mode": null, + "transform_quantity": null, + "type": "one_time", + "unit_amount": 8000, + "unit_amount_decimal": "8000" + }, + "proration": false, + "quantity": 123, + "subscription": null, + "tax_rates": [], + "test_clock": null, + "unit_amount": 8000, + "unit_amount_decimal": "8000" + } + }, + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "livemode": false, + "object": "event", + "pending_webhooks": 0, + "request": { + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "idempotency_key": "00000000-0000-0000-0000-000000000000" + }, + "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": "upgrade_to_fixed_price_plus_plan--Customer.create.1.json", + "invoice_prefix": "NORMALIZED", + "invoice_settings": { + "custom_fields": null, + "default_payment_method": null, + "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": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "livemode": false, + "object": "event", + "pending_webhooks": 0, + "request": { + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "idempotency_key": "00000000-0000-0000-0000-000000000000" + }, + "type": "customer.updated" + }, + { + "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": "upgrade_to_fixed_price_plus_plan--Customer.create.1.json", + "invoice_prefix": "NORMALIZED", + "invoice_settings": { + "custom_fields": null, + "default_payment_method": null, + "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 + } + }, + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "livemode": false, + "object": "event", + "pending_webhooks": 0, + "request": { + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "idempotency_key": "00000000-0000-0000-0000-000000000000" + }, + "type": "customer.created" + } + ], + "has_more": true, + "object": "list", + "url": "/v1/events" +} diff --git a/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--Event.list.3.json b/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--Event.list.3.json new file mode 100644 index 0000000000..8650a4722a --- /dev/null +++ b/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--Event.list.3.json @@ -0,0 +1,401 @@ +{ + "data": [ + { + "api_version": "2020-08-27", + "created": 1000000000, + "data": { + "object": { + "account_country": "US", + "account_name": "Kandra Labs, Inc.", + "account_tax_ids": null, + "amount_due": 984000, + "amount_paid": 0, + "amount_remaining": 984000, + "amount_shipping": 0, + "application": null, + "application_fee_amount": null, + "attempt_count": 0, + "attempted": false, + "auto_advance": false, + "automatic_tax": { + "disabled_reason": null, + "enabled": false, + "liability": null, + "status": null + }, + "automatically_finalizes_at": null, + "billing_reason": "manual", + "charge": null, + "collection_method": "send_invoice", + "created": 1000000000, + "currency": "usd", + "custom_fields": null, + "customer": "cus_NORMALIZED", + "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": 1000000000, + "effective_at": 1000000000, + "ending_balance": 0, + "footer": null, + "from_invoice": null, + "hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED/test_NORMALIZED?s=ap", + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED/test_NORMALIZED/pdf?s=ap", + "issuer": { + "type": "self" + }, + "last_finalization_error": null, + "latest_revision": null, + "lines": { + "data": [ + { + "amount": 984000, + "amount_excluding_tax": 984000, + "currency": "usd", + "description": "Zulip Cloud Standard", + "discount_amounts": [], + "discountable": false, + "discounts": [], + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "invoice": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "invoice_item": "ii_NORMALIZED", + "livemode": false, + "metadata": {}, + "object": "line_item", + "period": { + "end": 1357095845, + "start": 1325473445 + }, + "plan": null, + "pretax_credit_amounts": [], + "price": { + "active": false, + "billing_scheme": "per_unit", + "created": 1000000000, + "currency": "usd", + "custom_unit_amount": null, + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_NORMALIZED", + "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": 123, + "subscription": null, + "tax_amounts": [], + "tax_rates": [], + "type": "invoiceitem", + "unit_amount_excluding_tax": "8000" + } + ], + "has_more": false, + "object": "list", + "total_count": 1, + "url": "/v1/invoices/upgrade_to_fixed_price_plus_plan--Event.list.2.json/lines" + }, + "livemode": false, + "metadata": { + "billing_schedule": "1", + "current_plan_id": "None", + "license_management": "manual", + "licenses": "123", + "on_free_trial": "False", + "plan_tier": "1", + "user_id": "10" + }, + "next_payment_attempt": null, + "number": "NORMALIZED", + "object": "invoice", + "on_behalf_of": null, + "paid": true, + "paid_out_of_band": true, + "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" + }, + "template": null, + "template_version": null + }, + "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": 984000, + "subtotal_excluding_tax": 984000, + "tax": null, + "test_clock": null, + "total": 984000, + "total_discount_amounts": [], + "total_excluding_tax": 984000, + "total_pretax_credit_amounts": [], + "total_tax_amounts": [], + "transfer_data": null, + "webhooks_delivered_at": 1000000000 + } + }, + "id": "upgrade_to_fixed_price_plus_plan--Event.list.3.json", + "livemode": false, + "object": "event", + "pending_webhooks": 0, + "request": { + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "idempotency_key": "00000000-0000-0000-0000-000000000000" + }, + "type": "invoice.paid" + }, + { + "api_version": "2020-08-27", + "created": 1000000000, + "data": { + "object": { + "account_country": "US", + "account_name": "Kandra Labs, Inc.", + "account_tax_ids": null, + "amount_due": 984000, + "amount_paid": 0, + "amount_remaining": 984000, + "amount_shipping": 0, + "application": null, + "application_fee_amount": null, + "attempt_count": 0, + "attempted": false, + "auto_advance": false, + "automatic_tax": { + "disabled_reason": null, + "enabled": false, + "liability": null, + "status": null + }, + "automatically_finalizes_at": null, + "billing_reason": "manual", + "charge": null, + "collection_method": "send_invoice", + "created": 1000000000, + "currency": "usd", + "custom_fields": null, + "customer": "cus_NORMALIZED", + "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": 1000000000, + "effective_at": 1000000000, + "ending_balance": 0, + "footer": null, + "from_invoice": null, + "hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED/test_NORMALIZED?s=ap", + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED/test_NORMALIZED/pdf?s=ap", + "issuer": { + "type": "self" + }, + "last_finalization_error": null, + "latest_revision": null, + "lines": { + "data": [ + { + "amount": 984000, + "amount_excluding_tax": 984000, + "currency": "usd", + "description": "Zulip Cloud Standard", + "discount_amounts": [], + "discountable": false, + "discounts": [], + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "invoice": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "invoice_item": "ii_NORMALIZED", + "livemode": false, + "metadata": {}, + "object": "line_item", + "period": { + "end": 1357095845, + "start": 1325473445 + }, + "plan": null, + "pretax_credit_amounts": [], + "price": { + "active": false, + "billing_scheme": "per_unit", + "created": 1000000000, + "currency": "usd", + "custom_unit_amount": null, + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_NORMALIZED", + "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": 123, + "subscription": null, + "tax_amounts": [], + "tax_rates": [], + "type": "invoiceitem", + "unit_amount_excluding_tax": "8000" + } + ], + "has_more": false, + "object": "list", + "total_count": 1, + "url": "/v1/invoices/upgrade_to_fixed_price_plus_plan--Event.list.2.json/lines" + }, + "livemode": false, + "metadata": { + "billing_schedule": "1", + "current_plan_id": "None", + "license_management": "manual", + "licenses": "123", + "on_free_trial": "False", + "plan_tier": "1", + "user_id": "10" + }, + "next_payment_attempt": null, + "number": "NORMALIZED", + "object": "invoice", + "on_behalf_of": null, + "paid": true, + "paid_out_of_band": true, + "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" + }, + "template": null, + "template_version": null + }, + "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": 984000, + "subtotal_excluding_tax": 984000, + "tax": null, + "test_clock": null, + "total": 984000, + "total_discount_amounts": [], + "total_excluding_tax": 984000, + "total_pretax_credit_amounts": [], + "total_tax_amounts": [], + "transfer_data": null, + "webhooks_delivered_at": 1000000000 + }, + "previous_attributes": { + "auto_advance": true, + "paid": false, + "paid_out_of_band": false, + "payment_intent": "pi_NORMALIZED", + "status": "open", + "status_transitions": { + "paid_at": null + } + } + }, + "id": "upgrade_to_fixed_price_plus_plan--Event.list.3.json", + "livemode": false, + "object": "event", + "pending_webhooks": 0, + "request": { + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "idempotency_key": "00000000-0000-0000-0000-000000000000" + }, + "type": "invoice.updated" + } + ], + "has_more": false, + "object": "list", + "url": "/v1/events" +} diff --git a/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--Event.list.4.json b/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--Event.list.4.json new file mode 100644 index 0000000000..6d922067af --- /dev/null +++ b/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--Event.list.4.json @@ -0,0 +1,6 @@ +{ + "data": [], + "has_more": false, + "object": "list", + "url": "/v1/events" +} diff --git a/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--Invoice.create.1.json b/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--Invoice.create.1.json new file mode 100644 index 0000000000..cee1de974d --- /dev/null +++ b/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--Invoice.create.1.json @@ -0,0 +1,177 @@ +{ + "account_country": "US", + "account_name": "Kandra Labs, Inc.", + "account_tax_ids": null, + "amount_due": 984000, + "amount_paid": 0, + "amount_remaining": 984000, + "amount_shipping": 0, + "application": null, + "application_fee_amount": null, + "attempt_count": 0, + "attempted": false, + "auto_advance": true, + "automatic_tax": { + "disabled_reason": null, + "enabled": false, + "liability": null, + "status": null + }, + "automatically_finalizes_at": 1000000000, + "billing_reason": "manual", + "charge": null, + "collection_method": "send_invoice", + "created": 1000000000, + "currency": "usd", + "custom_fields": null, + "customer": "cus_NORMALIZED", + "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": 1000000000, + "effective_at": null, + "ending_balance": null, + "footer": null, + "from_invoice": null, + "hosted_invoice_url": null, + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "invoice_pdf": null, + "issuer": { + "type": "self" + }, + "last_finalization_error": null, + "latest_revision": null, + "lines": { + "data": [ + { + "amount": 984000, + "amount_excluding_tax": 984000, + "currency": "usd", + "description": "Zulip Cloud Standard", + "discount_amounts": [], + "discountable": false, + "discounts": [], + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "invoice": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "invoice_item": "ii_NORMALIZED", + "livemode": false, + "metadata": {}, + "object": "line_item", + "period": { + "end": 1357095845, + "start": 1325473445 + }, + "plan": null, + "pretax_credit_amounts": [], + "price": { + "active": false, + "billing_scheme": "per_unit", + "created": 1000000000, + "currency": "usd", + "custom_unit_amount": null, + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_NORMALIZED", + "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": 123, + "subscription": null, + "tax_amounts": [], + "tax_rates": [], + "type": "invoiceitem", + "unit_amount_excluding_tax": "8000" + } + ], + "has_more": false, + "object": "list", + "total_count": 1, + "url": "/v1/invoices/upgrade_to_fixed_price_plus_plan--Event.list.2.json/lines" + }, + "livemode": false, + "metadata": { + "billing_schedule": "1", + "current_plan_id": "None", + "license_management": "manual", + "licenses": "123", + "on_free_trial": "False", + "plan_tier": "1", + "user_id": "10" + }, + "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" + }, + "template": null, + "template_version": null + }, + "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": 984000, + "subtotal_excluding_tax": 984000, + "tax": null, + "test_clock": null, + "total": 984000, + "total_discount_amounts": [], + "total_excluding_tax": 984000, + "total_pretax_credit_amounts": [], + "total_tax_amounts": [], + "transfer_data": null, + "webhooks_delivered_at": null +} diff --git a/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--Invoice.create.2.json b/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--Invoice.create.2.json new file mode 100644 index 0000000000..23559426d0 --- /dev/null +++ b/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--Invoice.create.2.json @@ -0,0 +1,169 @@ +{ + "account_country": "US", + "account_name": "Kandra Labs, Inc.", + "account_tax_ids": null, + "amount_due": 36000, + "amount_paid": 0, + "amount_remaining": 36000, + "amount_shipping": 0, + "application": null, + "application_fee_amount": null, + "attempt_count": 0, + "attempted": false, + "auto_advance": true, + "automatic_tax": { + "disabled_reason": null, + "enabled": false, + "liability": null, + "status": null + }, + "automatically_finalizes_at": 1000000000, + "billing_reason": "manual", + "charge": null, + "collection_method": "send_invoice", + "created": 1000000000, + "currency": "usd", + "custom_fields": null, + "customer": "cus_NORMALIZED", + "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": 1000000000, + "effective_at": null, + "ending_balance": null, + "footer": null, + "from_invoice": null, + "hosted_invoice_url": null, + "id": "upgrade_to_fixed_price_plus_plan--Invoice.create.2.json", + "invoice_pdf": null, + "issuer": { + "type": "self" + }, + "last_finalization_error": null, + "latest_revision": null, + "lines": { + "data": [ + { + "amount": 36000, + "amount_excluding_tax": 36000, + "currency": "usd", + "description": "Zulip Cloud Plus - renewal", + "discount_amounts": [], + "discountable": false, + "discounts": [], + "id": "upgrade_to_fixed_price_plus_plan--Invoice.create.2.json", + "invoice": "upgrade_to_fixed_price_plus_plan--Invoice.create.2.json", + "invoice_item": "ii_NORMALIZED", + "livemode": false, + "metadata": {}, + "object": "line_item", + "period": { + "end": 1388620800, + "start": 1357084800 + }, + "plan": null, + "pretax_credit_amounts": [], + "price": { + "active": false, + "billing_scheme": "per_unit", + "created": 1000000000, + "currency": "usd", + "custom_unit_amount": null, + "id": "upgrade_to_fixed_price_plus_plan--Event.list.1.json", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_NORMALIZED", + "recurring": null, + "tax_behavior": "unspecified", + "tiers_mode": null, + "transform_quantity": null, + "type": "one_time", + "unit_amount": 36000, + "unit_amount_decimal": "36000" + }, + "proration": false, + "proration_details": { + "credited_items": null + }, + "quantity": 1, + "subscription": null, + "tax_amounts": [], + "tax_rates": [], + "type": "invoiceitem", + "unit_amount_excluding_tax": "36000" + } + ], + "has_more": false, + "object": "list", + "total_count": 1, + "url": "/v1/invoices/upgrade_to_fixed_price_plus_plan--Invoice.create.2.json/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" + }, + "template": null, + "template_version": null + }, + "rendering_options": null, + "shipping_cost": null, + "shipping_details": null, + "starting_balance": 0, + "statement_descriptor": "Zulip Cloud 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": 36000, + "subtotal_excluding_tax": 36000, + "tax": null, + "test_clock": null, + "total": 36000, + "total_discount_amounts": [], + "total_excluding_tax": 36000, + "total_pretax_credit_amounts": [], + "total_tax_amounts": [], + "transfer_data": null, + "webhooks_delivered_at": null +} diff --git a/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--Invoice.finalize_invoice.1.json b/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--Invoice.finalize_invoice.1.json new file mode 100644 index 0000000000..e256a3057d --- /dev/null +++ b/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--Invoice.finalize_invoice.1.json @@ -0,0 +1,177 @@ +{ + "account_country": "US", + "account_name": "Kandra Labs, Inc.", + "account_tax_ids": null, + "amount_due": 984000, + "amount_paid": 0, + "amount_remaining": 984000, + "amount_shipping": 0, + "application": null, + "application_fee_amount": null, + "attempt_count": 0, + "attempted": false, + "auto_advance": true, + "automatic_tax": { + "disabled_reason": null, + "enabled": false, + "liability": null, + "status": null + }, + "automatically_finalizes_at": null, + "billing_reason": "manual", + "charge": null, + "collection_method": "send_invoice", + "created": 1000000000, + "currency": "usd", + "custom_fields": null, + "customer": "cus_NORMALIZED", + "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": 1000000000, + "effective_at": 1000000000, + "ending_balance": 0, + "footer": null, + "from_invoice": null, + "hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED/test_NORMALIZED?s=ap", + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED/test_NORMALIZED/pdf?s=ap", + "issuer": { + "type": "self" + }, + "last_finalization_error": null, + "latest_revision": null, + "lines": { + "data": [ + { + "amount": 984000, + "amount_excluding_tax": 984000, + "currency": "usd", + "description": "Zulip Cloud Standard", + "discount_amounts": [], + "discountable": false, + "discounts": [], + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "invoice": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "invoice_item": "ii_NORMALIZED", + "livemode": false, + "metadata": {}, + "object": "line_item", + "period": { + "end": 1357095845, + "start": 1325473445 + }, + "plan": null, + "pretax_credit_amounts": [], + "price": { + "active": false, + "billing_scheme": "per_unit", + "created": 1000000000, + "currency": "usd", + "custom_unit_amount": null, + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_NORMALIZED", + "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": 123, + "subscription": null, + "tax_amounts": [], + "tax_rates": [], + "type": "invoiceitem", + "unit_amount_excluding_tax": "8000" + } + ], + "has_more": false, + "object": "list", + "total_count": 1, + "url": "/v1/invoices/upgrade_to_fixed_price_plus_plan--Event.list.2.json/lines" + }, + "livemode": false, + "metadata": { + "billing_schedule": "1", + "current_plan_id": "None", + "license_management": "manual", + "licenses": "123", + "on_free_trial": "False", + "plan_tier": "1", + "user_id": "10" + }, + "next_payment_attempt": null, + "number": "NORMALIZED", + "object": "invoice", + "on_behalf_of": null, + "paid": false, + "paid_out_of_band": false, + "payment_intent": "pi_NORMALIZED", + "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" + }, + "template": null, + "template_version": null + }, + "rendering_options": null, + "shipping_cost": null, + "shipping_details": null, + "starting_balance": 0, + "statement_descriptor": "Zulip Cloud Standard", + "status": "open", + "status_transitions": { + "finalized_at": 1000000000, + "marked_uncollectible_at": null, + "paid_at": null, + "voided_at": null + }, + "subscription": null, + "subscription_details": { + "metadata": null + }, + "subtotal": 984000, + "subtotal_excluding_tax": 984000, + "tax": null, + "test_clock": null, + "total": 984000, + "total_discount_amounts": [], + "total_excluding_tax": 984000, + "total_pretax_credit_amounts": [], + "total_tax_amounts": [], + "transfer_data": null, + "webhooks_delivered_at": null +} diff --git a/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--Invoice.finalize_invoice.2.json b/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--Invoice.finalize_invoice.2.json new file mode 100644 index 0000000000..ba32b8569d --- /dev/null +++ b/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--Invoice.finalize_invoice.2.json @@ -0,0 +1,169 @@ +{ + "account_country": "US", + "account_name": "Kandra Labs, Inc.", + "account_tax_ids": null, + "amount_due": 36000, + "amount_paid": 0, + "amount_remaining": 36000, + "amount_shipping": 0, + "application": null, + "application_fee_amount": null, + "attempt_count": 0, + "attempted": false, + "auto_advance": true, + "automatic_tax": { + "disabled_reason": null, + "enabled": false, + "liability": null, + "status": null + }, + "automatically_finalizes_at": null, + "billing_reason": "manual", + "charge": null, + "collection_method": "send_invoice", + "created": 1000000000, + "currency": "usd", + "custom_fields": null, + "customer": "cus_NORMALIZED", + "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": 1000000000, + "effective_at": 1000000000, + "ending_balance": 0, + "footer": null, + "from_invoice": null, + "hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED/test_NORMALIZED?s=ap", + "id": "upgrade_to_fixed_price_plus_plan--Invoice.create.2.json", + "invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED/test_NORMALIZED/pdf?s=ap", + "issuer": { + "type": "self" + }, + "last_finalization_error": null, + "latest_revision": null, + "lines": { + "data": [ + { + "amount": 36000, + "amount_excluding_tax": 36000, + "currency": "usd", + "description": "Zulip Cloud Plus - renewal", + "discount_amounts": [], + "discountable": false, + "discounts": [], + "id": "upgrade_to_fixed_price_plus_plan--Invoice.create.2.json", + "invoice": "upgrade_to_fixed_price_plus_plan--Invoice.create.2.json", + "invoice_item": "ii_NORMALIZED", + "livemode": false, + "metadata": {}, + "object": "line_item", + "period": { + "end": 1388620800, + "start": 1357084800 + }, + "plan": null, + "pretax_credit_amounts": [], + "price": { + "active": false, + "billing_scheme": "per_unit", + "created": 1000000000, + "currency": "usd", + "custom_unit_amount": null, + "id": "upgrade_to_fixed_price_plus_plan--Event.list.1.json", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_NORMALIZED", + "recurring": null, + "tax_behavior": "unspecified", + "tiers_mode": null, + "transform_quantity": null, + "type": "one_time", + "unit_amount": 36000, + "unit_amount_decimal": "36000" + }, + "proration": false, + "proration_details": { + "credited_items": null + }, + "quantity": 1, + "subscription": null, + "tax_amounts": [], + "tax_rates": [], + "type": "invoiceitem", + "unit_amount_excluding_tax": "36000" + } + ], + "has_more": false, + "object": "list", + "total_count": 1, + "url": "/v1/invoices/upgrade_to_fixed_price_plus_plan--Invoice.create.2.json/lines" + }, + "livemode": false, + "metadata": {}, + "next_payment_attempt": null, + "number": "NORMALIZED", + "object": "invoice", + "on_behalf_of": null, + "paid": false, + "paid_out_of_band": false, + "payment_intent": "pi_NORMALIZED", + "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" + }, + "template": null, + "template_version": null + }, + "rendering_options": null, + "shipping_cost": null, + "shipping_details": null, + "starting_balance": 0, + "statement_descriptor": "Zulip Cloud 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": 36000, + "subtotal_excluding_tax": 36000, + "tax": null, + "test_clock": null, + "total": 36000, + "total_discount_amounts": [], + "total_excluding_tax": 36000, + "total_pretax_credit_amounts": [], + "total_tax_amounts": [], + "transfer_data": null, + "webhooks_delivered_at": 1000000000 +} diff --git a/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--Invoice.pay.1.json b/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--Invoice.pay.1.json new file mode 100644 index 0000000000..083158bcfc --- /dev/null +++ b/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--Invoice.pay.1.json @@ -0,0 +1,177 @@ +{ + "account_country": "US", + "account_name": "Kandra Labs, Inc.", + "account_tax_ids": null, + "amount_due": 984000, + "amount_paid": 0, + "amount_remaining": 984000, + "amount_shipping": 0, + "application": null, + "application_fee_amount": null, + "attempt_count": 0, + "attempted": false, + "auto_advance": false, + "automatic_tax": { + "disabled_reason": null, + "enabled": false, + "liability": null, + "status": null + }, + "automatically_finalizes_at": null, + "billing_reason": "manual", + "charge": null, + "collection_method": "send_invoice", + "created": 1000000000, + "currency": "usd", + "custom_fields": null, + "customer": "cus_NORMALIZED", + "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": 1000000000, + "effective_at": 1000000000, + "ending_balance": 0, + "footer": null, + "from_invoice": null, + "hosted_invoice_url": "https://invoice.stripe.com/i/acct_NORMALIZED/test_NORMALIZED?s=ap", + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "invoice_pdf": "https://pay.stripe.com/invoice/acct_NORMALIZED/test_NORMALIZED/pdf?s=ap", + "issuer": { + "type": "self" + }, + "last_finalization_error": null, + "latest_revision": null, + "lines": { + "data": [ + { + "amount": 984000, + "amount_excluding_tax": 984000, + "currency": "usd", + "description": "Zulip Cloud Standard", + "discount_amounts": [], + "discountable": false, + "discounts": [], + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "invoice": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "invoice_item": "ii_NORMALIZED", + "livemode": false, + "metadata": {}, + "object": "line_item", + "period": { + "end": 1357095845, + "start": 1325473445 + }, + "plan": null, + "pretax_credit_amounts": [], + "price": { + "active": false, + "billing_scheme": "per_unit", + "created": 1000000000, + "currency": "usd", + "custom_unit_amount": null, + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_NORMALIZED", + "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": 123, + "subscription": null, + "tax_amounts": [], + "tax_rates": [], + "type": "invoiceitem", + "unit_amount_excluding_tax": "8000" + } + ], + "has_more": false, + "object": "list", + "total_count": 1, + "url": "/v1/invoices/upgrade_to_fixed_price_plus_plan--Event.list.2.json/lines" + }, + "livemode": false, + "metadata": { + "billing_schedule": "1", + "current_plan_id": "None", + "license_management": "manual", + "licenses": "123", + "on_free_trial": "False", + "plan_tier": "1", + "user_id": "10" + }, + "next_payment_attempt": null, + "number": "NORMALIZED", + "object": "invoice", + "on_behalf_of": null, + "paid": true, + "paid_out_of_band": true, + "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" + }, + "template": null, + "template_version": null + }, + "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": 984000, + "subtotal_excluding_tax": 984000, + "tax": null, + "test_clock": null, + "total": 984000, + "total_discount_amounts": [], + "total_excluding_tax": 984000, + "total_pretax_credit_amounts": [], + "total_tax_amounts": [], + "transfer_data": null, + "webhooks_delivered_at": 1000000000 +} diff --git a/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--InvoiceItem.create.1.json b/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--InvoiceItem.create.1.json new file mode 100644 index 0000000000..3010bc10d1 --- /dev/null +++ b/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--InvoiceItem.create.1.json @@ -0,0 +1,47 @@ +{ + "amount": 984000, + "currency": "usd", + "customer": "cus_NORMALIZED", + "date": 1000000000, + "description": "Zulip Cloud Standard", + "discountable": false, + "discounts": [], + "id": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "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": "upgrade_to_fixed_price_plus_plan--Event.list.2.json", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_NORMALIZED", + "recurring": null, + "tax_behavior": "unspecified", + "tiers_mode": null, + "transform_quantity": null, + "type": "one_time", + "unit_amount": 8000, + "unit_amount_decimal": "8000" + }, + "proration": false, + "quantity": 123, + "subscription": null, + "tax_rates": [], + "test_clock": null, + "unit_amount": 8000, + "unit_amount_decimal": "8000" +} diff --git a/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--InvoiceItem.create.2.json b/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--InvoiceItem.create.2.json new file mode 100644 index 0000000000..baa6bbe255 --- /dev/null +++ b/corporate/tests/stripe_fixtures/upgrade_to_fixed_price_plus_plan--InvoiceItem.create.2.json @@ -0,0 +1,47 @@ +{ + "amount": 36000, + "currency": "usd", + "customer": "cus_NORMALIZED", + "date": 1000000000, + "description": "Zulip Cloud Plus - renewal", + "discountable": false, + "discounts": [], + "id": "upgrade_to_fixed_price_plus_plan--InvoiceItem.create.2.json", + "invoice": null, + "livemode": false, + "metadata": {}, + "object": "invoiceitem", + "period": { + "end": 1388620800, + "start": 1357084800 + }, + "plan": null, + "price": { + "active": false, + "billing_scheme": "per_unit", + "created": 1000000000, + "currency": "usd", + "custom_unit_amount": null, + "id": "upgrade_to_fixed_price_plus_plan--Event.list.1.json", + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": null, + "object": "price", + "product": "prod_NORMALIZED", + "recurring": null, + "tax_behavior": "unspecified", + "tiers_mode": null, + "transform_quantity": null, + "type": "one_time", + "unit_amount": 36000, + "unit_amount_decimal": "36000" + }, + "proration": false, + "quantity": 1, + "subscription": null, + "tax_rates": [], + "test_clock": null, + "unit_amount": 36000, + "unit_amount_decimal": "36000" +} diff --git a/corporate/tests/test_stripe.py b/corporate/tests/test_stripe.py index e9ebe5348f..dc73391ef9 100644 --- a/corporate/tests/test_stripe.py +++ b/corporate/tests/test_stripe.py @@ -6073,6 +6073,113 @@ class InvoiceTest(StripeTestCase): for key, value in line_item_params.items(): self.assertEqual(item.get(key), value) + @mock_stripe() + def test_upgrade_to_fixed_price_plus_plan(self, *mocks: Mock) -> None: + iago = self.example_user("iago") + hamlet = self.example_user("hamlet") + realm = get_realm("zulip") + self.assertEqual(realm.plan_type, Realm.PLAN_TYPE_SELF_HOSTED) + + self.login_user(hamlet) + with time_machine.travel(self.now, tick=False): + self.upgrade(invoice=True) + plan = CustomerPlan.objects.first() + assert plan is not None + self.assertIsNone(plan.end_date) + self.assertEqual(plan.tier, CustomerPlan.TIER_CLOUD_STANDARD) + realm.refresh_from_db() + self.assertEqual(realm.plan_type, Realm.PLAN_TYPE_STANDARD) + + billing_session = RealmBillingSession(user=hamlet, realm=realm) + next_billing_cycle = billing_session.get_next_billing_cycle(plan) + plan_end_date_string = next_billing_cycle.strftime("%Y-%m-%d") + plan_end_date = datetime.strptime(plan_end_date_string, "%Y-%m-%d").replace( + tzinfo=timezone.utc + ) + + self.logout() + self.login_user(iago) + + result = self.client_post( + "/activity/support", + { + "realm_id": f"{realm.id}", + "required_plan_tier": f"{CustomerPlanOffer.TIER_CLOUD_PLUS}", + }, + ) + self.assert_in_success_response( + ["Required plan tier for zulip set to Zulip Cloud Plus."], + result, + ) + + with time_machine.travel(self.now, tick=False): + result = self.client_post( + "/activity/support", + { + "realm_id": f"{realm.id}", + "plan_end_date": plan_end_date_string, + }, + ) + self.assert_in_success_response( + [f"Current plan for zulip updated to end on {plan_end_date_string}."], + result, + ) + + plan.refresh_from_db() + self.assertEqual(plan.end_date, plan_end_date) + + result = self.client_post( + "/activity/support", + { + "realm_id": f"{realm.id}", + "fixed_price": 360, + }, + ) + self.assert_in_success_response( + [f"Fixed price Zulip Cloud Plus plan scheduled to start on {plan_end_date_string}."], + result, + ) + + plan.refresh_from_db() + self.assertEqual(plan.status, CustomerPlan.SWITCH_PLAN_TIER_AT_PLAN_END) + self.assertEqual(plan.next_invoice_date, plan_end_date) + new_plan = CustomerPlan.objects.filter(fixed_price__isnull=False).first() + assert new_plan is not None + self.assertEqual(new_plan.next_invoice_date, plan_end_date) + self.assertEqual( + new_plan.invoicing_status, CustomerPlan.INVOICING_STATUS_INITIAL_INVOICE_TO_BE_SENT + ) + + with time_machine.travel(next_billing_cycle, tick=False): + invoice_plans_as_needed() + + plan.refresh_from_db() + self.assertEqual(plan.status, CustomerPlan.ENDED) + self.assertEqual(plan.next_invoice_date, None) + + new_plan.refresh_from_db() + self.assertEqual(new_plan.tier, CustomerPlan.TIER_CLOUD_PLUS) + self.assertIsNotNone(new_plan.fixed_price) + self.assertIsNone(new_plan.price_per_license) + + realm.refresh_from_db() + self.assertEqual(realm.plan_type, Realm.PLAN_TYPE_PLUS) + + # Visit /billing + self.logout() + self.login_user(hamlet) + with time_machine.travel(plan_end_date + timedelta(days=1), tick=False): + response = self.client_get(f"{self.billing_session.billing_base_url}/billing/") + for substring in [ + "Zulip Cloud Plus", + "Annual", + "Invoice", + "This is a fixed-price plan", + "You will be contacted by Zulip Sales", + ]: + self.assert_in_response(substring, response) + self.assert_not_in_success_response(["Update card"], response) + def test_no_invoice_needed(self) -> None: # local_upgrade uses hamlet as user, therefore realm is zulip. with time_machine.travel(self.now, tick=False): diff --git a/corporate/tests/test_support_views.py b/corporate/tests/test_support_views.py index 9891680d27..d907321ce9 100644 --- a/corporate/tests/test_support_views.py +++ b/corporate/tests/test_support_views.py @@ -12,11 +12,13 @@ from corporate.lib.stripe import ( RealmBillingSession, RemoteRealmBillingSession, add_months, + get_configured_fixed_price_plan_offer, start_of_next_billing_cycle, ) from corporate.models import ( Customer, CustomerPlan, + CustomerPlanOffer, LicenseLedger, SponsoredPlanTypes, ZulipSponsorshipRequest, @@ -1569,6 +1571,231 @@ class TestSupportEndpoint(ZulipTestCase): self.assertEqual(current_plan.end_date, datetime(2050, 3, 1, tzinfo=timezone.utc)) self.assertEqual(current_plan.next_invoice_date, next_invoice_date) + def test_configure_fixed_price_plan_without_current_plan(self) -> None: + plan_offer_tier = CustomerPlanOffer.TIER_CLOUD_STANDARD + plan_offer_tier_name = CustomerPlanOffer.name_from_tier(plan_offer_tier) + + lear_realm = get_realm("lear") + customer = get_customer_by_realm(lear_realm) + assert customer is None + + iago = self.example_user("iago") + self.login_user(iago) + + # Configuring a fixed-price plan requires setting + # a required plan tier for the organization. + result = self.client_post( + "/activity/support", + { + "realm_id": f"{lear_realm.id}", + "fixed_price": 360, + }, + ) + self.assert_in_success_response( + ["Required plan tier should not be set to None"], + result, + ) + + customer = get_customer_by_realm(lear_realm) + assert customer is not None + self.assertIsNone(customer.required_plan_tier) + plan = get_current_plan_by_customer(customer) + assert plan is None + + result = self.client_post( + "/activity/support", + { + "realm_id": f"{lear_realm.id}", + "required_plan_tier": f"{plan_offer_tier}", + }, + ) + self.assert_in_success_response( + [f"Required plan tier for lear set to {plan_offer_tier_name}."], + result, + ) + + customer.refresh_from_db() + assert customer.required_plan_tier is not None + plan_offer = get_configured_fixed_price_plan_offer(customer, customer.required_plan_tier) + assert plan_offer is None + + result = self.client_post( + "/activity/support", + { + "realm_id": f"{lear_realm.id}", + "fixed_price": 360, + }, + ) + self.assert_in_success_response( + [f"Customer can now buy a fixed price {plan_offer_tier_name} plan."], + result, + ) + + customer.refresh_from_db() + plan_offer = get_configured_fixed_price_plan_offer(customer, customer.required_plan_tier) + assert plan_offer is not None + self.assertEqual(plan_offer.status, CustomerPlanOffer.CONFIGURED) + self.assertEqual(plan_offer.fixed_price, 36000) + self.assertIsNone(plan_offer.sent_invoice_id) + + # Test deleting the fixed-price plan offer via support. + result = self.client_post( + "/activity/support", + { + "realm_id": f"{lear_realm.id}", + "delete_fixed_price_next_plan": "true", + }, + ) + self.assert_in_success_response( + ["Fixed price offer deleted"], + result, + ) + customer.refresh_from_db() + plan_offer = get_configured_fixed_price_plan_offer(customer, customer.required_plan_tier) + self.assertIsNone(plan_offer) + + def test_configure_upgrade_fixed_price_plan_with_current_plan(self) -> None: + plan_offer_tier = CustomerPlanOffer.TIER_CLOUD_PLUS + plan_offer_tier_name = CustomerPlanOffer.name_from_tier(plan_offer_tier) + + lear_realm = get_realm("lear") + customer = self.create_customer_and_plan(lear_realm, True) + plan = get_current_plan_by_customer(customer) + assert plan is not None + self.assertIsNone(plan.end_date) + + iago = self.example_user("iago") + self.login_user(iago) + + # Configuring a fixed-price plan requires setting + # a required plan tier for the organization. + result = self.client_post( + "/activity/support", + { + "realm_id": f"{lear_realm.id}", + "fixed_price": 360, + }, + ) + self.assert_in_success_response( + ["Required plan tier should not be set to None"], + result, + ) + + result = self.client_post( + "/activity/support", + { + "realm_id": f"{lear_realm.id}", + "required_plan_tier": f"{plan_offer_tier}", + }, + ) + self.assert_in_success_response( + [f"Required plan tier for lear set to {plan_offer_tier_name}."], + result, + ) + + # Configuring a fixed-price plan requires any current + # plan to have an end date set. + result = self.client_post( + "/activity/support", + { + "realm_id": f"{lear_realm.id}", + "fixed_price": 360, + }, + ) + self.assert_in_success_response( + ["Configure lear current plan end-date, before scheduling a new plan."], + result, + ) + + result = self.client_post( + "/activity/support", + { + "realm_id": f"{lear_realm.id}", + "plan_end_date": "2050-03-01", + }, + ) + self.assert_in_success_response( + ["Current plan for lear updated to end on 2050-03-01."], + result, + ) + + plan.refresh_from_db() + self.assertEqual(plan.end_date, datetime(2050, 3, 1, tzinfo=timezone.utc)) + + result = self.client_post( + "/activity/support", + { + "realm_id": f"{lear_realm.id}", + "required_plan_tier": f"{plan_offer_tier}", + }, + ) + self.assert_in_success_response( + [f"Required plan tier for lear set to {plan_offer_tier_name}."], + result, + ) + + # Configuring a fixed-price plan requires any current + # plan to have all invoices prior to the final invoice + # processed. + result = self.client_post( + "/activity/support", + { + "realm_id": f"{lear_realm.id}", + "fixed_price": 360, + }, + ) + self.assert_in_success_response( + [ + "New plan for lear cannot be scheduled until all the invoices of the current plan are processed." + ], + result, + ) + + billing_session = RealmBillingSession(user=iago, realm=lear_realm, support_session=True) + next_billing_cycle = billing_session.get_next_billing_cycle(plan).strftime("%Y-%m-%d") + with time_machine.travel(datetime(2016, 1, 3, tzinfo=timezone.utc), tick=False): + result = self.client_post( + "/activity/support", + { + "realm_id": f"{lear_realm.id}", + "plan_end_date": next_billing_cycle, + }, + ) + self.assert_in_success_response( + [f"Current plan for lear updated to end on {next_billing_cycle}."], + result, + ) + + plan.refresh_from_db() + self.assertEqual(plan.end_date, datetime(2016, 2, 2, tzinfo=timezone.utc)) + self.assertEqual(plan.status, CustomerPlan.ACTIVE) + next_plan = billing_session.get_next_plan(plan) + assert next_plan is None + + result = self.client_post( + "/activity/support", + { + "realm_id": f"{lear_realm.id}", + "fixed_price": 360, + }, + ) + self.assert_in_success_response( + [ + f"Fixed price {plan_offer_tier_name} plan scheduled to start on {next_billing_cycle}." + ], + result, + ) + + plan.refresh_from_db() + self.assertEqual(plan.end_date, datetime(2016, 2, 2, tzinfo=timezone.utc)) + self.assertEqual(plan.status, CustomerPlan.SWITCH_PLAN_TIER_AT_PLAN_END) + next_plan = billing_session.get_next_plan(plan) + assert next_plan is not None + self.assertEqual(next_plan.fixed_price, 36000) + self.assertEqual(next_plan.billing_cycle_anchor, plan.end_date) + self.assertEqual(next_plan.charge_automatically, plan.charge_automatically) + self.assertTrue(next_plan.automanage_licenses) + def test_approve_sponsorship_deactivated_realm(self) -> None: support_admin = self.example_user("iago") with self.settings(BILLING_ENABLED=True): diff --git a/corporate/views/support.py b/corporate/views/support.py index c2c1ceeb24..5dbcce268d 100644 --- a/corporate/views/support.py +++ b/corporate/views/support.py @@ -421,6 +421,9 @@ def support( max_invites: Json[NonNegativeInt] | None = None, plan_end_date: Annotated[str, AfterValidator(lambda x: check_date("plan_end_date", x))] | None = None, + fixed_price: Json[NonNegativeInt] | None = None, + sent_invoice_id: str | None = None, + delete_fixed_price_next_plan: Json[bool] = False, ) -> HttpResponse: from corporate.lib.stripe import ( RealmBillingSession, @@ -489,6 +492,19 @@ def support( support_type=SupportType.update_plan_end_date, plan_end_date=plan_end_date, ) + elif fixed_price is not None: + # Treat empty string for send_invoice_id as None. + if sent_invoice_id is not None and sent_invoice_id.strip() == "": + sent_invoice_id = None + support_view_request = SupportViewRequest( + support_type=SupportType.configure_fixed_price_plan, + fixed_price=fixed_price, + sent_invoice_id=sent_invoice_id, + ) + elif delete_fixed_price_next_plan: + support_view_request = SupportViewRequest( + support_type=SupportType.delete_fixed_price_next_plan, + ) elif plan_type is not None: current_plan_type = realm.plan_type do_change_realm_plan_type(realm, plan_type, acting_user=acting_user) diff --git a/templates/corporate/support/realm_details.html b/templates/corporate/support/realm_details.html index dbc9868728..34ba7d398a 100644 --- a/templates/corporate/support/realm_details.html +++ b/templates/corporate/support/realm_details.html @@ -135,6 +135,27 @@ {% endif %} + {% if realm_support_data[realm.id].plan_data.next_plan %} +
+ {% elif not realm.deactivated %} + + {% endif %} +