diff --git a/corporate/lib/stripe.py b/corporate/lib/stripe.py index 94e0e5c935..261f269b65 100644 --- a/corporate/lib/stripe.py +++ b/corporate/lib/stripe.py @@ -313,12 +313,7 @@ def next_invoice_date(plan: CustomerPlan) -> Optional[datetime]: if plan.status == CustomerPlan.ENDED: return None assert plan.next_invoice_date is not None # for mypy - months_per_period = { - CustomerPlan.BILLING_SCHEDULE_ANNUAL: 12, - CustomerPlan.BILLING_SCHEDULE_MONTHLY: 1, - }[plan.billing_schedule] - if plan.automanage_licenses: - months_per_period = 1 + months_per_period = 1 periods = 1 dt = plan.billing_cycle_anchor while dt <= plan.next_invoice_date: @@ -1657,7 +1652,6 @@ class BillingSession(ABC): price_per_license, ) = compute_plan_parameters( plan_tier, - automanage_licenses, billing_schedule, discount_for_plan, free_trial, @@ -1923,7 +1917,6 @@ class BillingSession(ABC): discount_for_current_plan = plan.discount _, _, _, price_per_license = compute_plan_parameters( tier=plan.tier, - automanage_licenses=plan.automanage_licenses, billing_schedule=schedule, discount=discount_for_current_plan, ) @@ -2069,7 +2062,6 @@ class BillingSession(ABC): discount_for_current_plan = plan.discount _, _, _, price_per_license = compute_plan_parameters( tier=plan.tier, - automanage_licenses=plan.automanage_licenses, billing_schedule=CustomerPlan.BILLING_SCHEDULE_ANNUAL, discount=discount_for_current_plan, ) @@ -2118,7 +2110,6 @@ class BillingSession(ABC): discount_for_current_plan = plan.discount _, _, _, price_per_license = compute_plan_parameters( tier=plan.tier, - automanage_licenses=plan.automanage_licenses, billing_schedule=CustomerPlan.BILLING_SCHEDULE_MONTHLY, discount=discount_for_current_plan, ) @@ -2469,7 +2460,6 @@ class BillingSession(ABC): if free_trial_days is not None: _, _, free_trial_end, _ = compute_plan_parameters( tier, - False, CustomerPlan.BILLING_SCHEDULE_ANNUAL, None, True, @@ -4716,7 +4706,6 @@ def get_price_per_license( def compute_plan_parameters( tier: int, - automanage_licenses: bool, billing_schedule: int, discount: Optional[Decimal], free_trial: bool = False, @@ -4739,9 +4728,9 @@ def compute_plan_parameters( price_per_license = get_price_per_license(tier, billing_schedule, discount) - next_invoice_date = period_end - if automanage_licenses: - next_invoice_date = add_months(billing_cycle_anchor, 1) + # `next_invoice_date` is the date when we check if there are any invoices that need to be generated. + # It is always the next month regardless of the billing schedule / billing modality. + next_invoice_date = add_months(billing_cycle_anchor, 1) if free_trial: period_end = billing_cycle_anchor + timedelta( days=assert_is_not_none(get_free_trial_days(is_self_hosted_billing, tier)) diff --git a/corporate/tests/test_stripe.py b/corporate/tests/test_stripe.py index bdd2c17f75..5d70ab3655 100644 --- a/corporate/tests/test_stripe.py +++ b/corporate/tests/test_stripe.py @@ -1039,7 +1039,7 @@ class StripeTest(StripeTestCase): billing_cycle_anchor=self.now, billing_schedule=CustomerPlan.BILLING_SCHEDULE_ANNUAL, invoiced_through=LicenseLedger.objects.first(), - next_invoice_date=self.next_year, + next_invoice_date=self.next_month, tier=CustomerPlan.TIER_CLOUD_STANDARD, status=CustomerPlan.ACTIVE, ) @@ -1438,7 +1438,7 @@ class StripeTest(StripeTestCase): customer_plan.refresh_from_db() realm.refresh_from_db() self.assertEqual(customer_plan.status, CustomerPlan.ACTIVE) - self.assertEqual(customer_plan.next_invoice_date, add_months(free_trial_end_date, 12)) + self.assertEqual(customer_plan.next_invoice_date, add_months(free_trial_end_date, 1)) self.assertEqual(realm.plan_type, Realm.PLAN_TYPE_STANDARD) [invoice] = iter(stripe.Invoice.list(customer=stripe_customer.id)) invoice_params = { @@ -2719,7 +2719,7 @@ class StripeTest(StripeTestCase): annual_plan.refresh_from_db() self.assertEqual(annual_plan.invoiced_through, annual_ledger_entries[0]) - self.assertEqual(annual_plan.next_invoice_date, add_months(self.next_month, 12)) + self.assertEqual(annual_plan.next_invoice_date, add_months(self.next_month, 1)) self.assertEqual(annual_plan.invoicing_status, CustomerPlan.INVOICING_STATUS_DONE) assert customer.stripe_customer_id @@ -2743,7 +2743,8 @@ class StripeTest(StripeTestCase): with patch("corporate.lib.stripe.BillingSession.invoice_plan") as m: invoice_plans_as_needed(add_months(self.now, 2)) - m.assert_not_called() + # Even annual plans get invoiced monthly for additional licenses. + m.assert_called_once() invoice_plans_as_needed(add_months(self.now, 13)) @@ -4542,46 +4543,42 @@ class BillingHelpersTest(ZulipTestCase): ( ( CustomerPlan.TIER_CLOUD_STANDARD, - True, CustomerPlan.BILLING_SCHEDULE_ANNUAL, None, ), (anchor, month_later, year_later, 8000), ), ( - (CustomerPlan.TIER_CLOUD_STANDARD, True, CustomerPlan.BILLING_SCHEDULE_ANNUAL, 85), + (CustomerPlan.TIER_CLOUD_STANDARD, CustomerPlan.BILLING_SCHEDULE_ANNUAL, 85), (anchor, month_later, year_later, 1200), ), ( ( CustomerPlan.TIER_CLOUD_STANDARD, - True, CustomerPlan.BILLING_SCHEDULE_MONTHLY, None, ), (anchor, month_later, month_later, 800), ), ( - (CustomerPlan.TIER_CLOUD_STANDARD, True, CustomerPlan.BILLING_SCHEDULE_MONTHLY, 85), + (CustomerPlan.TIER_CLOUD_STANDARD, CustomerPlan.BILLING_SCHEDULE_MONTHLY, 85), (anchor, month_later, month_later, 120), ), ( ( CustomerPlan.TIER_CLOUD_STANDARD, - False, CustomerPlan.BILLING_SCHEDULE_ANNUAL, None, ), - (anchor, year_later, year_later, 8000), + (anchor, month_later, year_later, 8000), ), ( - (CustomerPlan.TIER_CLOUD_STANDARD, False, CustomerPlan.BILLING_SCHEDULE_ANNUAL, 85), - (anchor, year_later, year_later, 1200), + (CustomerPlan.TIER_CLOUD_STANDARD, CustomerPlan.BILLING_SCHEDULE_ANNUAL, 85), + (anchor, month_later, year_later, 1200), ), ( ( CustomerPlan.TIER_CLOUD_STANDARD, - False, CustomerPlan.BILLING_SCHEDULE_MONTHLY, None, ), @@ -4590,7 +4587,6 @@ class BillingHelpersTest(ZulipTestCase): ( ( CustomerPlan.TIER_CLOUD_STANDARD, - False, CustomerPlan.BILLING_SCHEDULE_MONTHLY, 85, ), @@ -4600,7 +4596,6 @@ class BillingHelpersTest(ZulipTestCase): ( ( CustomerPlan.TIER_CLOUD_STANDARD, - False, CustomerPlan.BILLING_SCHEDULE_MONTHLY, 87.25, ), @@ -4610,7 +4605,6 @@ class BillingHelpersTest(ZulipTestCase): ( ( CustomerPlan.TIER_CLOUD_STANDARD, - False, CustomerPlan.BILLING_SCHEDULE_MONTHLY, 87.15, ), @@ -4618,10 +4612,9 @@ class BillingHelpersTest(ZulipTestCase): ), ] with time_machine.travel(anchor, tick=False): - for (tier, automanage_licenses, billing_schedule, discount), output in test_cases: + for (tier, billing_schedule, discount), output in test_cases: output_ = compute_plan_parameters( tier, - automanage_licenses, billing_schedule, None if discount is None else Decimal(discount), )