From 8cba101e05bc3d1991db96bb64fdd8c80ad9d9c9 Mon Sep 17 00:00:00 2001 From: Aman Agrawal Date: Tue, 13 Feb 2024 12:23:07 +0000 Subject: [PATCH] support: Add button to delete configured fixed next plan. This will help us modify the configured plan if we need to. --- corporate/lib/stripe.py | 10 ++++ corporate/tests/test_stripe.py | 55 +++++++++++++++++++ corporate/views/support.py | 5 ++ .../corporate/support/next_plan_details.html | 8 +++ .../support/remote_realm_details.html | 2 + .../support/remote_server_support.html | 2 + web/styles/portico/activity.css | 2 + 7 files changed, 84 insertions(+) diff --git a/corporate/lib/stripe.py b/corporate/lib/stripe.py index 51f84e87bc..a302591a76 100644 --- a/corporate/lib/stripe.py +++ b/corporate/lib/stripe.py @@ -571,6 +571,7 @@ class SupportType(Enum): update_plan_end_date = 7 update_required_plan_tier = 8 configure_fixed_price_plan = 9 + delete_fixed_price_next_plan = 10 class SupportViewRequest(TypedDict, total=False): @@ -3030,6 +3031,15 @@ class BillingSession(ABC): assert support_request["new_plan_tier"] is not None new_plan_tier = support_request["new_plan_tier"] success_message = self.do_change_plan_to_new_tier(new_plan_tier) + elif support_type == SupportType.delete_fixed_price_next_plan: + customer = self.get_customer() + assert customer is not None + fixed_price_offer = CustomerPlanOffer.objects.filter( + customer=customer, status=CustomerPlanOffer.CONFIGURED + ).first() + assert fixed_price_offer is not None + fixed_price_offer.delete() + success_message = "Fixed price offer deleted" return success_message diff --git a/corporate/tests/test_stripe.py b/corporate/tests/test_stripe.py index f06774cc0a..337c64ad38 100644 --- a/corporate/tests/test_stripe.py +++ b/corporate/tests/test_stripe.py @@ -6350,6 +6350,61 @@ class TestRemoteRealmBillingFlow(StripeTestCase, RemoteRealmBillingTestCase): ]: self.assert_in_response(substring, response) + @responses.activate + @mock_stripe() + def test_delete_configured_fixed_price_plan_offer(self, *mocks: Mock) -> None: + self.login("iago") + + self.add_mock_response() + with time_machine.travel(self.now, tick=False): + send_server_data_to_push_bouncer(consider_usage_statistics=False) + + self.assertFalse(CustomerPlanOffer.objects.exists()) + + annual_fixed_price = 1200 + # Configure required_plan_tier and fixed_price. + result = self.client_post( + "/activity/remote/support", + { + "remote_realm_id": f"{self.remote_realm.id}", + "required_plan_tier": CustomerPlan.TIER_SELF_HOSTED_BASIC, + }, + ) + self.assert_in_success_response( + ["Required plan tier for Zulip Dev set to Zulip Basic."], result + ) + + result = self.client_post( + "/activity/remote/support", + {"remote_realm_id": f"{self.remote_realm.id}", "fixed_price": annual_fixed_price}, + ) + self.assert_in_success_response( + ["Customer can now buy a fixed price Zulip Basic plan."], result + ) + fixed_price_plan_offer = CustomerPlanOffer.objects.filter( + status=CustomerPlanOffer.CONFIGURED + ).first() + assert fixed_price_plan_offer is not None + self.assertEqual(fixed_price_plan_offer.tier, CustomerPlanOffer.TIER_SELF_HOSTED_BASIC) + self.assertEqual(fixed_price_plan_offer.fixed_price, annual_fixed_price * 100) + self.assertEqual(fixed_price_plan_offer.get_plan_status_as_text(), "Configured") + + result = self.client_get("/activity/remote/support", {"q": "example.com"}) + self.assert_in_success_response( + ["Next plan information:", "Zulip Basic", "Configured", "Plan has a fixed price."], + result, + ) + + billing_session = RemoteRealmBillingSession(remote_realm=self.remote_realm) + support_request = SupportViewRequest( + support_type=SupportType.delete_fixed_price_next_plan, + ) + success_message = billing_session.process_support_view_request(support_request) + self.assertEqual(success_message, "Fixed price offer deleted") + result = self.client_get("/activity/remote/support", {"q": "example.com"}) + self.assert_not_in_success_response(["Next plan information:"], result) + self.assert_in_success_response(["Fixed price", "Annual amount in dollars"], result) + @responses.activate @mock_stripe() def test_upgrade_user_to_fixed_price_plan_pay_by_invoice(self, *mocks: Mock) -> None: diff --git a/corporate/views/support.py b/corporate/views/support.py index c1f2d3a33b..b8903ce627 100644 --- a/corporate/views/support.py +++ b/corporate/views/support.py @@ -503,6 +503,7 @@ def remote_servers_support( modify_plan: Optional[str] = REQ( default=None, str_validator=check_string_in(VALID_MODIFY_PLAN_METHODS) ), + delete_fixed_price_next_plan: bool = REQ(default=False, json_validator=check_bool), ) -> HttpResponse: context: Dict[str, Any] = {} @@ -573,6 +574,10 @@ def remote_servers_support( support_type=SupportType.modify_plan, plan_modification=modify_plan, ) + elif delete_fixed_price_next_plan: + support_view_request = SupportViewRequest( + support_type=SupportType.delete_fixed_price_next_plan, + ) if support_view_request is not None: if remote_realm_support_request: try: diff --git a/templates/corporate/support/next_plan_details.html b/templates/corporate/support/next_plan_details.html index 963a270e7f..68aa61b3d3 100644 --- a/templates/corporate/support/next_plan_details.html +++ b/templates/corporate/support/next_plan_details.html @@ -16,3 +16,11 @@ {% endif %} {% endif %} Estimated annual revenue: ${{ dollar_amount(plan_data.estimated_next_plan_revenue) }}
+{% if plan_data.next_plan.fixed_price %} +
+ {{ csrf_input }} + + + +
+{% endif %} diff --git a/templates/corporate/support/remote_realm_details.html b/templates/corporate/support/remote_realm_details.html index 1f8e20ae57..103c74bf2d 100644 --- a/templates/corporate/support/remote_realm_details.html +++ b/templates/corporate/support/remote_realm_details.html @@ -63,6 +63,8 @@ {% set plan_data = support_data[remote_realm.id].plan_data %} {% set format_discount = format_discount %} {% set dollar_amount = dollar_amount %} + {% set remote_id = remote_realm.id %} + {% set remote_type = "remote_realm_id" %} {% include 'corporate/support/next_plan_details.html' %} {% endwith %} diff --git a/templates/corporate/support/remote_server_support.html b/templates/corporate/support/remote_server_support.html index eaf3c4160a..b6e0493c70 100644 --- a/templates/corporate/support/remote_server_support.html +++ b/templates/corporate/support/remote_server_support.html @@ -103,6 +103,8 @@ {% set plan_data = remote_servers_support_data[remote_server.id].plan_data %} {% set format_discount = format_discount %} {% set dollar_amount = dollar_amount %} + {% set remote_id = remote_server.id %} + {% set remote_type = "remote_server_id" %} {% include 'corporate/support/next_plan_details.html' %} {% endwith %} diff --git a/web/styles/portico/activity.css b/web/styles/portico/activity.css index 83eaef0211..476e246e3d 100644 --- a/web/styles/portico/activity.css +++ b/web/styles/portico/activity.css @@ -170,6 +170,7 @@ tr.admin td:first-child { } } +.delete-next-fixed-price-plan-button, .approve-sponsorship-button, .support-search-button, .support-submit-button, @@ -228,6 +229,7 @@ tr.admin td:first-child { } } +.delete-next-fixed-price-plan-button, .delete-user-button, .scrub-realm-button { color: hsl(0deg 0% 100%);