mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-15 19:19:17 +00:00
feat: Multi UOM support in Request for Quotation
This commit is contained in:
@@ -25,6 +25,7 @@ class RequestforQuotation(BuyingController):
|
|||||||
self.validate_duplicate_supplier()
|
self.validate_duplicate_supplier()
|
||||||
self.validate_supplier_list()
|
self.validate_supplier_list()
|
||||||
validate_for_items(self)
|
validate_for_items(self)
|
||||||
|
super(RequestforQuotation, self).set_qty_as_per_stock_uom()
|
||||||
self.update_email_id()
|
self.update_email_id()
|
||||||
|
|
||||||
def validate_duplicate_supplier(self):
|
def validate_duplicate_supplier(self):
|
||||||
@@ -278,6 +279,7 @@ def create_rfq_items(sq_doc, supplier, data):
|
|||||||
"description": data.description,
|
"description": data.description,
|
||||||
"qty": data.qty,
|
"qty": data.qty,
|
||||||
"rate": data.rate,
|
"rate": data.rate,
|
||||||
|
"conversion_factor": data.conversion_factor if data.conversion_factor else None,
|
||||||
"supplier_part_no": frappe.db.get_value("Item Supplier", {'parent': data.item_code, 'supplier': supplier}, "supplier_part_no"),
|
"supplier_part_no": frappe.db.get_value("Item Supplier", {'parent': data.item_code, 'supplier': supplier}, "supplier_part_no"),
|
||||||
"warehouse": data.warehouse or '',
|
"warehouse": data.warehouse or '',
|
||||||
"request_for_quotation_item": data.name,
|
"request_for_quotation_item": data.name,
|
||||||
|
|||||||
@@ -6,12 +6,14 @@ from __future__ import unicode_literals
|
|||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from erpnext.templates.pages.rfq import check_supplier_has_docname_access
|
|
||||||
from frappe.utils import nowdate
|
from frappe.utils import nowdate
|
||||||
|
from erpnext.stock.doctype.item.test_item import make_item
|
||||||
|
from erpnext.templates.pages.rfq import check_supplier_has_docname_access
|
||||||
|
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import make_supplier_quotation
|
||||||
|
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import create_supplier_quotation
|
||||||
|
|
||||||
class TestRequestforQuotation(unittest.TestCase):
|
class TestRequestforQuotation(unittest.TestCase):
|
||||||
def test_quote_status(self):
|
def test_quote_status(self):
|
||||||
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import make_supplier_quotation
|
|
||||||
rfq = make_request_for_quotation()
|
rfq = make_request_for_quotation()
|
||||||
|
|
||||||
self.assertEqual(rfq.get('suppliers')[0].quote_status, 'Pending')
|
self.assertEqual(rfq.get('suppliers')[0].quote_status, 'Pending')
|
||||||
@@ -31,7 +33,6 @@ class TestRequestforQuotation(unittest.TestCase):
|
|||||||
self.assertEqual(rfq.get('suppliers')[1].quote_status, 'No Quote')
|
self.assertEqual(rfq.get('suppliers')[1].quote_status, 'No Quote')
|
||||||
|
|
||||||
def test_make_supplier_quotation(self):
|
def test_make_supplier_quotation(self):
|
||||||
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import make_supplier_quotation
|
|
||||||
rfq = make_request_for_quotation()
|
rfq = make_request_for_quotation()
|
||||||
|
|
||||||
sq = make_supplier_quotation(rfq.name, rfq.get('suppliers')[0].supplier)
|
sq = make_supplier_quotation(rfq.name, rfq.get('suppliers')[0].supplier)
|
||||||
@@ -51,15 +52,13 @@ class TestRequestforQuotation(unittest.TestCase):
|
|||||||
self.assertEqual(sq1.get('items')[0].qty, 5)
|
self.assertEqual(sq1.get('items')[0].qty, 5)
|
||||||
|
|
||||||
def test_make_supplier_quotation_with_special_characters(self):
|
def test_make_supplier_quotation_with_special_characters(self):
|
||||||
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import make_supplier_quotation
|
|
||||||
|
|
||||||
frappe.delete_doc_if_exists("Supplier", "_Test Supplier '1", force=1)
|
frappe.delete_doc_if_exists("Supplier", "_Test Supplier '1", force=1)
|
||||||
supplier = frappe.new_doc("Supplier")
|
supplier = frappe.new_doc("Supplier")
|
||||||
supplier.supplier_name = "_Test Supplier '1"
|
supplier.supplier_name = "_Test Supplier '1"
|
||||||
supplier.supplier_group = "_Test Supplier Group"
|
supplier.supplier_group = "_Test Supplier Group"
|
||||||
supplier.insert()
|
supplier.insert()
|
||||||
|
|
||||||
rfq = make_request_for_quotation(supplier_wt_appos)
|
rfq = make_request_for_quotation(supplier_data=supplier_wt_appos)
|
||||||
|
|
||||||
sq = make_supplier_quotation(rfq.name, supplier_wt_appos[0].get("supplier"))
|
sq = make_supplier_quotation(rfq.name, supplier_wt_appos[0].get("supplier"))
|
||||||
sq.submit()
|
sq.submit()
|
||||||
@@ -76,7 +75,6 @@ class TestRequestforQuotation(unittest.TestCase):
|
|||||||
frappe.form_dict.name = None
|
frappe.form_dict.name = None
|
||||||
|
|
||||||
def test_make_supplier_quotation_from_portal(self):
|
def test_make_supplier_quotation_from_portal(self):
|
||||||
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import create_supplier_quotation
|
|
||||||
rfq = make_request_for_quotation()
|
rfq = make_request_for_quotation()
|
||||||
rfq.get('items')[0].rate = 100
|
rfq.get('items')[0].rate = 100
|
||||||
rfq.supplier = rfq.suppliers[0].supplier
|
rfq.supplier = rfq.suppliers[0].supplier
|
||||||
@@ -90,12 +88,34 @@ class TestRequestforQuotation(unittest.TestCase):
|
|||||||
self.assertEqual(supplier_quotation_doc.get('items')[0].qty, 5)
|
self.assertEqual(supplier_quotation_doc.get('items')[0].qty, 5)
|
||||||
self.assertEqual(supplier_quotation_doc.get('items')[0].amount, 500)
|
self.assertEqual(supplier_quotation_doc.get('items')[0].amount, 500)
|
||||||
|
|
||||||
|
def test_make_multi_uom_supplier_quotation(self):
|
||||||
|
item_code = "_Test Multi UOM RFQ Item"
|
||||||
|
if not frappe.db.exists('Item', item_code):
|
||||||
|
item = make_item(item_code, {'stock_uom': '_Test UOM'})
|
||||||
|
row = item.append('uoms', {
|
||||||
|
'uom': 'Kg',
|
||||||
|
'conversion_factor': 2
|
||||||
|
})
|
||||||
|
row.db_update()
|
||||||
|
|
||||||
def make_request_for_quotation(supplier_data=None):
|
rfq = make_request_for_quotation(item_code="_Test Multi UOM RFQ Item", uom="Kg", conversion_factor=2)
|
||||||
|
rfq.get('items')[0].rate = 100
|
||||||
|
rfq.supplier = rfq.suppliers[0].supplier
|
||||||
|
|
||||||
|
self.assertEqual(rfq.items[0].stock_qty, 10)
|
||||||
|
|
||||||
|
supplier_quotation_name = create_supplier_quotation(rfq)
|
||||||
|
supplier_quotation = frappe.get_doc('Supplier Quotation', supplier_quotation_name)
|
||||||
|
|
||||||
|
self.assertEqual(supplier_quotation.items[0].qty, 5)
|
||||||
|
self.assertEqual(supplier_quotation.items[0].stock_qty, 10)
|
||||||
|
|
||||||
|
def make_request_for_quotation(**args):
|
||||||
"""
|
"""
|
||||||
:param supplier_data: List containing supplier data
|
:param supplier_data: List containing supplier data
|
||||||
"""
|
"""
|
||||||
supplier_data = supplier_data if supplier_data else get_supplier_data()
|
args = frappe._dict(args)
|
||||||
|
supplier_data = args.get("supplier_data") if args.get("supplier_data") else get_supplier_data()
|
||||||
rfq = frappe.new_doc('Request for Quotation')
|
rfq = frappe.new_doc('Request for Quotation')
|
||||||
rfq.transaction_date = nowdate()
|
rfq.transaction_date = nowdate()
|
||||||
rfq.status = 'Draft'
|
rfq.status = 'Draft'
|
||||||
@@ -106,11 +126,13 @@ def make_request_for_quotation(supplier_data=None):
|
|||||||
rfq.append('suppliers', data)
|
rfq.append('suppliers', data)
|
||||||
|
|
||||||
rfq.append("items", {
|
rfq.append("items", {
|
||||||
"item_code": "_Test Item",
|
"item_code": args.item_code or "_Test Item",
|
||||||
"description": "_Test Item",
|
"description": "_Test Item",
|
||||||
"uom": "_Test UOM",
|
"uom": args.uom or "_Test UOM",
|
||||||
"qty": 5,
|
"stock_uom": args.stock_uom or "_Test UOM",
|
||||||
"warehouse": "_Test Warehouse - _TC",
|
"qty": args.qty or 5,
|
||||||
|
"conversion_factor": args.conversion_factor or 1.0,
|
||||||
|
"warehouse": args.warehouse or "_Test Warehouse - _TC",
|
||||||
"schedule_date": nowdate()
|
"schedule_date": nowdate()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"actions": [],
|
||||||
"autoname": "hash",
|
"autoname": "hash",
|
||||||
"creation": "2016-02-25 08:04:02.452958",
|
"creation": "2016-02-25 08:04:02.452958",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
@@ -9,6 +10,7 @@
|
|||||||
"supplier_part_no",
|
"supplier_part_no",
|
||||||
"column_break_3",
|
"column_break_3",
|
||||||
"item_name",
|
"item_name",
|
||||||
|
"schedule_date",
|
||||||
"section_break_5",
|
"section_break_5",
|
||||||
"description",
|
"description",
|
||||||
"item_group",
|
"item_group",
|
||||||
@@ -18,9 +20,11 @@
|
|||||||
"image_view",
|
"image_view",
|
||||||
"quantity",
|
"quantity",
|
||||||
"qty",
|
"qty",
|
||||||
|
"stock_uom",
|
||||||
"col_break2",
|
"col_break2",
|
||||||
"schedule_date",
|
|
||||||
"uom",
|
"uom",
|
||||||
|
"conversion_factor",
|
||||||
|
"stock_qty",
|
||||||
"warehouse_and_reference",
|
"warehouse_and_reference",
|
||||||
"warehouse",
|
"warehouse",
|
||||||
"project_name",
|
"project_name",
|
||||||
@@ -33,7 +37,7 @@
|
|||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"bold": 1,
|
"bold": 1,
|
||||||
"columns": 3,
|
"columns": 2,
|
||||||
"fieldname": "item_code",
|
"fieldname": "item_code",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
@@ -98,7 +102,7 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "quantity",
|
"fieldname": "quantity",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"label": "Quantity"
|
"label": "Quantity & Stock"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"bold": 1,
|
"bold": 1,
|
||||||
@@ -129,12 +133,12 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "uom",
|
"fieldname": "uom",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
|
"in_list_view": 1,
|
||||||
"label": "UOM",
|
"label": "UOM",
|
||||||
"oldfieldname": "uom",
|
"oldfieldname": "uom",
|
||||||
"oldfieldtype": "Link",
|
"oldfieldtype": "Link",
|
||||||
"options": "UOM",
|
"options": "UOM",
|
||||||
"print_width": "100px",
|
"print_width": "100px",
|
||||||
"read_only": 1,
|
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"width": "100px"
|
"width": "100px"
|
||||||
},
|
},
|
||||||
@@ -144,7 +148,7 @@
|
|||||||
"label": "Warehouse and Reference"
|
"label": "Warehouse and Reference"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"columns": 3,
|
"columns": 2,
|
||||||
"fieldname": "warehouse",
|
"fieldname": "warehouse",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
@@ -202,6 +206,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 1,
|
"allow_on_submit": 1,
|
||||||
|
"default": "0",
|
||||||
"fieldname": "page_break",
|
"fieldname": "page_break",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Page Break",
|
"label": "Page Break",
|
||||||
@@ -219,10 +224,36 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "section_break_23",
|
"fieldname": "section_break_23",
|
||||||
"fieldtype": "Section Break"
|
"fieldtype": "Section Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "stock_uom",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Stock UOM",
|
||||||
|
"options": "UOM",
|
||||||
|
"print_hide": 1,
|
||||||
|
"read_only": 1,
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "conversion_factor",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"label": "UOM Conversion Factor",
|
||||||
|
"print_hide": 1,
|
||||||
|
"read_only": 1,
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "stock_qty",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"label": "Qty as per Stock UOM",
|
||||||
|
"no_copy": 1,
|
||||||
|
"print_hide": 1,
|
||||||
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"modified": "2019-05-01 17:50:23.703801",
|
"links": [],
|
||||||
|
"modified": "2020-06-12 19:10:36.333441",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Buying",
|
"module": "Buying",
|
||||||
"name": "Request for Quotation Item",
|
"name": "Request for Quotation Item",
|
||||||
|
|||||||
@@ -671,3 +671,4 @@ erpnext.patches.v12_0.update_uom_conversion_factor
|
|||||||
erpnext.patches.v12_0.set_italian_import_supplier_invoice_permissions
|
erpnext.patches.v12_0.set_italian_import_supplier_invoice_permissions
|
||||||
execute:frappe.reload_doc("HR", "doctype", "Employee Advance")
|
execute:frappe.reload_doc("HR", "doctype", "Employee Advance")
|
||||||
erpnext.patches.v12_0.move_due_advance_amount_to_pending_amount
|
erpnext.patches.v12_0.move_due_advance_amount_to_pending_amount
|
||||||
|
erpnext.patches.v12_0.set_multi_uom_in_rfq
|
||||||
|
|||||||
29
erpnext/patches/v12_0/set_multi_uom_in_rfq.py
Normal file
29
erpnext/patches/v12_0/set_multi_uom_in_rfq.py
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# Copyright (c) 2017, Frappe and Contributors
|
||||||
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
from frappe.utils import flt
|
||||||
|
from erpnext.stock.get_item_details import get_conversion_factor
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
frappe.reload_doc('buying', 'doctype', 'request_for_quotation_item')
|
||||||
|
|
||||||
|
for rfq_item in frappe.db.sql("""SELECT name, item_code, uom, qty FROM `tabRequest for Quotation Item` WHERE docstatus<2""", as_dict=1):
|
||||||
|
item_code, uom, qty = rfq_item.get("item_code"), rfq_item.get("uom"), rfq_item.get("qty")
|
||||||
|
conversion_factor = get_conversion_factor(item_code, uom).get("conversion_factor") or 1.0
|
||||||
|
|
||||||
|
filters = {
|
||||||
|
"name" : rfq_item.get("name"),
|
||||||
|
"stock_uom" : frappe.db.get_value("Item", item_code, "stock_uom"),
|
||||||
|
"conversion_factor" : conversion_factor,
|
||||||
|
"stock_qty" : flt(qty) * flt(conversion_factor)
|
||||||
|
}
|
||||||
|
|
||||||
|
frappe.db.sql("""UPDATE `tabRequest for Quotation Item`
|
||||||
|
SET
|
||||||
|
stock_uom= %(stock_uom)s,
|
||||||
|
conversion_factor = %(conversion_factor)s,
|
||||||
|
stock_qty = %(stock_qty)s
|
||||||
|
WHERE
|
||||||
|
name = %(name)s""", filters)
|
||||||
Reference in New Issue
Block a user