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 fc987d29f93..bc13afb2792 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 @@ -268,22 +268,17 @@ class MaterialRequirementsPlanningReport: def get_detailed_view_chart_data(self, data): chart_data = frappe._dict({}) - i = 0 sorted_data = sorted(data, key=lambda x: getdate(x.get("delivery_date"))) for row in sorted_data: - if getdate(row.deliver_date) < getdate(today()): - continue - if not row.delivery_date: continue - if i == 10: - break + 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: - i += 1 chart_data[delivery_date] = frappe._dict( { "demand": 0.0, @@ -299,6 +294,7 @@ class MaterialRequirementsPlanningReport: demand_data = [] supply_data = [] + delivery_dates = list(chart_data) for row in chart_data: value = chart_data[row] @@ -307,7 +303,7 @@ class MaterialRequirementsPlanningReport: return { "data": { - "labels": list(chart_data.keys()), + "labels": self.get_detailed_chart_labels(delivery_dates), "datasets": [ { "name": _("Demand"), @@ -325,6 +321,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 new file mode 100644 index 00000000000..a449f27f8a6 --- /dev/null +++ b/erpnext/manufacturing/report/material_requirements_planning_report/test_material_requirements_planning_report.py @@ -0,0 +1,72 @@ +# Copyright (c) 2024, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt + +import frappe +from frappe.tests.classes.context_managers import freeze_time +from frappe.utils import add_days, formatdate, today + +from erpnext.manufacturing.report.material_requirements_planning_report.material_requirements_planning_report import ( + MaterialRequirementsPlanningReport, +) +from erpnext.tests.utils import ERPNextTestSuite + + +class TestMaterialRequirementsPlanningReport(ERPNextTestSuite): + def test_detailed_chart_includes_full_date_range(self): + 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) + + 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): + 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) + + self.assertEqual( + chart["data"]["labels"], + [formatdate(delivery_date, "dd MMM") for delivery_date in delivery_dates], + ) + + +def make_chart_row(delivery_date, planned_qty=1): + return frappe._dict( + { + "delivery_date": delivery_date, + "planned_qty": planned_qty, + "in_hand_qty": 0, + "po_ordered_qty": 0, + "wo_ordered_qty": 0, + } + )