mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-23 15:09:20 +00:00
feat: company wise default warehouses
This commit is contained in:
@@ -1085,7 +1085,7 @@ class JobCard(Document):
|
|||||||
|
|
||||||
def set_wip_warehouse(self):
|
def set_wip_warehouse(self):
|
||||||
if not self.wip_warehouse:
|
if not self.wip_warehouse:
|
||||||
self.wip_warehouse = frappe.db.get_single_value("Manufacturing Settings", "default_wip_warehouse")
|
self.wip_warehouse = frappe.get_cached_value("Company", self.company, "default_wip_warehouse")
|
||||||
|
|
||||||
def validate_operation_id(self):
|
def validate_operation_id(self):
|
||||||
if (
|
if (
|
||||||
|
|||||||
@@ -18,18 +18,6 @@ frappe.tour["Manufacturing Settings"] = [
|
|||||||
"The Stock Entry of type 'Manufacture' is known as backflush. Raw materials being consumed to manufacture finished goods is known as backflushing. <br><br> When creating Manufacture Entry, raw-material items are backflushed based on BOM of production item. If you want raw-material items to be backflushed based on Material Transfer entry made against that Work Order instead, then you can set it under this field."
|
"The Stock Entry of type 'Manufacture' is known as backflush. Raw materials being consumed to manufacture finished goods is known as backflushing. <br><br> When creating Manufacture Entry, raw-material items are backflushed based on BOM of production item. If you want raw-material items to be backflushed based on Material Transfer entry made against that Work Order instead, then you can set it under this field."
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
|
||||||
fieldname: "default_wip_warehouse",
|
|
||||||
title: __("Work In Progress Warehouse"),
|
|
||||||
description: __(
|
|
||||||
"This Warehouse will be auto-updated in the Work In Progress Warehouse field of Work Orders."
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldname: "default_fg_warehouse",
|
|
||||||
title: __("Finished Goods Warehouse"),
|
|
||||||
description: __("This Warehouse will be auto-updated in the Target Warehouse field of Work Order."),
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
fieldname: "update_bom_costs_automatically",
|
fieldname: "update_bom_costs_automatically",
|
||||||
title: __("Update BOM Cost Automatically"),
|
title: __("Update BOM Cost Automatically"),
|
||||||
|
|||||||
@@ -16,11 +16,6 @@
|
|||||||
"update_bom_costs_automatically",
|
"update_bom_costs_automatically",
|
||||||
"column_break_lhyt",
|
"column_break_lhyt",
|
||||||
"allow_editing_of_items_and_quantities_in_work_order",
|
"allow_editing_of_items_and_quantities_in_work_order",
|
||||||
"section_break_6",
|
|
||||||
"default_wip_warehouse",
|
|
||||||
"default_fg_warehouse",
|
|
||||||
"column_break_11",
|
|
||||||
"default_scrap_warehouse",
|
|
||||||
"over_production_for_sales_and_work_order_section",
|
"over_production_for_sales_and_work_order_section",
|
||||||
"overproduction_percentage_for_sales_order",
|
"overproduction_percentage_for_sales_order",
|
||||||
"column_break_16",
|
"column_break_16",
|
||||||
@@ -86,11 +81,6 @@
|
|||||||
"fieldtype": "Int",
|
"fieldtype": "Int",
|
||||||
"label": "Time Between Operations (Mins)"
|
"label": "Time Between Operations (Mins)"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"fieldname": "section_break_6",
|
|
||||||
"fieldtype": "Section Break",
|
|
||||||
"label": "Default Warehouses for Production"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fieldname": "overproduction_percentage_for_sales_order",
|
"fieldname": "overproduction_percentage_for_sales_order",
|
||||||
"fieldtype": "Percent",
|
"fieldtype": "Percent",
|
||||||
@@ -122,34 +112,12 @@
|
|||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Update BOM Cost Automatically"
|
"label": "Update BOM Cost Automatically"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"fieldname": "column_break_11",
|
|
||||||
"fieldtype": "Column Break"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "default_wip_warehouse",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"label": "Default Work In Progress Warehouse",
|
|
||||||
"options": "Warehouse"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "default_fg_warehouse",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"label": "Default Finished Goods Warehouse",
|
|
||||||
"options": "Warehouse"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"default": "0",
|
"default": "0",
|
||||||
"fieldname": "disable_capacity_planning",
|
"fieldname": "disable_capacity_planning",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Disable Capacity Planning"
|
"label": "Disable Capacity Planning"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"fieldname": "default_scrap_warehouse",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"label": "Default Scrap Warehouse",
|
|
||||||
"options": "Warehouse"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fieldname": "over_production_for_sales_and_work_order_section",
|
"fieldname": "over_production_for_sales_and_work_order_section",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
@@ -275,7 +243,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2025-11-07 14:52:56.241459",
|
"modified": "2025-11-13 12:30:29.006822",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "Manufacturing Settings",
|
"name": "Manufacturing Settings",
|
||||||
|
|||||||
@@ -23,9 +23,6 @@ class ManufacturingSettings(Document):
|
|||||||
allow_production_on_holidays: DF.Check
|
allow_production_on_holidays: DF.Check
|
||||||
backflush_raw_materials_based_on: DF.Literal["BOM", "Material Transferred for Manufacture"]
|
backflush_raw_materials_based_on: DF.Literal["BOM", "Material Transferred for Manufacture"]
|
||||||
capacity_planning_for_days: DF.Int
|
capacity_planning_for_days: DF.Int
|
||||||
default_fg_warehouse: DF.Link | None
|
|
||||||
default_scrap_warehouse: DF.Link | None
|
|
||||||
default_wip_warehouse: DF.Link | None
|
|
||||||
disable_capacity_planning: DF.Check
|
disable_capacity_planning: DF.Check
|
||||||
enforce_time_logs: DF.Check
|
enforce_time_logs: DF.Check
|
||||||
get_rm_cost_from_consumption_entry: DF.Check
|
get_rm_cost_from_consumption_entry: DF.Check
|
||||||
|
|||||||
@@ -756,7 +756,7 @@ class ProductionPlan(Document):
|
|||||||
|
|
||||||
wo_list, po_list = [], []
|
wo_list, po_list = [], []
|
||||||
subcontracted_po = {}
|
subcontracted_po = {}
|
||||||
default_warehouses = get_default_warehouse()
|
default_warehouses = get_default_warehouse(self.company)
|
||||||
|
|
||||||
self.make_work_order_for_finished_goods(wo_list, default_warehouses)
|
self.make_work_order_for_finished_goods(wo_list, default_warehouses)
|
||||||
self.make_work_order_for_subassembly_items(wo_list, subcontracted_po, default_warehouses)
|
self.make_work_order_for_subassembly_items(wo_list, subcontracted_po, default_warehouses)
|
||||||
|
|||||||
@@ -932,6 +932,9 @@ erpnext.work_order = {
|
|||||||
if (!(frm.doc.wip_warehouse || frm.doc.fg_warehouse)) {
|
if (!(frm.doc.wip_warehouse || frm.doc.fg_warehouse)) {
|
||||||
frappe.call({
|
frappe.call({
|
||||||
method: "erpnext.manufacturing.doctype.work_order.work_order.get_default_warehouse",
|
method: "erpnext.manufacturing.doctype.work_order.work_order.get_default_warehouse",
|
||||||
|
args: {
|
||||||
|
company: frm.doc.company,
|
||||||
|
},
|
||||||
callback: function (r) {
|
callback: function (r) {
|
||||||
if (!r.exe) {
|
if (!r.exe) {
|
||||||
frm.set_value("wip_warehouse", r.message.wip_warehouse);
|
frm.set_value("wip_warehouse", r.message.wip_warehouse);
|
||||||
|
|||||||
@@ -453,9 +453,9 @@ class WorkOrder(Document):
|
|||||||
|
|
||||||
def set_default_warehouse(self):
|
def set_default_warehouse(self):
|
||||||
if not self.wip_warehouse and not self.skip_transfer:
|
if not self.wip_warehouse and not self.skip_transfer:
|
||||||
self.wip_warehouse = frappe.db.get_single_value("Manufacturing Settings", "default_wip_warehouse")
|
self.wip_warehouse = frappe.get_cached_value("Company", self.company, "default_wip_warehouse")
|
||||||
if not self.fg_warehouse:
|
if not self.fg_warehouse:
|
||||||
self.fg_warehouse = frappe.db.get_single_value("Manufacturing Settings", "default_fg_warehouse")
|
self.fg_warehouse = frappe.get_cached_value("Company", self.company, "default_fg_warehouse")
|
||||||
|
|
||||||
def check_wip_warehouse_skip(self):
|
def check_wip_warehouse_skip(self):
|
||||||
if self.skip_transfer and not self.from_wip_warehouse:
|
if self.skip_transfer and not self.from_wip_warehouse:
|
||||||
@@ -2318,13 +2318,14 @@ def make_stock_entry(
|
|||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_default_warehouse():
|
def get_default_warehouse(company):
|
||||||
doc = frappe.get_cached_doc("Manufacturing Settings")
|
wip, fg, scrap = frappe.get_cached_value(
|
||||||
|
"Company", company, ["default_wip_warehouse", "default_fg_warehouse", "default_scrap_warehouse"]
|
||||||
|
)
|
||||||
return {
|
return {
|
||||||
"wip_warehouse": doc.default_wip_warehouse,
|
"wip_warehouse": wip,
|
||||||
"fg_warehouse": doc.default_fg_warehouse,
|
"fg_warehouse": fg,
|
||||||
"scrap_warehouse": doc.default_scrap_warehouse,
|
"scrap_warehouse": scrap,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -446,3 +446,4 @@ erpnext.patches.v16_0.add_new_stock_entry_types
|
|||||||
erpnext.patches.v15_0.set_asset_status_if_not_already_set
|
erpnext.patches.v15_0.set_asset_status_if_not_already_set
|
||||||
erpnext.patches.v15_0.toggle_legacy_controller_for_period_closing
|
erpnext.patches.v15_0.toggle_legacy_controller_for_period_closing
|
||||||
erpnext.patches.v16_0.update_serial_batch_entries
|
erpnext.patches.v16_0.update_serial_batch_entries
|
||||||
|
erpnext.patches.v16_0.set_company_wise_warehouses
|
||||||
14
erpnext/patches/v16_0/set_company_wise_warehouses.py
Normal file
14
erpnext/patches/v16_0/set_company_wise_warehouses.py
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import frappe
|
||||||
|
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
warehouses = frappe.get_single_value(
|
||||||
|
"Manufacturing Settings",
|
||||||
|
["default_wip_warehouse", "default_fg_warehouse", "default_scrap_warehouse"],
|
||||||
|
as_dict=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
for name, warehouse in warehouses.items():
|
||||||
|
if warehouse:
|
||||||
|
company = frappe.get_value("Warehouse", warehouse, "company")
|
||||||
|
frappe.db.set_value("Company", company, name, warehouse)
|
||||||
@@ -1796,7 +1796,7 @@ class TestSalesOrder(AccountsTestMixin, IntegrationTestCase):
|
|||||||
mr.submit()
|
mr.submit()
|
||||||
|
|
||||||
# WO from MR
|
# WO from MR
|
||||||
wo_name = raise_work_orders(mr.name)[0]
|
wo_name = raise_work_orders(mr.name, mr.company)[0]
|
||||||
wo = frappe.get_doc("Work Order", wo_name)
|
wo = frappe.get_doc("Work Order", wo_name)
|
||||||
wo.wip_warehouse = "Work In Progress - _TC"
|
wo.wip_warehouse = "Work In Progress - _TC"
|
||||||
wo.skip_transfer = True
|
wo.skip_transfer = True
|
||||||
|
|||||||
@@ -124,6 +124,10 @@
|
|||||||
"default_in_transit_warehouse",
|
"default_in_transit_warehouse",
|
||||||
"manufacturing_section",
|
"manufacturing_section",
|
||||||
"default_operating_cost_account",
|
"default_operating_cost_account",
|
||||||
|
"column_break_9prc",
|
||||||
|
"default_wip_warehouse",
|
||||||
|
"default_fg_warehouse",
|
||||||
|
"default_scrap_warehouse",
|
||||||
"dashboard_tab"
|
"dashboard_tab"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
@@ -885,6 +889,31 @@
|
|||||||
"fieldname": "enable_item_wise_inventory_account",
|
"fieldname": "enable_item_wise_inventory_account",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Enable Item-wise Inventory Account"
|
"label": "Enable Item-wise Inventory Account"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "default_wip_warehouse",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": " Default Work In Progress Warehouse ",
|
||||||
|
"link_filters": "[[\"Warehouse\",\"disabled\",\"=\",0]]",
|
||||||
|
"options": "Warehouse"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "default_fg_warehouse",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Default Finished Goods Warehouse",
|
||||||
|
"link_filters": "[[\"Warehouse\",\"disabled\",\"=\",0]]",
|
||||||
|
"options": "Warehouse"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "default_scrap_warehouse",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Default Scrap Warehouse",
|
||||||
|
"link_filters": "[[\"Warehouse\",\"disabled\",\"=\",0]]",
|
||||||
|
"options": "Warehouse"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_9prc",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "fa fa-building",
|
"icon": "fa fa-building",
|
||||||
@@ -892,7 +921,7 @@
|
|||||||
"image_field": "company_logo",
|
"image_field": "company_logo",
|
||||||
"is_tree": 1,
|
"is_tree": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2025-10-23 13:15:52.411984",
|
"modified": "2025-11-16 16:50:27.624096",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Setup",
|
"module": "Setup",
|
||||||
"name": "Company",
|
"name": "Company",
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ class Company(NestedSet):
|
|||||||
default_deferred_revenue_account: DF.Link | None
|
default_deferred_revenue_account: DF.Link | None
|
||||||
default_discount_account: DF.Link | None
|
default_discount_account: DF.Link | None
|
||||||
default_expense_account: DF.Link | None
|
default_expense_account: DF.Link | None
|
||||||
|
default_fg_warehouse: DF.Link | None
|
||||||
default_finance_book: DF.Link | None
|
default_finance_book: DF.Link | None
|
||||||
default_holiday_list: DF.Link | None
|
default_holiday_list: DF.Link | None
|
||||||
default_in_transit_warehouse: DF.Link | None
|
default_in_transit_warehouse: DF.Link | None
|
||||||
@@ -69,8 +70,10 @@ class Company(NestedSet):
|
|||||||
default_payable_account: DF.Link | None
|
default_payable_account: DF.Link | None
|
||||||
default_provisional_account: DF.Link | None
|
default_provisional_account: DF.Link | None
|
||||||
default_receivable_account: DF.Link | None
|
default_receivable_account: DF.Link | None
|
||||||
|
default_scrap_warehouse: DF.Link | None
|
||||||
default_selling_terms: DF.Link | None
|
default_selling_terms: DF.Link | None
|
||||||
default_warehouse_for_sales_return: DF.Link | None
|
default_warehouse_for_sales_return: DF.Link | None
|
||||||
|
default_wip_warehouse: DF.Link | None
|
||||||
depreciation_cost_center: DF.Link | None
|
depreciation_cost_center: DF.Link | None
|
||||||
depreciation_expense_account: DF.Link | None
|
depreciation_expense_account: DF.Link | None
|
||||||
disposal_account: DF.Link | None
|
disposal_account: DF.Link | None
|
||||||
|
|||||||
@@ -495,6 +495,7 @@ frappe.ui.form.on("Material Request", {
|
|||||||
method: "erpnext.stock.doctype.material_request.material_request.raise_work_orders",
|
method: "erpnext.stock.doctype.material_request.material_request.raise_work_orders",
|
||||||
args: {
|
args: {
|
||||||
material_request: frm.doc.name,
|
material_request: frm.doc.name,
|
||||||
|
company: frm.doc.company,
|
||||||
},
|
},
|
||||||
freeze: true,
|
freeze: true,
|
||||||
callback: function (r) {
|
callback: function (r) {
|
||||||
|
|||||||
@@ -833,11 +833,11 @@ def make_stock_entry(source_name, target_doc=None):
|
|||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def raise_work_orders(material_request):
|
def raise_work_orders(material_request, company):
|
||||||
mr = frappe.get_doc("Material Request", material_request)
|
mr = frappe.get_doc("Material Request", material_request)
|
||||||
errors = []
|
errors = []
|
||||||
work_orders = []
|
work_orders = []
|
||||||
default_wip_warehouse = frappe.db.get_single_value("Manufacturing Settings", "default_wip_warehouse")
|
default_wip_warehouse = frappe.get_cached_value("Company", company, "default_wip_warehouse")
|
||||||
|
|
||||||
for d in mr.items:
|
for d in mr.items:
|
||||||
if (d.stock_qty - d.ordered_qty) > 0:
|
if (d.stock_qty - d.ordered_qty) > 0:
|
||||||
|
|||||||
@@ -747,7 +747,7 @@ class TestMaterialRequest(IntegrationTestCase):
|
|||||||
(mr.items[0].item_code, mr.items[0].warehouse),
|
(mr.items[0].item_code, mr.items[0].warehouse),
|
||||||
)[0][0]
|
)[0][0]
|
||||||
|
|
||||||
prod_order = raise_work_orders(mr.name)
|
prod_order = raise_work_orders(mr.name, mr.company)
|
||||||
po = frappe.get_doc("Work Order", prod_order[0])
|
po = frappe.get_doc("Work Order", prod_order[0])
|
||||||
po.wip_warehouse = "_Test Warehouse 1 - _TC"
|
po.wip_warehouse = "_Test Warehouse 1 - _TC"
|
||||||
po.submit()
|
po.submit()
|
||||||
@@ -789,7 +789,7 @@ class TestMaterialRequest(IntegrationTestCase):
|
|||||||
|
|
||||||
self.assertEqual(requested_qty, existing_requested_qty + 120)
|
self.assertEqual(requested_qty, existing_requested_qty + 120)
|
||||||
|
|
||||||
work_order = raise_work_orders(mr.name)
|
work_order = raise_work_orders(mr.name, mr.company)
|
||||||
wo = frappe.get_doc("Work Order", work_order[0])
|
wo = frappe.get_doc("Work Order", work_order[0])
|
||||||
wo.qty = 50
|
wo.qty = 50
|
||||||
wo.wip_warehouse = "_Test Warehouse 1 - _TC"
|
wo.wip_warehouse = "_Test Warehouse 1 - _TC"
|
||||||
@@ -924,7 +924,7 @@ class TestMaterialRequest(IntegrationTestCase):
|
|||||||
item_code="_Test FG Item", material_request_type="Manufacture", do_not_submit=False
|
item_code="_Test FG Item", material_request_type="Manufacture", do_not_submit=False
|
||||||
)
|
)
|
||||||
|
|
||||||
work_order = raise_work_orders(mr.name)
|
work_order = raise_work_orders(mr.name, mr.company)
|
||||||
wo = frappe.get_doc("Work Order", work_order[0])
|
wo = frappe.get_doc("Work Order", work_order[0])
|
||||||
wo.wip_warehouse = "_Test Warehouse 1 - _TC"
|
wo.wip_warehouse = "_Test Warehouse 1 - _TC"
|
||||||
wo.submit()
|
wo.submit()
|
||||||
|
|||||||
Reference in New Issue
Block a user