From 196730c53563f2fdcfe62df21c1718f15f59e2e0 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 3 Jul 2026 14:08:20 +0530 Subject: [PATCH] fix: bill all months across a year boundary in Monthly Rate plans --- .../doctype/subscription_plan/subscription_plan.py | 4 +++- .../subscription_plan/test_subscription_plan.py | 10 ++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/erpnext/accounts/doctype/subscription_plan/subscription_plan.py b/erpnext/accounts/doctype/subscription_plan/subscription_plan.py index 932caaa2db2..630cc39b0b1 100644 --- a/erpnext/accounts/doctype/subscription_plan/subscription_plan.py +++ b/erpnext/accounts/doctype/subscription_plan/subscription_plan.py @@ -79,7 +79,9 @@ def get_plan_rate( start_date = getdate(start_date) end_date = getdate(end_date) - no_of_months = relativedelta.relativedelta(end_date, start_date).months + 1 + delta = relativedelta.relativedelta(end_date, start_date) + # include the years component so cross-year spans aren't under-counted + no_of_months = delta.years * 12 + delta.months + 1 cost = plan.cost * no_of_months # Adjust cost if start or end date is not month start or end diff --git a/erpnext/accounts/doctype/subscription_plan/test_subscription_plan.py b/erpnext/accounts/doctype/subscription_plan/test_subscription_plan.py index 48bf885a813..057e083eda0 100644 --- a/erpnext/accounts/doctype/subscription_plan/test_subscription_plan.py +++ b/erpnext/accounts/doctype/subscription_plan/test_subscription_plan.py @@ -45,12 +45,10 @@ class TestSubscriptionPlan(ERPNextTestSuite): rate = get_plan_rate(plan.name, start_date="2026-01-01", end_date="2026-03-31") self.assertEqual(rate, 300) - def test_monthly_rate_across_year_boundary_underbills(self): - # SUSPECTED BUG: no_of_months uses relativedelta(end, start).months, which drops - # the years component, so a 14-month span (Jan 2026 to Feb 2027) that should bill - # 1400 (14 x 100) is billed as only 200 (2 months). Locking the current (wrong) - # value so a fix trips this test; the correct expectation is 1400. + def test_monthly_rate_across_year_boundary(self): + # a 14-month span (Jan 2026 to Feb 2027) bills all 14 months, not just the + # 2-month remainder that relativedelta.months alone would give plan = self.make_plan(price_determination="Monthly Rate", cost=100) plan.insert() rate = get_plan_rate(plan.name, start_date="2026-01-01", end_date="2027-02-28") - self.assertEqual(rate, 200) + self.assertEqual(rate, 1400)