mirror of
https://github.com/frappe/erpnext.git
synced 2026-02-16 16:15:02 +00:00
Merge pull request #50318 from rohitwaghchaure/fixed-mrp-issues
fix: multiple MRP issues
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user