BIS issue fixes
This commit is contained in:
parent
29552c1ec4
commit
34766c0c50
@ -678,7 +678,9 @@ class BuyingController(StockController):
|
|||||||
frappe.db.sql("delete from `tabSerial No` where purchase_document_no=%s", self.name)
|
frappe.db.sql("delete from `tabSerial No` where purchase_document_no=%s", self.name)
|
||||||
|
|
||||||
def validate_schedule_date(self):
|
def validate_schedule_date(self):
|
||||||
if not self.schedule_date and self.get("items"):
|
if not self.get("items"):
|
||||||
|
return
|
||||||
|
if not self.schedule_date:
|
||||||
self.schedule_date = min([d.schedule_date for d in self.get("items")])
|
self.schedule_date = min([d.schedule_date for d in self.get("items")])
|
||||||
|
|
||||||
if self.schedule_date:
|
if self.schedule_date:
|
||||||
|
@ -7,7 +7,7 @@ import frappe, json
|
|||||||
from frappe import msgprint, _
|
from frappe import msgprint, _
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from erpnext.manufacturing.doctype.bom.bom import validate_bom_no
|
from erpnext.manufacturing.doctype.bom.bom import validate_bom_no
|
||||||
from frappe.utils import cstr, flt, cint, nowdate, add_days, comma_and, now_datetime
|
from frappe.utils import cstr, flt, cint, nowdate, add_days, comma_and, now_datetime, ceil
|
||||||
from erpnext.manufacturing.doctype.work_order.work_order import get_item_details
|
from erpnext.manufacturing.doctype.work_order.work_order import get_item_details
|
||||||
from six import string_types
|
from six import string_types
|
||||||
from erpnext.setup.doctype.item_group.item_group import get_item_group_defaults
|
from erpnext.setup.doctype.item_group.item_group import get_item_group_defaults
|
||||||
@ -376,13 +376,16 @@ def get_exploded_items(bom_wise_item_details, company, bom_no, include_non_stock
|
|||||||
for d in frappe.db.sql("""select bei.item_code, item.default_bom as bom,
|
for d in frappe.db.sql("""select bei.item_code, item.default_bom as bom,
|
||||||
ifnull(sum(bei.stock_qty/ifnull(bom.quantity, 1)), 0) as qty, item.item_name,
|
ifnull(sum(bei.stock_qty/ifnull(bom.quantity, 1)), 0) as qty, item.item_name,
|
||||||
bei.description, bei.stock_uom, item.min_order_qty, bei.source_warehouse,
|
bei.description, bei.stock_uom, item.min_order_qty, bei.source_warehouse,
|
||||||
item.default_material_request_type, item.min_order_qty, item_default.default_warehouse
|
item.default_material_request_type, item.min_order_qty, item_default.default_warehouse,
|
||||||
|
item.purchase_uom, item_uom.conversion_factor
|
||||||
from
|
from
|
||||||
`tabBOM Explosion Item` bei
|
`tabBOM Explosion Item` bei
|
||||||
JOIN `tabBOM` bom ON bom.name = bei.parent
|
JOIN `tabBOM` bom ON bom.name = bei.parent
|
||||||
JOIN `tabItem` item ON item.name = bei.item_code
|
JOIN `tabItem` item ON item.name = bei.item_code
|
||||||
LEFT JOIN `tabItem Default` item_default
|
LEFT JOIN `tabItem Default` item_default
|
||||||
ON item_default.parent = item.name and item_default.company=%s
|
ON item_default.parent = item.name and item_default.company=%s
|
||||||
|
LEFT JOIN `tabUOM Conversion Detail` item_uom
|
||||||
|
ON item.name = item_uom.parent and item_uom.uom = item.purchase_uom
|
||||||
where
|
where
|
||||||
bei.docstatus < 2
|
bei.docstatus < 2
|
||||||
and bom.name=%s and item.is_stock_item in (1, {0})
|
and bom.name=%s and item.is_stock_item in (1, {0})
|
||||||
@ -399,13 +402,15 @@ def get_subitems(doc, data, bom_wise_item_details, bom_no, company, include_non_
|
|||||||
item.is_sub_contracted_item as is_sub_contracted, bom_item.source_warehouse,
|
item.is_sub_contracted_item as is_sub_contracted, bom_item.source_warehouse,
|
||||||
item.default_bom as default_bom, bom_item.description as description,
|
item.default_bom as default_bom, bom_item.description as description,
|
||||||
bom_item.stock_uom as stock_uom, item.min_order_qty as min_order_qty,
|
bom_item.stock_uom as stock_uom, item.min_order_qty as min_order_qty,
|
||||||
item_default.default_warehouse
|
item_default.default_warehouse, item.purchase_uom, item_uom.conversion_factor
|
||||||
FROM
|
FROM
|
||||||
`tabBOM Item` bom_item
|
`tabBOM Item` bom_item
|
||||||
JOIN `tabBOM` bom ON bom.name = bom_item.parent
|
JOIN `tabBOM` bom ON bom.name = bom_item.parent
|
||||||
JOIN tabItem item ON bom_item.item_code = item.name
|
JOIN tabItem item ON bom_item.item_code = item.name
|
||||||
LEFT JOIN `tabItem Default` item_default
|
LEFT JOIN `tabItem Default` item_default
|
||||||
ON item.name = item_default.parent and item_default.company = %(company)s
|
ON item.name = item_default.parent and item_default.company = %(company)s
|
||||||
|
LEFT JOIN `tabUOM Conversion Detail` item_uom
|
||||||
|
ON item.name = item_uom.parent and item_uom.uom = item.purchase_uom
|
||||||
where
|
where
|
||||||
bom.name = %(bom)s
|
bom.name = %(bom)s
|
||||||
and bom_item.docstatus < 2
|
and bom_item.docstatus < 2
|
||||||
@ -431,17 +436,30 @@ def get_subitems(doc, data, bom_wise_item_details, bom_no, company, include_non_
|
|||||||
return bom_wise_item_details
|
return bom_wise_item_details
|
||||||
|
|
||||||
def add_item_in_material_request_items(doc, planned_qty, ignore_existing_ordered_qty, item, row, data, warehouse, company):
|
def add_item_in_material_request_items(doc, planned_qty, ignore_existing_ordered_qty, item, row, data, warehouse, company):
|
||||||
|
print("add item in material request")
|
||||||
total_qty = row.qty * planned_qty
|
total_qty = row.qty * planned_qty
|
||||||
projected_qty, actual_qty = get_bin_details(row)
|
projected_qty, actual_qty = get_bin_details(row)
|
||||||
|
|
||||||
requested_qty = 0
|
requested_qty = 0
|
||||||
if ignore_existing_ordered_qty:
|
if ignore_existing_ordered_qty:
|
||||||
requested_qty = total_qty
|
requested_qty = total_qty
|
||||||
else:
|
elif total_qty > projected_qty:
|
||||||
requested_qty = total_qty - projected_qty
|
requested_qty = total_qty - projected_qty
|
||||||
if requested_qty > 0 and requested_qty < row.min_order_qty:
|
if requested_qty > 0 and requested_qty < row.min_order_qty:
|
||||||
requested_qty = row.min_order_qty
|
requested_qty = row.min_order_qty
|
||||||
item_group_defaults = get_item_group_defaults(item, company)
|
item_group_defaults = get_item_group_defaults(item, company)
|
||||||
|
|
||||||
|
if not row.purchase_uom:
|
||||||
|
row.purchase_uom = row.stock_uom
|
||||||
|
|
||||||
|
if row.purchase_uom != row.stock_uom:
|
||||||
|
if not row.conversion_factor:
|
||||||
|
frappe.throw(_("UOM Conversion factor ({0} -> {1}) not found for item: {2}").format(row.purchase_uom, row.stock_uom, item))
|
||||||
|
|
||||||
|
requested_qty = requested_qty / row.conversion_factor
|
||||||
|
if frappe.db.get_value("UOM", row.purchase_uom, "must_be_whole_number"):
|
||||||
|
requested_qty = ceil(requested_qty)
|
||||||
|
print(row)
|
||||||
if requested_qty > 0:
|
if requested_qty > 0:
|
||||||
doc.setdefault('mr_items', []).append({
|
doc.setdefault('mr_items', []).append({
|
||||||
'item_code': item,
|
'item_code': item,
|
||||||
@ -487,8 +505,8 @@ def get_sales_orders(self):
|
|||||||
"project": self.project,
|
"project": self.project,
|
||||||
"item": self.item_code,
|
"item": self.item_code,
|
||||||
"company": self.company
|
"company": self.company
|
||||||
}, as_dict=1)
|
|
||||||
|
|
||||||
|
}, as_dict=1)
|
||||||
return open_so
|
return open_so
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
@ -511,6 +529,7 @@ def get_bin_details(row):
|
|||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_items_for_material_requests(doc, company=None):
|
def get_items_for_material_requests(doc, company=None):
|
||||||
|
print("get items for material request")
|
||||||
if isinstance(doc, string_types):
|
if isinstance(doc, string_types):
|
||||||
doc = frappe._dict(json.loads(doc))
|
doc = frappe._dict(json.loads(doc))
|
||||||
|
|
||||||
@ -520,34 +539,69 @@ def get_items_for_material_requests(doc, company=None):
|
|||||||
for data in po_items:
|
for data in po_items:
|
||||||
warehouse = None
|
warehouse = None
|
||||||
bom_wise_item_details = {}
|
bom_wise_item_details = {}
|
||||||
|
if data.get("bom"):
|
||||||
if data.get('required_qty'):
|
print(doc),print("-------------------------------------------------")
|
||||||
planned_qty = data.get('required_qty')
|
if data.get('required_qty'):
|
||||||
bom_no = data.get('bom')
|
planned_qty = data.get('required_qty')
|
||||||
ignore_existing_ordered_qty = data.get('ignore_existing_ordered_qty')
|
bom_no = data.get('bom')
|
||||||
include_non_stock_items = 1
|
ignore_existing_ordered_qty = data.get('ignore_existing_ordered_qty')
|
||||||
warehouse = data.get('for_warehouse')
|
include_non_stock_items = 1
|
||||||
if data.get('include_exploded_items'):
|
warehouse = data.get('for_warehouse')
|
||||||
include_subcontracted_items = 1
|
if data.get('include_exploded_items'):
|
||||||
|
include_subcontracted_items = 1
|
||||||
|
else:
|
||||||
|
include_subcontracted_items = 0
|
||||||
else:
|
else:
|
||||||
include_subcontracted_items = 0
|
planned_qty = data.get('planned_qty')
|
||||||
else:
|
bom_no = data.get('bom_no')
|
||||||
planned_qty = data.get('planned_qty')
|
include_subcontracted_items = doc.get('include_subcontracted_items')
|
||||||
bom_no = data.get('bom_no')
|
company = doc.get('company')
|
||||||
include_subcontracted_items = doc.get('include_subcontracted_items')
|
include_non_stock_items = doc.get('include_non_stock_items')
|
||||||
company = doc.get('company')
|
ignore_existing_ordered_qty = doc.get('ignore_existing_ordered_qty')
|
||||||
include_non_stock_items = doc.get('include_non_stock_items')
|
if not planned_qty:
|
||||||
ignore_existing_ordered_qty = doc.get('ignore_existing_ordered_qty')
|
frappe.throw(_("For row {0}: Enter Planned Qty").format(data.get('idx')))
|
||||||
if not planned_qty:
|
|
||||||
frappe.throw(_("For row {0}: Enter Planned Qty").format(data.get('idx')))
|
|
||||||
|
|
||||||
if data.get('include_exploded_items') and bom_no and include_subcontracted_items:
|
if data.get('include_exploded_items') and bom_no and include_subcontracted_items:
|
||||||
# fetch exploded items from BOM
|
# fetch exploded items from BOM
|
||||||
bom_wise_item_details = get_exploded_items(bom_wise_item_details, company, bom_no, include_non_stock_items)
|
bom_wise_item_details = get_exploded_items(bom_wise_item_details, company, bom_no, include_non_stock_items)
|
||||||
|
else:
|
||||||
|
bom_wise_item_details = get_subitems(doc, data, bom_wise_item_details, bom_no, company, include_non_stock_items, include_subcontracted_items, 1)
|
||||||
|
for item, item_details in bom_wise_item_details.items():
|
||||||
|
print(item),print(item_details)
|
||||||
|
if item_details.qty > 0:
|
||||||
|
add_item_in_material_request_items(doc, planned_qty, ignore_existing_ordered_qty, item, item_details, data, warehouse, company)
|
||||||
else:
|
else:
|
||||||
bom_wise_item_details = get_subitems(doc, data, bom_wise_item_details, bom_no, company, include_non_stock_items, include_subcontracted_items, 1)
|
sales_order_item = frappe.get_doc('Sales OrderItem', data.sales_order_item).as_dict()
|
||||||
for item, item_details in bom_wise_item_details.items():
|
planned_qty = data.get('required_qty')
|
||||||
|
ignore_existing_ordered_qty = data.get('ignore_existing_ordered_qty')
|
||||||
|
item = doc.item_code
|
||||||
|
purchase_uom = sales_order_item.uom
|
||||||
|
stock_uom = sales_order_item.stock_uom
|
||||||
|
conversion_factor = sales_order_item.conversion_factor
|
||||||
|
qty = doc.required_qty
|
||||||
|
if not purchase_uom == stock_uom:
|
||||||
|
qty = qty / conversion_factor
|
||||||
|
if frappe.db.get_value("UOM", purchase_uom, "must_be_whole_number"):
|
||||||
|
qty = ceil(qty)
|
||||||
|
item_details = {
|
||||||
|
'item_name' = sales_order_item.item_name,
|
||||||
|
'default_bom' = doc.bom,
|
||||||
|
'purchase_uom' = purchase_uom,
|
||||||
|
'default_warehouse' = doc.warehouse,
|
||||||
|
'min_order_qty' =
|
||||||
|
'default_material_request_type' =
|
||||||
|
'qty' = qty,
|
||||||
|
'is_sub_contracted' = ,
|
||||||
|
'item_code' = doc.item_code,
|
||||||
|
'description' = sales_order_item.description,
|
||||||
|
'stock_uom' = stock_uom,
|
||||||
|
'conversion_factor' = conversion_factor,
|
||||||
|
'source_warehouse' = ,
|
||||||
|
}
|
||||||
|
warehouse = doc.warehouse
|
||||||
|
company =
|
||||||
if item_details.qty > 0:
|
if item_details.qty > 0:
|
||||||
add_item_in_material_request_items(doc, planned_qty, ignore_existing_ordered_qty, item, item_details, data, warehouse, company)
|
add_item_in_material_request_items(doc, planned_qty, ignore_existing_ordered_qty, item, item_details, data, warehouse, company)
|
||||||
|
print(doc),print("-------------------------------------------------")
|
||||||
|
|
||||||
return doc['mr_items']
|
return doc['mr_items']
|
||||||
|
@ -344,6 +344,8 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend(
|
|||||||
label: __('Include Exploded Items')},
|
label: __('Include Exploded Items')},
|
||||||
{fieldtype:'Check', fieldname:'ignore_existing_ordered_qty',
|
{fieldtype:'Check', fieldname:'ignore_existing_ordered_qty',
|
||||||
label: __('Ignore Existing Ordered Qty')},
|
label: __('Ignore Existing Ordered Qty')},
|
||||||
|
{fieldtype:'Check', fieldname:'include_raw_materials_from_sales_order',
|
||||||
|
label: __('Include raw materials from sales order')},
|
||||||
{
|
{
|
||||||
fieldtype:'Table', fieldname: 'items',
|
fieldtype:'Table', fieldname: 'items',
|
||||||
description: __('Select BOM, Qty and For Warehouse'),
|
description: __('Select BOM, Qty and For Warehouse'),
|
||||||
@ -367,7 +369,7 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend(
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
var d = new frappe.ui.Dialog({
|
var d = new frappe.ui.Dialog({
|
||||||
title: __("Select from Items having BOM"),
|
title: __("Items for Raw Material Request"),
|
||||||
fields: fields,
|
fields: fields,
|
||||||
primary_action: function() {
|
primary_action: function() {
|
||||||
var data = d.get_values();
|
var data = d.get_values();
|
||||||
|
@ -372,20 +372,19 @@ class SalesOrder(SellingController):
|
|||||||
def get_work_order_items(self, for_raw_material_request=0):
|
def get_work_order_items(self, for_raw_material_request=0):
|
||||||
'''Returns items with BOM that already do not have a linked work order'''
|
'''Returns items with BOM that already do not have a linked work order'''
|
||||||
items = []
|
items = []
|
||||||
|
|
||||||
for table in [self.items, self.packed_items]:
|
for table in [self.items, self.packed_items]:
|
||||||
for i in table:
|
for i in table:
|
||||||
bom = get_default_bom_item(i.item_code)
|
bom = get_default_bom_item(i.item_code)
|
||||||
if bom:
|
stock_qty = i.qty if i.doctype == 'Packed Item' else i.stock_qty
|
||||||
stock_qty = i.qty if i.doctype == 'Packed Item' else i.stock_qty
|
if not for_raw_material_request:
|
||||||
if not for_raw_material_request:
|
total_work_order_qty = flt(frappe.db.sql('''select sum(qty) from `tabWork Order`
|
||||||
total_work_order_qty = flt(frappe.db.sql('''select sum(qty) from `tabWork Order`
|
where production_item=%s and sales_order=%s and sales_order_item = %s and docstatus<2''', (i.item_code, self.name, i.name))[0][0])
|
||||||
where production_item=%s and sales_order=%s and sales_order_item = %s and docstatus<2''', (i.item_code, self.name, i.name))[0][0])
|
pending_qty = stock_qty - total_work_order_qty
|
||||||
pending_qty = stock_qty - total_work_order_qty
|
else:
|
||||||
else:
|
pending_qty = stock_qty
|
||||||
pending_qty = stock_qty
|
|
||||||
|
|
||||||
if pending_qty:
|
if pending_qty:
|
||||||
|
if bom:
|
||||||
items.append(dict(
|
items.append(dict(
|
||||||
name= i.name,
|
name= i.name,
|
||||||
item_code= i.item_code,
|
item_code= i.item_code,
|
||||||
@ -395,6 +394,16 @@ class SalesOrder(SellingController):
|
|||||||
required_qty = pending_qty if for_raw_material_request else 0,
|
required_qty = pending_qty if for_raw_material_request else 0,
|
||||||
sales_order_item = i.name
|
sales_order_item = i.name
|
||||||
))
|
))
|
||||||
|
else:
|
||||||
|
items.append(dict(
|
||||||
|
name= i.name,
|
||||||
|
item_code= i.item_code,
|
||||||
|
bom = '',
|
||||||
|
warehouse = i.warehouse,
|
||||||
|
pending_qty = pending_qty,
|
||||||
|
required_qty = pending_qty if for_raw_material_request else 0,
|
||||||
|
sales_order_item = i.name
|
||||||
|
))
|
||||||
return items
|
return items
|
||||||
|
|
||||||
def on_recurring(self, reference_doc, auto_repeat_doc):
|
def on_recurring(self, reference_doc, auto_repeat_doc):
|
||||||
@ -923,10 +932,12 @@ def make_raw_material_request(items, company, sales_order, project=None):
|
|||||||
for item in items.get('items'):
|
for item in items.get('items'):
|
||||||
item["include_exploded_items"] = items.get('include_exploded_items')
|
item["include_exploded_items"] = items.get('include_exploded_items')
|
||||||
item["ignore_existing_ordered_qty"] = items.get('ignore_existing_ordered_qty')
|
item["ignore_existing_ordered_qty"] = items.get('ignore_existing_ordered_qty')
|
||||||
|
item["include_raw_materials_from_sales_order"] = items.get('include_raw_materials_from_sales_order')
|
||||||
|
|
||||||
raw_materials = get_items_for_material_requests(items, company)
|
raw_materials = get_items_for_material_requests(items, company)
|
||||||
if not raw_materials:
|
if not raw_materials:
|
||||||
frappe.msgprint(_("Material Request not created, as quantity for Raw Materials already available."))
|
frappe.msgprint(_("Material Request not created, as quantity for Raw Materials already available."))
|
||||||
|
return
|
||||||
|
|
||||||
material_request = frappe.new_doc('Material Request')
|
material_request = frappe.new_doc('Material Request')
|
||||||
material_request.update(dict(
|
material_request.update(dict(
|
||||||
|
Loading…
Reference in New Issue
Block a user