Merge pull request #50318 from rohitwaghchaure/fixed-mrp-issues

fix: multiple MRP issues
This commit is contained in:
rohitwaghchaure
2025-11-03 17:35:17 +05:30
committed by GitHub
7 changed files with 52 additions and 78 deletions

View File

@@ -284,9 +284,6 @@ class MasterProductionSchedule(Document):
row = data[key]
row.cumulative_lead_time = math.ceil(row.cumulative_lead_time)
row.order_release_date = add_days(row.delivery_date, -row.cumulative_lead_time)
if getdate(row.order_release_date) < getdate(today()):
continue
row.planned_qty = row.qty
row.uom = row.stock_uom
row.warehouse = row.warehouse or self.parent_warehouse

View File

@@ -84,7 +84,7 @@ class SalesForecast(Document):
)
for index in range(self.demand_number):
if self.horizon_type == "Monthly":
if self.frequency == "Monthly":
delivery_date = add_to_date(self.from_date, months=index + 1)
else:
delivery_date = add_to_date(self.from_date, weeks=index + 1)
@@ -95,15 +95,13 @@ class SalesForecast(Document):
"delivery_date": delivery_date,
"item_name": item_details.item_name,
"uom": item_details.uom,
"demand_qty": 0.0,
"demand_qty": 1.0,
}
)
for demand in forecast_demand:
self.append("items", demand)
self.save()
@frappe.whitelist()
def generate_demand(self):
from statsmodels.tsa.holtwinters import ExponentialSmoothing
@@ -124,7 +122,7 @@ class SalesForecast(Document):
seasonal_periods = self.get_seasonal_periods(data)
pd_sales_data = pd.DataFrame({"item": data.item, "date": data.date, "qty": data.qty})
resample_val = "M" if self.horizon_type == "Monthly" else "W"
resample_val = "M" if self.frequency == "Monthly" else "W"
_sales_data = pd_sales_data.set_index("date").resample(resample_val).sum()["qty"]
model = ExponentialSmoothing(
@@ -164,7 +162,7 @@ class SalesForecast(Document):
def get_seasonal_periods(self, data):
days = date_diff(data["end_date"], data["start_date"])
if self.horizon_type == "Monthly":
if self.frequency == "Monthly":
months = (days / 365) * 12
seasonal_periods = cint(months / 2)
if seasonal_periods > 12:

View File

@@ -77,13 +77,6 @@ frappe.query_reports["Material Requirements Planning Report"] = {
default: "All",
options: "\nFinished Goods\nRaw Materials\nAll",
},
{
fieldname: "safety_stock_check_frequency",
label: __("Safety Stock Check Frequency"),
fieldtype: "Select",
default: "Weekly",
options: "\nDaily\nWeekly\nMonthly",
},
{
fieldname: "add_safety_stock",
label: __("Add Safety Stock"),

View File

@@ -41,8 +41,9 @@ class MaterialRequirementsPlanningReport:
self.rm_items = []
self.dates = self.get_dates()
self.mps_data = self.get_mps_data()
items = self.get_items_from_mps(self.mps_data)
self.update_sales_forecast_data()
self.item_rm_details = self.get_raw_materials_data(items)
self._bin_details = self.get_item_wise_bin_details()
@@ -52,7 +53,6 @@ class MaterialRequirementsPlanningReport:
self._po_details = self.get_purchase_order_data()
self._so_details = self.get_sales_order_data()
self.update_sales_forecast_data()
data, chart = self.get_mrp_data()
return data, chart
@@ -850,6 +850,23 @@ class MaterialRequirementsPlanningReport:
if row.item_code not in items:
items.append(row.item_code)
if self.filters.mps:
sales_forecasts = frappe.get_all(
"Master Production Schedule",
filters={"name": self.filters.mps},
pluck="sales_forecast",
)
if sales_forecasts:
sales_forecast_items = frappe.get_all(
"Sales Forecast Item",
filters={"parent": ("in", sales_forecasts)},
pluck="item_code",
)
if sales_forecast_items:
items.extend(sales_forecast_items)
return items
def get_raw_materials_data(self, items):
@@ -1139,7 +1156,12 @@ class MaterialRequirementsPlanningReport:
query = query.where(doctype.delivery_date <= self.filters.to_date)
if self.filters.warehouse:
query = query.where(doctype.warehouse == self.filters.warehouse)
warehouses = [self.filters.get("warehouse")]
if frappe.db.get_value("Warehouse", self.filters.get("warehouse"), "is_group"):
warehouses = get_descendants_of("Warehouse", self.filters.get("warehouse"))
warehouses.append(self.filters.get("warehouse"))
query = query.where(forecast_doc.parent_warehouse.isin(warehouses))
if self.filters.item_code:
query = query.where(doctype.item_code == self.filters.item_code)

View File

@@ -347,7 +347,7 @@
"hidden": 0,
"is_query_report": 0,
"label": "Production",
"link_count": 7,
"link_count": 8,
"link_type": "DocType",
"onboard": 0,
"type": "Card Break"
@@ -385,16 +385,6 @@
"onboard": 1,
"type": "Link"
},
{
"hidden": 0,
"is_query_report": 0,
"label": "Master Production Schedule",
"link_count": 0,
"link_to": "Master Production Schedule",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"dependencies": "",
"hidden": 0,
@@ -406,6 +396,26 @@
"onboard": 0,
"type": "Link"
},
{
"hidden": 0,
"is_query_report": 0,
"label": "Item Lead Time",
"link_count": 0,
"link_to": "Item Lead Time",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"hidden": 0,
"is_query_report": 0,
"label": "Master Production Schedule",
"link_count": 0,
"link_to": "Master Production Schedule",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"dependencies": "",
"hidden": 0,
@@ -428,7 +438,7 @@
"type": "Link"
}
],
"modified": "2025-10-30 11:49:35.589944",
"modified": "2025-11-03 17:02:26.882516",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "Manufacturing",

View File

@@ -119,12 +119,6 @@
"default_item_manufacturer",
"default_manufacturer_part_no",
"total_projected_qty",
"lead_time_in_days_section",
"procurement_time",
"manufacturing_time",
"column_break_whvr",
"planning_buffer",
"cumulative_time",
"capacity_in_days_section",
"production_capacity"
],
@@ -894,36 +888,6 @@
"fieldtype": "Section Break",
"label": "Deferred Accounting"
},
{
"fieldname": "lead_time_in_days_section",
"fieldtype": "Section Break",
"label": "Lead Time (In Days)"
},
{
"fieldname": "procurement_time",
"fieldtype": "Int",
"label": "Procurement Time"
},
{
"fieldname": "planning_buffer",
"fieldtype": "Int",
"label": "Planning Buffer"
},
{
"fieldname": "column_break_whvr",
"fieldtype": "Column Break"
},
{
"fieldname": "manufacturing_time",
"fieldtype": "Int",
"label": "Manufacturing Time"
},
{
"fieldname": "cumulative_time",
"fieldtype": "Int",
"label": "Cumulative Time",
"read_only": 1
},
{
"fieldname": "capacity_in_days_section",
"fieldtype": "Section Break",
@@ -953,7 +917,7 @@
"image_field": "image",
"links": [],
"make_attachments_public": 1,
"modified": "2025-10-13 16:58:40.946604",
"modified": "2025-11-03 17:01:24.555003",
"modified_by": "Administrator",
"module": "Stock",
"name": "Item",

View File

@@ -81,7 +81,6 @@ class Item(Document):
brand: DF.Link | None
country_of_origin: DF.Link | None
create_new_batch: DF.Check
cumulative_time: DF.Int
customer: DF.Link | None
customer_code: DF.SmallText | None
customer_items: DF.Table[ItemCustomerDetail]
@@ -120,7 +119,6 @@ class Item(Document):
item_name: DF.Data | None
last_purchase_rate: DF.Float
lead_time_days: DF.Int
manufacturing_time: DF.Int
max_discount: DF.Float
min_order_qty: DF.Float
naming_series: DF.Literal["STO-ITEM-.YYYY.-"]
@@ -129,8 +127,6 @@ class Item(Document):
opening_stock: DF.Float
over_billing_allowance: DF.Float
over_delivery_receipt_allowance: DF.Float
planning_buffer: DF.Int
procurement_time: DF.Int
production_capacity: DF.Int
purchase_uom: DF.Link | None
quality_inspection_template: DF.Link | None
@@ -221,16 +217,10 @@ class Item(Document):
self.validate_auto_reorder_enabled_in_stock_settings()
self.cant_change()
self.validate_item_tax_net_rate_range()
self.set_cumulative_time()
if not self.is_new():
self.old_item_group = frappe.db.get_value(self.doctype, self.name, "item_group")
def set_cumulative_time(self):
self.cumulative_time = (
cint(self.procurement_time) + cint(self.manufacturing_time) + cint(self.planning_buffer)
)
def on_update(self):
self.update_variants()
self.update_item_price()