From 5ad085887d38136f3daf2797b2bde6735ecab85f Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Wed, 12 Aug 2026 12:28:13 +0530 Subject: [PATCH] fix(manufacturing): keep MRP chart dates distinct --- .../material_requirements_planning_report.py | 9 ++- ...t_material_requirements_planning_report.py | 61 ++++++++++++------- 2 files changed, 47 insertions(+), 23 deletions(-) diff --git a/erpnext/manufacturing/report/material_requirements_planning_report/material_requirements_planning_report.py b/erpnext/manufacturing/report/material_requirements_planning_report/material_requirements_planning_report.py index 70b252d97c4..c3e45e755ac 100644 --- a/erpnext/manufacturing/report/material_requirements_planning_report/material_requirements_planning_report.py +++ b/erpnext/manufacturing/report/material_requirements_planning_report/material_requirements_planning_report.py @@ -276,7 +276,7 @@ class MaterialRequirementsPlanningReport: if getdate(row.delivery_date) < getdate(today()): continue - delivery_date = formatdate(row.delivery_date, "dd MMM") + delivery_date = getdate(row.delivery_date) if delivery_date not in chart_data: chart_data[delivery_date] = frappe._dict( { @@ -293,6 +293,7 @@ class MaterialRequirementsPlanningReport: demand_data = [] supply_data = [] + delivery_dates = list(chart_data) for row in chart_data: value = chart_data[row] @@ -301,7 +302,7 @@ class MaterialRequirementsPlanningReport: return { "data": { - "labels": list(chart_data.keys()), + "labels": self.get_detailed_chart_labels(delivery_dates), "datasets": [ { "name": _("Demand"), @@ -319,6 +320,10 @@ class MaterialRequirementsPlanningReport: "title": _("Demand vs Supply"), } + def get_detailed_chart_labels(self, delivery_dates): + date_format = "dd MMM yyyy" if len({date.year for date in delivery_dates}) > 1 else "dd MMM" + return [formatdate(date, date_format) for date in delivery_dates] + def get_bucket_view_chart_data(self, data): chart_data = frappe._dict({}) labels = [] diff --git a/erpnext/manufacturing/report/material_requirements_planning_report/test_material_requirements_planning_report.py b/erpnext/manufacturing/report/material_requirements_planning_report/test_material_requirements_planning_report.py index d91f44be985..d7f7ca9e725 100644 --- a/erpnext/manufacturing/report/material_requirements_planning_report/test_material_requirements_planning_report.py +++ b/erpnext/manufacturing/report/material_requirements_planning_report/test_material_requirements_planning_report.py @@ -2,6 +2,7 @@ # See license.txt import frappe +from frappe.tests.classes.context_managers import freeze_time from frappe.utils import add_days, flt, formatdate, today from erpnext.accounts.doctype.tax_rule.test_tax_rule import make_tax_rule @@ -23,33 +24,51 @@ TAX_TEMPLATE = "_Test Purchase Taxes and Charges Template - _TC" class TestMaterialRequirementsPlanningReport(ERPNextTestSuite): def test_detailed_chart_includes_full_date_range(self): - start_date = add_days(today(), 1) - delivery_dates = [add_days(start_date, offset) for offset in range(12)] - rows = [make_chart_row(delivery_date) for delivery_date in delivery_dates] - rows.append(make_chart_row(delivery_dates[-1], planned_qty=2)) + with freeze_time("2026-08-12"): + start_date = add_days(today(), 1) + delivery_dates = [add_days(start_date, offset) for offset in range(12)] + rows = [make_chart_row(delivery_date) for delivery_date in delivery_dates] + rows.append(make_chart_row(delivery_dates[-1], planned_qty=2)) - chart = MaterialRequirementsPlanningReport(frappe._dict()).get_detailed_view_chart_data(rows) + chart = MaterialRequirementsPlanningReport(frappe._dict()).get_detailed_view_chart_data(rows) - self.assertEqual( - chart["data"]["labels"], - [formatdate(delivery_date, "dd MMM") for delivery_date in delivery_dates], - ) - self.assertEqual(chart["data"]["datasets"][0]["values"], [1] * 11 + [3]) + self.assertEqual( + chart["data"]["labels"], + [formatdate(delivery_date, "dd MMM") for delivery_date in delivery_dates], + ) + self.assertEqual(chart["data"]["datasets"][0]["values"], [1] * 11 + [3]) + + def test_detailed_chart_distinguishes_delivery_dates_across_years(self): + with freeze_time("2026-08-12"): + delivery_dates = ["2026-08-15", "2027-08-15"] + rows = [ + make_chart_row(delivery_dates[0]), + make_chart_row(delivery_dates[1], planned_qty=2), + ] + + chart = MaterialRequirementsPlanningReport(frappe._dict()).get_detailed_view_chart_data(rows) + + self.assertEqual( + chart["data"]["labels"], + [formatdate(delivery_date, "dd MMM yyyy") for delivery_date in delivery_dates], + ) + self.assertEqual(chart["data"]["datasets"][0]["values"], [1, 2]) def test_detailed_chart_excludes_past_and_empty_delivery_dates(self): - delivery_dates = [today(), add_days(today(), 1)] - rows = [ - make_chart_row(add_days(today(), -1)), - make_chart_row(None), - *[make_chart_row(delivery_date) for delivery_date in delivery_dates], - ] + with freeze_time("2026-08-12"): + delivery_dates = [today(), add_days(today(), 1)] + rows = [ + make_chart_row(add_days(today(), -1)), + make_chart_row(None), + *[make_chart_row(delivery_date) for delivery_date in delivery_dates], + ] - chart = MaterialRequirementsPlanningReport(frappe._dict()).get_detailed_view_chart_data(rows) + chart = MaterialRequirementsPlanningReport(frappe._dict()).get_detailed_view_chart_data(rows) - self.assertEqual( - chart["data"]["labels"], - [formatdate(delivery_date, "dd MMM") for delivery_date in delivery_dates], - ) + self.assertEqual( + chart["data"]["labels"], + [formatdate(delivery_date, "dd MMM") for delivery_date in delivery_dates], + ) def test_manufacture_lead_time_is_not_int_truncated(self): """lead_time = 1440 / manufacturing_time_in_mins + buffer_time. Both columns are Int;