mirror of
https://github.com/frappe/erpnext.git
synced 2026-08-29 22:58:25 +00:00
feat(rfq): add accounting dimensions support to Request for Quotation
- Add `cost_center` field and `accounting_dimensions_section` / `dimension_col_break` to Request for Quotation Item DocType so custom accounting dimensions propagate automatically - Register `Request for Quotation Item` in `accounting_dimension_doctypes` hook - Map `cost_center` from Material Request → RFQ in `make_request_for_quotation` - Map `cost_center` from RFQ → Supplier Quotation in `make_supplier_quotation_from_rfq` and `create_rfq_items` (portal flow) - Map `cost_center` in `get_item_from_material_requests_based_on_supplier` (MR-based RFQ flow) - Add test cases to verify cost_center propagation through the MR → RFQ → SQ chain Fixes #55855 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -43,6 +43,7 @@ def make_supplier_quotation_from_rfq(
|
|||||||
"name": "request_for_quotation_item",
|
"name": "request_for_quotation_item",
|
||||||
"parent": "request_for_quotation",
|
"parent": "request_for_quotation",
|
||||||
"project_name": "project",
|
"project_name": "project",
|
||||||
|
"cost_center": "cost_center",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -110,6 +111,7 @@ def create_rfq_items(sq_doc, supplier, data):
|
|||||||
"material_request_item",
|
"material_request_item",
|
||||||
"stock_qty",
|
"stock_qty",
|
||||||
"uom",
|
"uom",
|
||||||
|
"cost_center",
|
||||||
]:
|
]:
|
||||||
args[field] = data.get(field)
|
args[field] = data.get(field)
|
||||||
|
|
||||||
@@ -176,6 +178,7 @@ def get_item_from_material_requests_based_on_supplier(
|
|||||||
["name", "material_request_item"],
|
["name", "material_request_item"],
|
||||||
["parent", "material_request"],
|
["parent", "material_request"],
|
||||||
["uom", "uom"],
|
["uom", "uom"],
|
||||||
|
["cost_center", "cost_center"],
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ from erpnext.controllers.accounts_controller import InvalidQtyError
|
|||||||
from erpnext.crm.doctype.opportunity.mapper import make_request_for_quotation as make_rfq
|
from erpnext.crm.doctype.opportunity.mapper import make_request_for_quotation as make_rfq
|
||||||
from erpnext.crm.doctype.opportunity.test_opportunity import make_opportunity
|
from erpnext.crm.doctype.opportunity.test_opportunity import make_opportunity
|
||||||
from erpnext.stock.doctype.item.test_item import make_item
|
from erpnext.stock.doctype.item.test_item import make_item
|
||||||
|
from erpnext.stock.doctype.material_request.test_material_request import make_material_request
|
||||||
from erpnext.templates.pages.rfq import check_supplier_has_docname_access
|
from erpnext.templates.pages.rfq import check_supplier_has_docname_access
|
||||||
from erpnext.tests.utils import ERPNextTestSuite
|
from erpnext.tests.utils import ERPNextTestSuite
|
||||||
|
|
||||||
@@ -250,6 +251,40 @@ class TestRequestforQuotation(ERPNextTestSuite):
|
|||||||
self.assertEqual(sq.items[0].qty, 0)
|
self.assertEqual(sq.items[0].qty, 0)
|
||||||
self.assertEqual(sq.items[0].item_code, rfq.items[0].item_code)
|
self.assertEqual(sq.items[0].item_code, rfq.items[0].item_code)
|
||||||
|
|
||||||
|
def test_cost_center_flows_from_mr_to_rfq(self):
|
||||||
|
from erpnext.stock.doctype.material_request.mapper import (
|
||||||
|
make_request_for_quotation as mr_make_rfq,
|
||||||
|
)
|
||||||
|
|
||||||
|
mr = make_material_request(cost_center="_Test Cost Center - _TC")
|
||||||
|
rfq = mr_make_rfq(mr.name)
|
||||||
|
|
||||||
|
self.assertEqual(rfq.items[0].cost_center, "_Test Cost Center - _TC")
|
||||||
|
|
||||||
|
def test_cost_center_flows_from_rfq_to_supplier_quotation(self):
|
||||||
|
rfq = make_request_for_quotation()
|
||||||
|
rfq.items[0].cost_center = "_Test Cost Center - _TC"
|
||||||
|
rfq.save()
|
||||||
|
|
||||||
|
sq = make_supplier_quotation_from_rfq(rfq.name, for_supplier=rfq.get("suppliers")[0].supplier)
|
||||||
|
|
||||||
|
self.assertEqual(sq.items[0].cost_center, "_Test Cost Center - _TC")
|
||||||
|
|
||||||
|
def test_cost_center_flows_end_to_end_mr_rfq_sq(self):
|
||||||
|
from erpnext.stock.doctype.material_request.mapper import (
|
||||||
|
make_request_for_quotation as mr_make_rfq,
|
||||||
|
)
|
||||||
|
|
||||||
|
mr = make_material_request(cost_center="_Test Cost Center - _TC")
|
||||||
|
rfq = mr_make_rfq(mr.name)
|
||||||
|
rfq.append("suppliers", {"supplier": "_Test Supplier", "supplier_name": "_Test Supplier"})
|
||||||
|
rfq.insert()
|
||||||
|
rfq.submit()
|
||||||
|
|
||||||
|
sq = make_supplier_quotation_from_rfq(rfq.name, for_supplier="_Test Supplier")
|
||||||
|
|
||||||
|
self.assertEqual(sq.items[0].cost_center, "_Test Cost Center - _TC")
|
||||||
|
|
||||||
|
|
||||||
def make_request_for_quotation(**args):
|
def make_request_for_quotation(**args):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -30,7 +30,9 @@
|
|||||||
"col_break4",
|
"col_break4",
|
||||||
"material_request",
|
"material_request",
|
||||||
"material_request_item",
|
"material_request_item",
|
||||||
"section_break_24",
|
"accounting_dimensions_section",
|
||||||
|
"cost_center",
|
||||||
|
"dimension_col_break",
|
||||||
"project_name",
|
"project_name",
|
||||||
"section_break_23",
|
"section_break_23",
|
||||||
"page_break"
|
"page_break"
|
||||||
@@ -253,15 +255,26 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"collapsible": 1,
|
"collapsible": 1,
|
||||||
"fieldname": "section_break_24",
|
"fieldname": "accounting_dimensions_section",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"label": "Accounting Dimensions"
|
"label": "Accounting Dimensions"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "cost_center",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Cost Center",
|
||||||
|
"options": "Cost Center",
|
||||||
|
"print_hide": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "dimension_col_break",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2026-01-31 19:46:27.884592",
|
"modified": "2026-06-15 00:00:00.000000",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Buying",
|
"module": "Buying",
|
||||||
"name": "Request for Quotation Item",
|
"name": "Request for Quotation Item",
|
||||||
|
|||||||
@@ -596,6 +596,7 @@ accounting_dimension_doctypes = [
|
|||||||
"Account Closing Balance",
|
"Account Closing Balance",
|
||||||
"Supplier Quotation",
|
"Supplier Quotation",
|
||||||
"Supplier Quotation Item",
|
"Supplier Quotation Item",
|
||||||
|
"Request for Quotation Item",
|
||||||
"Payment Reconciliation",
|
"Payment Reconciliation",
|
||||||
"Payment Reconciliation Allocation",
|
"Payment Reconciliation Allocation",
|
||||||
"Payment Request",
|
"Payment Request",
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ def make_request_for_quotation(source_name: str, target_doc: str | Document | No
|
|||||||
["name", "material_request_item"],
|
["name", "material_request_item"],
|
||||||
["parent", "material_request"],
|
["parent", "material_request"],
|
||||||
["project", "project_name"],
|
["project", "project_name"],
|
||||||
|
["cost_center", "cost_center"],
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user