Merge pull request #25845 from noahjacob/item_so_variant_fix
fix: production plan not fetching sales order of a variant
This commit is contained in:
commit
e9c293d621
@ -109,6 +109,15 @@ class ProductionPlan(Document):
|
|||||||
so_mr_list = [d.get(field) for d in self.get(table) if d.get(field)]
|
so_mr_list = [d.get(field) for d in self.get(table) if d.get(field)]
|
||||||
return so_mr_list
|
return so_mr_list
|
||||||
|
|
||||||
|
def get_bom_item(self):
|
||||||
|
"""Check if Item or if its Template has a BOM."""
|
||||||
|
bom_item = None
|
||||||
|
has_bom = frappe.db.exists({'doctype': 'BOM', 'item': self.item_code, 'docstatus': 1})
|
||||||
|
if not has_bom:
|
||||||
|
template_item = frappe.db.get_value('Item', self.item_code, ['variant_of'])
|
||||||
|
bom_item = "bom.item = {0}".format(frappe.db.escape(template_item)) if template_item else bom_item
|
||||||
|
return bom_item
|
||||||
|
|
||||||
def get_so_items(self):
|
def get_so_items(self):
|
||||||
# Check for empty table or empty rows
|
# Check for empty table or empty rows
|
||||||
if not self.get("sales_orders") or not self.get_so_mr_list("sales_order", "sales_orders"):
|
if not self.get("sales_orders") or not self.get_so_mr_list("sales_order", "sales_orders"):
|
||||||
@ -117,16 +126,26 @@ class ProductionPlan(Document):
|
|||||||
so_list = self.get_so_mr_list("sales_order", "sales_orders")
|
so_list = self.get_so_mr_list("sales_order", "sales_orders")
|
||||||
|
|
||||||
item_condition = ""
|
item_condition = ""
|
||||||
if self.item_code:
|
bom_item = "bom.item = so_item.item_code"
|
||||||
|
if self.item_code and frappe.db.exists('Item', self.item_code):
|
||||||
|
bom_item = self.get_bom_item() or bom_item
|
||||||
item_condition = ' and so_item.item_code = {0}'.format(frappe.db.escape(self.item_code))
|
item_condition = ' and so_item.item_code = {0}'.format(frappe.db.escape(self.item_code))
|
||||||
|
|
||||||
items = frappe.db.sql("""select distinct parent, item_code, warehouse,
|
items = frappe.db.sql("""
|
||||||
(qty - work_order_qty) * conversion_factor as pending_qty, description, name
|
select
|
||||||
from `tabSales Order Item` so_item
|
distinct parent, item_code, warehouse,
|
||||||
where parent in (%s) and docstatus = 1 and qty > work_order_qty
|
(qty - work_order_qty) * conversion_factor as pending_qty,
|
||||||
and exists (select name from `tabBOM` bom where bom.item=so_item.item_code
|
description, name
|
||||||
and bom.is_active = 1) %s""" % \
|
from
|
||||||
(", ".join(["%s"] * len(so_list)), item_condition), tuple(so_list), as_dict=1)
|
`tabSales Order Item` so_item
|
||||||
|
where
|
||||||
|
parent in (%s) and docstatus = 1 and qty > work_order_qty
|
||||||
|
and exists (select name from `tabBOM` bom where %s
|
||||||
|
and bom.is_active = 1) %s""" %
|
||||||
|
(", ".join(["%s"] * len(so_list)),
|
||||||
|
bom_item,
|
||||||
|
item_condition),
|
||||||
|
tuple(so_list), as_dict=1)
|
||||||
|
|
||||||
if self.item_code:
|
if self.item_code:
|
||||||
item_condition = ' and so_item.item_code = {0}'.format(frappe.db.escape(self.item_code))
|
item_condition = ' and so_item.item_code = {0}'.format(frappe.db.escape(self.item_code))
|
||||||
@ -683,6 +702,7 @@ def get_material_request_items(row, sales_order, company,
|
|||||||
|
|
||||||
def get_sales_orders(self):
|
def get_sales_orders(self):
|
||||||
so_filter = item_filter = ""
|
so_filter = item_filter = ""
|
||||||
|
bom_item = "bom.item = so_item.item_code"
|
||||||
if self.from_date:
|
if self.from_date:
|
||||||
so_filter += " and so.transaction_date >= %(from_date)s"
|
so_filter += " and so.transaction_date >= %(from_date)s"
|
||||||
if self.to_date:
|
if self.to_date:
|
||||||
@ -694,7 +714,8 @@ def get_sales_orders(self):
|
|||||||
if self.sales_order_status:
|
if self.sales_order_status:
|
||||||
so_filter += "and so.status = %(sales_order_status)s"
|
so_filter += "and so.status = %(sales_order_status)s"
|
||||||
|
|
||||||
if self.item_code:
|
if self.item_code and frappe.db.exists('Item', self.item_code):
|
||||||
|
bom_item = self.get_bom_item() or bom_item
|
||||||
item_filter += " and so_item.item_code = %(item)s"
|
item_filter += " and so_item.item_code = %(item)s"
|
||||||
|
|
||||||
open_so = frappe.db.sql("""
|
open_so = frappe.db.sql("""
|
||||||
@ -704,13 +725,13 @@ def get_sales_orders(self):
|
|||||||
and so.docstatus = 1 and so.status not in ("Stopped", "Closed")
|
and so.docstatus = 1 and so.status not in ("Stopped", "Closed")
|
||||||
and so.company = %(company)s
|
and so.company = %(company)s
|
||||||
and so_item.qty > so_item.work_order_qty {0} {1}
|
and so_item.qty > so_item.work_order_qty {0} {1}
|
||||||
and (exists (select name from `tabBOM` bom where bom.item=so_item.item_code
|
and (exists (select name from `tabBOM` bom where {2}
|
||||||
and bom.is_active = 1)
|
and bom.is_active = 1)
|
||||||
or exists (select name from `tabPacked Item` pi
|
or exists (select name from `tabPacked Item` pi
|
||||||
where pi.parent = so.name and pi.parent_item = so_item.item_code
|
where pi.parent = so.name and pi.parent_item = so_item.item_code
|
||||||
and exists (select name from `tabBOM` bom where bom.item=pi.item_code
|
and exists (select name from `tabBOM` bom where bom.item=pi.item_code
|
||||||
and bom.is_active = 1)))
|
and bom.is_active = 1)))
|
||||||
""".format(so_filter, item_filter), {
|
""".format(so_filter, item_filter, bom_item), {
|
||||||
"from_date": self.from_date,
|
"from_date": self.from_date,
|
||||||
"to_date": self.to_date,
|
"to_date": self.to_date,
|
||||||
"customer": self.customer,
|
"customer": self.customer,
|
||||||
|
|||||||
@ -11,6 +11,7 @@ from erpnext.manufacturing.doctype.production_plan.production_plan import get_sa
|
|||||||
from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import create_stock_reconciliation
|
from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import create_stock_reconciliation
|
||||||
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
|
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
|
||||||
from erpnext.manufacturing.doctype.production_plan.production_plan import get_items_for_material_requests, get_warehouse_list
|
from erpnext.manufacturing.doctype.production_plan.production_plan import get_items_for_material_requests, get_warehouse_list
|
||||||
|
from erpnext.controllers.item_variant import create_variant
|
||||||
|
|
||||||
class TestProductionPlan(unittest.TestCase):
|
class TestProductionPlan(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@ -271,6 +272,60 @@ class TestProductionPlan(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertEqual(warehouses, expected_warehouses)
|
self.assertEqual(warehouses, expected_warehouses)
|
||||||
|
|
||||||
|
def test_get_sales_order_with_variant(self):
|
||||||
|
if not frappe.db.exists('Item', {"item_code": 'PIV'}):
|
||||||
|
item = create_item('PIV', valuation_rate = 100)
|
||||||
|
variant_settings = {
|
||||||
|
"attributes": [
|
||||||
|
{
|
||||||
|
"attribute": "Colour"
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"has_variants": 1
|
||||||
|
}
|
||||||
|
item.update(variant_settings)
|
||||||
|
item.save()
|
||||||
|
parent_bom = make_bom(item = 'PIV', raw_materials = ['PIV'])
|
||||||
|
if not frappe.db.exists('BOM', {"item": 'PIV'}):
|
||||||
|
parent_bom = make_bom(item = 'PIV', raw_materials = ['PIV'])
|
||||||
|
else:
|
||||||
|
parent_bom = frappe.get_doc('BOM', {"item": 'PIV'})
|
||||||
|
|
||||||
|
if not frappe.db.exists('Item', {"item_code": 'PIV-RED'}):
|
||||||
|
variant = create_variant("PIV", {"Colour": "Red"})
|
||||||
|
variant.save()
|
||||||
|
variant_bom = make_bom(item = variant.item_code, raw_materials = [variant.item_code])
|
||||||
|
else:
|
||||||
|
variant = frappe.get_doc('Item', 'PIV-RED')
|
||||||
|
if not frappe.db.exists('BOM', {"item": 'PIV-RED'}):
|
||||||
|
variant_bom = make_bom(item = variant.item_code, raw_materials = [variant.item_code])
|
||||||
|
|
||||||
|
"""Testing when item variant has a BOM"""
|
||||||
|
so = make_sales_order(item_code="PIV-RED", qty=5)
|
||||||
|
pln = frappe.new_doc('Production Plan')
|
||||||
|
pln.company = so.company
|
||||||
|
pln.get_items_from = 'Sales Order'
|
||||||
|
pln.item_code = 'PIV-RED'
|
||||||
|
pln.get_open_sales_orders()
|
||||||
|
self.assertEqual(pln.sales_orders[0].sales_order, so.name)
|
||||||
|
pln.get_so_items()
|
||||||
|
self.assertEqual(pln.po_items[0].item_code, 'PIV-RED')
|
||||||
|
self.assertEqual(pln.po_items[0].bom_no, variant_bom.name)
|
||||||
|
so.cancel()
|
||||||
|
frappe.delete_doc('Sales Order', so.name)
|
||||||
|
variant_bom.cancel()
|
||||||
|
frappe.delete_doc('BOM', variant_bom.name)
|
||||||
|
|
||||||
|
"""Testing when item variant doesn't have a BOM"""
|
||||||
|
so = make_sales_order(item_code="PIV-RED", qty=5)
|
||||||
|
pln.get_open_sales_orders()
|
||||||
|
self.assertEqual(pln.sales_orders[0].sales_order, so.name)
|
||||||
|
pln.po_items = []
|
||||||
|
pln.get_so_items()
|
||||||
|
self.assertEqual(pln.po_items[0].item_code, 'PIV-RED')
|
||||||
|
self.assertEqual(pln.po_items[0].bom_no, parent_bom.name)
|
||||||
|
|
||||||
|
frappe.db.rollback()
|
||||||
|
|
||||||
def create_production_plan(**args):
|
def create_production_plan(**args):
|
||||||
args = frappe._dict(args)
|
args = frappe._dict(args)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user