[fix] Item Re-order if Bin does not exists and fixed Stock Projected Qty report to show per Warehouse Re-order level
This commit is contained in:
parent
2c749db2a9
commit
7b2b0cd73c
@ -15,21 +15,37 @@ def reorder_item():
|
|||||||
|
|
||||||
def _reorder_item():
|
def _reorder_item():
|
||||||
material_requests = {"Purchase": {}, "Transfer": {}}
|
material_requests = {"Purchase": {}, "Transfer": {}}
|
||||||
|
warehouse_company = frappe._dict(frappe.db.sql("""select name, company from `tabWarehouse`
|
||||||
item_warehouse_projected_qty = get_item_warehouse_projected_qty()
|
where disabled=0"""))
|
||||||
|
|
||||||
warehouse_company = frappe._dict(frappe.db.sql("""select name, company from `tabWarehouse`"""))
|
|
||||||
default_company = (frappe.defaults.get_defaults().get("company") or
|
default_company = (frappe.defaults.get_defaults().get("company") or
|
||||||
frappe.db.sql("""select name from tabCompany limit 1""")[0][0])
|
frappe.db.sql("""select name from tabCompany limit 1""")[0][0])
|
||||||
|
|
||||||
|
items_to_consider = frappe.db.sql_list("""select name from `tabItem` item
|
||||||
|
where is_stock_item=1 and has_variants=0
|
||||||
|
and (is_purchase_item=1 or is_sub_contracted_item=1)
|
||||||
|
and (end_of_life is null or end_of_life='0000-00-00' or end_of_life > %(today)s)
|
||||||
|
and ((re_order_level is not null and re_order_level > 0)
|
||||||
|
or exists (select name from `tabItem Reorder` ir where ir.parent=item.name)
|
||||||
|
or (variant_of is not null and variant_of != ''
|
||||||
|
and exists (select name from `tabItem Reorder` ir where ir.parent=item.variant_of))
|
||||||
|
)""",
|
||||||
|
{"today": nowdate()})
|
||||||
|
|
||||||
|
if not items_to_consider:
|
||||||
|
return
|
||||||
|
|
||||||
|
item_warehouse_projected_qty = get_item_warehouse_projected_qty(items_to_consider)
|
||||||
|
|
||||||
def add_to_material_request(item_code, warehouse, reorder_level, reorder_qty, material_request_type):
|
def add_to_material_request(item_code, warehouse, reorder_level, reorder_qty, material_request_type):
|
||||||
if warehouse not in item_warehouse_projected_qty[item_code]:
|
if warehouse not in warehouse_company:
|
||||||
# likely a disabled warehouse or a warehouse where BIN does not exist
|
# a disabled warehouse
|
||||||
return
|
return
|
||||||
|
|
||||||
reorder_level = flt(reorder_level)
|
reorder_level = flt(reorder_level)
|
||||||
reorder_qty = flt(reorder_qty)
|
reorder_qty = flt(reorder_qty)
|
||||||
projected_qty = item_warehouse_projected_qty[item_code][warehouse]
|
|
||||||
|
# projected_qty will be 0 if Bin does not exist
|
||||||
|
projected_qty = flt(item_warehouse_projected_qty.get(item_code, {}).get(warehouse))
|
||||||
|
|
||||||
if reorder_level and projected_qty < reorder_level:
|
if reorder_level and projected_qty < reorder_level:
|
||||||
deficiency = reorder_level - projected_qty
|
deficiency = reorder_level - projected_qty
|
||||||
@ -44,7 +60,7 @@ def _reorder_item():
|
|||||||
"reorder_qty": reorder_qty
|
"reorder_qty": reorder_qty
|
||||||
})
|
})
|
||||||
|
|
||||||
for item_code in item_warehouse_projected_qty:
|
for item_code in items_to_consider:
|
||||||
item = frappe.get_doc("Item", item_code)
|
item = frappe.get_doc("Item", item_code)
|
||||||
|
|
||||||
if item.variant_of and not item.get("reorder_levels"):
|
if item.variant_of and not item.get("reorder_levels"):
|
||||||
@ -62,18 +78,13 @@ def _reorder_item():
|
|||||||
if material_requests:
|
if material_requests:
|
||||||
return create_material_request(material_requests)
|
return create_material_request(material_requests)
|
||||||
|
|
||||||
def get_item_warehouse_projected_qty():
|
def get_item_warehouse_projected_qty(items_to_consider):
|
||||||
item_warehouse_projected_qty = {}
|
item_warehouse_projected_qty = {}
|
||||||
|
|
||||||
for item_code, warehouse, projected_qty in frappe.db.sql("""select item_code, warehouse, projected_qty
|
for item_code, warehouse, projected_qty in frappe.db.sql("""select item_code, warehouse, projected_qty
|
||||||
from tabBin where ifnull(item_code, '') != '' and ifnull(warehouse, '') != ''
|
from tabBin where item_code in ({0})
|
||||||
and exists (select name from `tabItem`
|
and (warehouse != "" and warehouse is not null)"""\
|
||||||
where `tabItem`.name = `tabBin`.item_code and
|
.format(", ".join(["%s"] * len(items_to_consider))), items_to_consider):
|
||||||
is_stock_item=1 and (is_purchase_item=1 or is_sub_contracted_item=1) and
|
|
||||||
(ifnull(end_of_life, '0000-00-00')='0000-00-00' or end_of_life > %s))
|
|
||||||
and exists (select name from `tabWarehouse`
|
|
||||||
where `tabWarehouse`.name = `tabBin`.warehouse
|
|
||||||
and ifnull(disabled, 0)=0)""", nowdate()):
|
|
||||||
|
|
||||||
item_warehouse_projected_qty.setdefault(item_code, {})[warehouse] = flt(projected_qty)
|
item_warehouse_projected_qty.setdefault(item_code, {})[warehouse] = flt(projected_qty)
|
||||||
|
|
||||||
|
@ -6,25 +6,8 @@ import frappe
|
|||||||
from frappe import _
|
from frappe import _
|
||||||
|
|
||||||
def execute(filters=None):
|
def execute(filters=None):
|
||||||
columns = get_columns()
|
filters = frappe._dict(filters or {})
|
||||||
|
return get_columns(), get_data(filters)
|
||||||
data = frappe.db.sql("""select
|
|
||||||
item.name, item.item_name, description, item_group, brand, warehouse, item.stock_uom,
|
|
||||||
actual_qty, planned_qty, indented_qty, ordered_qty, reserved_qty,
|
|
||||||
projected_qty, item.re_order_level, item.re_order_qty,
|
|
||||||
(item.re_order_level - projected_qty) as shortage_qty
|
|
||||||
from `tabBin` bin,
|
|
||||||
(select name, company from tabWarehouse
|
|
||||||
{warehouse_conditions}) wh,
|
|
||||||
(select name, item_name, description, stock_uom, item_group,
|
|
||||||
brand, re_order_level, re_order_qty
|
|
||||||
from `tabItem` {item_conditions}) item
|
|
||||||
where item_code = item.name and warehouse = wh.name
|
|
||||||
order by item.name, wh.name"""\
|
|
||||||
.format(item_conditions=get_item_conditions(filters),
|
|
||||||
warehouse_conditions=get_warehouse_conditions(filters)), filters)
|
|
||||||
|
|
||||||
return columns, data
|
|
||||||
|
|
||||||
def get_columns():
|
def get_columns():
|
||||||
return [_("Item Code") + ":Link/Item:140", _("Item Name") + "::100", _("Description") + "::200",
|
return [_("Item Code") + ":Link/Item:140", _("Item Name") + "::100", _("Description") + "::200",
|
||||||
@ -34,20 +17,47 @@ def get_columns():
|
|||||||
_("Projected Qty") + ":Float:100", _("Reorder Level") + ":Float:100", _("Reorder Qty") + ":Float:100",
|
_("Projected Qty") + ":Float:100", _("Reorder Level") + ":Float:100", _("Reorder Qty") + ":Float:100",
|
||||||
_("Shortage Qty") + ":Float:100"]
|
_("Shortage Qty") + ":Float:100"]
|
||||||
|
|
||||||
def get_item_conditions(filters):
|
def get_data(filters):
|
||||||
conditions = []
|
item_map = {}
|
||||||
if filters.get("item_code"):
|
warehouse_company = {}
|
||||||
conditions.append("name=%(item_code)s")
|
data = []
|
||||||
if filters.get("brand"):
|
|
||||||
conditions.append("brand=%(brand)s")
|
|
||||||
|
|
||||||
return "where {}".format(" and ".join(conditions)) if conditions else ""
|
for bin in get_bin_list(filters):
|
||||||
|
item = item_map.setdefault(bin.item_code, frappe.get_doc("Item", bin.item_code))
|
||||||
|
company = warehouse_company.setdefault(bin.warehouse, frappe.db.get_value("Warehouse", bin.warehouse, "company"))
|
||||||
|
|
||||||
def get_warehouse_conditions(filters):
|
if filters.brand and filters.brand != item.brand:
|
||||||
conditions = []
|
continue
|
||||||
if filters.get("company"):
|
|
||||||
conditions.append("company=%(company)s")
|
|
||||||
if filters.get("warehouse"):
|
|
||||||
conditions.append("name=%(warehouse)s")
|
|
||||||
|
|
||||||
return "where {}".format(" and ".join(conditions)) if conditions else ""
|
elif filters.company and filters.company != company:
|
||||||
|
continue
|
||||||
|
|
||||||
|
re_order_level = re_order_qty = 0
|
||||||
|
|
||||||
|
if bin.warehouse==item.default_warehouse:
|
||||||
|
re_order_level = item.re_order_level or 0
|
||||||
|
re_order_qty = item.re_order_qty or 0
|
||||||
|
|
||||||
|
for d in item.get("reorder_levels"):
|
||||||
|
if d.warehouse == bin.warehouse:
|
||||||
|
re_order_level = d.warehouse_reorder_level
|
||||||
|
re_order_qty = d.warehouse_reorder_qty
|
||||||
|
|
||||||
|
data.append([item.name, item.item_name, item.description, item.item_group, item.brand, bin.warehouse,
|
||||||
|
item.stock_uom, bin.actual_qty, bin.planned_qty, bin.indented_qty, bin.ordered_qty, bin.reserved_qty,
|
||||||
|
bin.projected_qty, re_order_level, re_order_qty, re_order_level - bin.projected_qty])
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
def get_bin_list(filters):
|
||||||
|
bin_filters = frappe._dict()
|
||||||
|
if filters.item_code:
|
||||||
|
bin_filters.item_code = filters.item_code
|
||||||
|
if filters.warehouse:
|
||||||
|
bin_filters.warehouse = filters.warehouse
|
||||||
|
|
||||||
|
bin_list = frappe.get_all("Bin", fields=["item_code", "warehouse",
|
||||||
|
"actual_qty", "planned_qty", "indented_qty", "ordered_qty", "reserved_qty", "projected_qty"],
|
||||||
|
filters=bin_filters, order_by="item_code, warehouse")
|
||||||
|
|
||||||
|
return bin_list
|
||||||
|
Loading…
x
Reference in New Issue
Block a user