Merge pull request #25797 from marination/item-variants-report
fix: Item Variant Details Report
This commit is contained in:
commit
eaf0465c44
@ -14,47 +14,58 @@ def get_data(item):
|
||||
if not item:
|
||||
return []
|
||||
item_dicts = []
|
||||
variants = None
|
||||
|
||||
variant_results = frappe.db.sql("""select name from `tabItem`
|
||||
where variant_of = %s""", item, as_dict=1)
|
||||
variant_results = frappe.db.get_all(
|
||||
"Item",
|
||||
fields=["name"],
|
||||
filters={
|
||||
"variant_of": ["=", item],
|
||||
"disabled": 0
|
||||
}
|
||||
)
|
||||
|
||||
if not variant_results:
|
||||
frappe.msgprint(_("There isn't any item variant for the selected item"))
|
||||
frappe.msgprint(_("There aren't any item variants for the selected item"))
|
||||
return []
|
||||
else:
|
||||
variants = ", ".join([frappe.db.escape(variant['name']) for variant in variant_results])
|
||||
variant_list = [variant['name'] for variant in variant_results]
|
||||
|
||||
order_count_map = get_open_sales_orders_map(variants)
|
||||
stock_details_map = get_stock_details_map(variants)
|
||||
buying_price_map = get_buying_price_map(variants)
|
||||
selling_price_map = get_selling_price_map(variants)
|
||||
attr_val_map = get_attribute_values_map(variants)
|
||||
order_count_map = get_open_sales_orders_count(variant_list)
|
||||
stock_details_map = get_stock_details_map(variant_list)
|
||||
buying_price_map = get_buying_price_map(variant_list)
|
||||
selling_price_map = get_selling_price_map(variant_list)
|
||||
attr_val_map = get_attribute_values_map(variant_list)
|
||||
|
||||
attribute_list = [d[0] for d in frappe.db.sql("""select attribute
|
||||
from `tabItem Variant Attribute`
|
||||
where parent in ({variants}) group by attribute""".format(variants=variants))]
|
||||
attributes = frappe.db.get_all(
|
||||
"Item Variant Attribute",
|
||||
fields=["attribute"],
|
||||
filters={
|
||||
"parent": ["in", variant_list]
|
||||
},
|
||||
group_by="attribute"
|
||||
)
|
||||
attribute_list = [row.get("attribute") for row in attributes]
|
||||
|
||||
# Prepare dicts
|
||||
variant_dicts = [{"variant_name": d['name']} for d in variant_results]
|
||||
for item_dict in variant_dicts:
|
||||
name = item_dict["variant_name"]
|
||||
name = item_dict.get("variant_name")
|
||||
|
||||
for d in attribute_list:
|
||||
attr_dict = attr_val_map[name]
|
||||
if attr_dict and attr_dict.get(d):
|
||||
item_dict[d] = attr_val_map[name][d]
|
||||
for attribute in attribute_list:
|
||||
attr_dict = attr_val_map.get(name)
|
||||
if attr_dict and attr_dict.get(attribute):
|
||||
item_dict[frappe.scrub(attribute)] = attr_val_map.get(name).get(attribute)
|
||||
|
||||
item_dict["Open Orders"] = order_count_map.get(name) or 0
|
||||
item_dict["open_orders"] = order_count_map.get(name) or 0
|
||||
|
||||
if stock_details_map.get(name):
|
||||
item_dict["Inventory"] = stock_details_map.get(name)["Inventory"] or 0
|
||||
item_dict["In Production"] = stock_details_map.get(name)["In Production"] or 0
|
||||
item_dict["Available Selling"] = stock_details_map.get(name)["Available Selling"] or 0
|
||||
item_dict["current_stock"] = stock_details_map.get(name)["Inventory"] or 0
|
||||
item_dict["in_production"] = stock_details_map.get(name)["In Production"] or 0
|
||||
else:
|
||||
item_dict["Inventory"] = item_dict["In Production"] = item_dict["Available Selling"] = 0
|
||||
item_dict["current_stock"] = item_dict["in_production"] = 0
|
||||
|
||||
item_dict["Avg. Buying Price List Rate"] = buying_price_map.get(name) or 0
|
||||
item_dict["Avg. Selling Price List Rate"] = selling_price_map.get(name) or 0
|
||||
item_dict["avg_buying_price_list_rate"] = buying_price_map.get(name) or 0
|
||||
item_dict["avg_selling_price_list_rate"] = selling_price_map.get(name) or 0
|
||||
|
||||
item_dicts.append(item_dict)
|
||||
|
||||
@ -71,117 +82,158 @@ def get_columns(item):
|
||||
|
||||
item_doc = frappe.get_doc("Item", item)
|
||||
|
||||
for d in item_doc.attributes:
|
||||
columns.append(d.attribute + ":Data:100")
|
||||
for entry in item_doc.attributes:
|
||||
columns.append({
|
||||
"fieldname": frappe.scrub(entry.attribute),
|
||||
"label": entry.attribute,
|
||||
"fieldtype": "Data",
|
||||
"width": 100
|
||||
})
|
||||
|
||||
columns += [_("Avg. Buying Price List Rate") + ":Currency:110", _("Avg. Selling Price List Rate") + ":Currency:110",
|
||||
_("Inventory") + ":Float:100", _("In Production") + ":Float:100",
|
||||
_("Open Orders") + ":Float:100", _("Available Selling") + ":Float:100"
|
||||
additional_columns = [
|
||||
{
|
||||
"fieldname": "avg_buying_price_list_rate",
|
||||
"label": _("Avg. Buying Price List Rate"),
|
||||
"fieldtype": "Currency",
|
||||
"width": 150
|
||||
},
|
||||
{
|
||||
"fieldname": "avg_selling_price_list_rate",
|
||||
"label": _("Avg. Selling Price List Rate"),
|
||||
"fieldtype": "Currency",
|
||||
"width": 150
|
||||
},
|
||||
{
|
||||
"fieldname": "current_stock",
|
||||
"label": _("Current Stock"),
|
||||
"fieldtype": "Float",
|
||||
"width": 120
|
||||
},
|
||||
{
|
||||
"fieldname": "in_production",
|
||||
"label": _("In Production"),
|
||||
"fieldtype": "Float",
|
||||
"width": 150
|
||||
},
|
||||
{
|
||||
"fieldname": "open_orders",
|
||||
"label": _("Open Sales Orders"),
|
||||
"fieldtype": "Float",
|
||||
"width": 150
|
||||
}
|
||||
]
|
||||
columns.extend(additional_columns)
|
||||
|
||||
return columns
|
||||
|
||||
def get_open_sales_orders_map(variants):
|
||||
open_sales_orders = frappe.db.sql("""
|
||||
select
|
||||
count(*) as count,
|
||||
item_code
|
||||
from
|
||||
`tabSales Order Item`
|
||||
where
|
||||
docstatus = 1 and
|
||||
qty > ifnull(delivered_qty, 0) and
|
||||
item_code in ({variants})
|
||||
group by
|
||||
item_code
|
||||
""".format(variants=variants), as_dict=1)
|
||||
def get_open_sales_orders_count(variants_list):
|
||||
open_sales_orders = frappe.db.get_list(
|
||||
"Sales Order",
|
||||
fields=[
|
||||
"name",
|
||||
"`tabSales Order Item`.item_code"
|
||||
],
|
||||
filters=[
|
||||
["Sales Order", "docstatus", "=", 1],
|
||||
["Sales Order Item", "item_code", "in", variants_list]
|
||||
],
|
||||
distinct=1
|
||||
)
|
||||
|
||||
order_count_map = {}
|
||||
for d in open_sales_orders:
|
||||
order_count_map[d["item_code"]] = d["count"]
|
||||
for row in open_sales_orders:
|
||||
item_code = row.get("item_code")
|
||||
if order_count_map.get(item_code) is None:
|
||||
order_count_map[item_code] = 1
|
||||
else:
|
||||
order_count_map[item_code] += 1
|
||||
|
||||
return order_count_map
|
||||
|
||||
def get_stock_details_map(variants):
|
||||
stock_details = frappe.db.sql("""
|
||||
select
|
||||
sum(planned_qty) as planned_qty,
|
||||
sum(actual_qty) as actual_qty,
|
||||
sum(projected_qty) as projected_qty,
|
||||
item_code
|
||||
from
|
||||
`tabBin`
|
||||
where
|
||||
item_code in ({variants})
|
||||
group by
|
||||
item_code
|
||||
""".format(variants=variants), as_dict=1)
|
||||
def get_stock_details_map(variant_list):
|
||||
stock_details = frappe.db.get_all(
|
||||
"Bin",
|
||||
fields=[
|
||||
"sum(planned_qty) as planned_qty",
|
||||
"sum(actual_qty) as actual_qty",
|
||||
"sum(projected_qty) as projected_qty",
|
||||
"item_code",
|
||||
],
|
||||
filters={
|
||||
"item_code": ["in", variant_list]
|
||||
},
|
||||
group_by="item_code"
|
||||
)
|
||||
|
||||
stock_details_map = {}
|
||||
for d in stock_details:
|
||||
name = d["item_code"]
|
||||
for row in stock_details:
|
||||
name = row.get("item_code")
|
||||
stock_details_map[name] = {
|
||||
"Inventory" :d["actual_qty"],
|
||||
"In Production" :d["planned_qty"],
|
||||
"Available Selling" :d["projected_qty"]
|
||||
"Inventory": row.get("actual_qty"),
|
||||
"In Production": row.get("planned_qty")
|
||||
}
|
||||
|
||||
return stock_details_map
|
||||
|
||||
def get_buying_price_map(variants):
|
||||
buying = frappe.db.sql("""
|
||||
select
|
||||
avg(price_list_rate) as avg_rate,
|
||||
item_code
|
||||
from
|
||||
`tabItem Price`
|
||||
where
|
||||
item_code in ({variants}) and buying=1
|
||||
group by
|
||||
item_code
|
||||
""".format(variants=variants), as_dict=1)
|
||||
def get_buying_price_map(variant_list):
|
||||
buying = frappe.db.get_all(
|
||||
"Item Price",
|
||||
fields=[
|
||||
"avg(price_list_rate) as avg_rate",
|
||||
"item_code",
|
||||
],
|
||||
filters={
|
||||
"item_code": ["in", variant_list],
|
||||
"buying": 1
|
||||
},
|
||||
group_by="item_code"
|
||||
)
|
||||
|
||||
buying_price_map = {}
|
||||
for d in buying:
|
||||
buying_price_map[d["item_code"]] = d["avg_rate"]
|
||||
for row in buying:
|
||||
buying_price_map[row.get("item_code")] = row.get("avg_rate")
|
||||
|
||||
return buying_price_map
|
||||
|
||||
def get_selling_price_map(variants):
|
||||
selling = frappe.db.sql("""
|
||||
select
|
||||
avg(price_list_rate) as avg_rate,
|
||||
item_code
|
||||
from
|
||||
`tabItem Price`
|
||||
where
|
||||
item_code in ({variants}) and selling=1
|
||||
group by
|
||||
item_code
|
||||
""".format(variants=variants), as_dict=1)
|
||||
def get_selling_price_map(variant_list):
|
||||
selling = frappe.db.get_all(
|
||||
"Item Price",
|
||||
fields=[
|
||||
"avg(price_list_rate) as avg_rate",
|
||||
"item_code",
|
||||
],
|
||||
filters={
|
||||
"item_code": ["in", variant_list],
|
||||
"selling": 1
|
||||
},
|
||||
group_by="item_code"
|
||||
)
|
||||
|
||||
selling_price_map = {}
|
||||
for d in selling:
|
||||
selling_price_map[d["item_code"]] = d["avg_rate"]
|
||||
for row in selling:
|
||||
selling_price_map[row.get("item_code")] = row.get("avg_rate")
|
||||
|
||||
return selling_price_map
|
||||
|
||||
def get_attribute_values_map(variants):
|
||||
list_attr = frappe.db.sql("""
|
||||
select
|
||||
attribute, attribute_value, parent
|
||||
from
|
||||
`tabItem Variant Attribute`
|
||||
where
|
||||
parent in ({variants})
|
||||
""".format(variants=variants), as_dict=1)
|
||||
def get_attribute_values_map(variant_list):
|
||||
attribute_list = frappe.db.get_all(
|
||||
"Item Variant Attribute",
|
||||
fields=[
|
||||
"attribute",
|
||||
"attribute_value",
|
||||
"parent"
|
||||
],
|
||||
filters={
|
||||
"parent": ["in", variant_list]
|
||||
}
|
||||
)
|
||||
|
||||
attr_val_map = {}
|
||||
for d in list_attr:
|
||||
name = d["parent"]
|
||||
for row in attribute_list:
|
||||
name = row.get("parent")
|
||||
if not attr_val_map.get(name):
|
||||
attr_val_map[name] = {}
|
||||
|
||||
attr_val_map[name][d["attribute"]] = d["attribute_value"]
|
||||
attr_val_map[name][row.get("attribute")] = row.get("attribute_value")
|
||||
|
||||
return attr_val_map
|
||||
|
Loading…
x
Reference in New Issue
Block a user