feat: Supplier Quotation Comparison - v3
This commit is contained in:
parent
59d20c7d2c
commit
59239172a1
@ -1,32 +0,0 @@
|
|||||||
{
|
|
||||||
"add_total_row": 0,
|
|
||||||
"apply_user_permissions": 1,
|
|
||||||
"creation": "2016-07-21 08:31:05.890362",
|
|
||||||
"disabled": 0,
|
|
||||||
"docstatus": 0,
|
|
||||||
"doctype": "Report",
|
|
||||||
"idx": 2,
|
|
||||||
"is_standard": "Yes",
|
|
||||||
"modified": "2017-02-24 20:04:58.784351",
|
|
||||||
"modified_by": "Administrator",
|
|
||||||
"module": "Buying",
|
|
||||||
"name": "Quoted Item Comparison",
|
|
||||||
"owner": "Administrator",
|
|
||||||
"ref_doctype": "Supplier Quotation",
|
|
||||||
"report_name": "Quoted Item Comparison",
|
|
||||||
"report_type": "Script Report",
|
|
||||||
"roles": [
|
|
||||||
{
|
|
||||||
"role": "Manufacturing Manager"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"role": "Purchase Manager"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"role": "Purchase User"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"role": "Stock User"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
@ -1,7 +1,7 @@
|
|||||||
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
// For license information, please see license.txt
|
// For license information, please see license.txt
|
||||||
|
|
||||||
frappe.query_reports["Quoted Item Comparison"] = {
|
frappe.query_reports["Supplier Quotation Comparison"] = {
|
||||||
filters: [
|
filters: [
|
||||||
{
|
{
|
||||||
fieldtype: "Link",
|
fieldtype: "Link",
|
||||||
@ -78,6 +78,13 @@ frappe.query_reports["Quoted Item Comparison"] = {
|
|||||||
return { filters: { "docstatus": ["<", 2] } }
|
return { filters: { "docstatus": ["<", 2] } }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"fieldname":"group_by",
|
||||||
|
"label": __("Group by"),
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"options": [__("Group by Supplier"), __("Group by Item")],
|
||||||
|
"default": __("Group by Supplier")
|
||||||
|
},
|
||||||
{
|
{
|
||||||
fieldtype: "Check",
|
fieldtype: "Check",
|
||||||
label: __("Include Expired"),
|
label: __("Include Expired"),
|
||||||
@ -98,6 +105,9 @@ frappe.query_reports["Quoted Item Comparison"] = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(column.fieldname === "price_per_unit" && data.price_per_unit && data.min && data.min === 1){
|
||||||
|
value = `<div style="color:green">${value}</div>`;
|
||||||
|
}
|
||||||
return value;
|
return value;
|
||||||
},
|
},
|
||||||
|
|
@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"add_total_row": 0,
|
||||||
|
"apply_user_permissions": 1,
|
||||||
|
"creation": "2016-07-21 08:31:05.890362",
|
||||||
|
"disabled": 0,
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Report",
|
||||||
|
"idx": 2,
|
||||||
|
"is_standard": "Yes",
|
||||||
|
"modified": "2017-02-24 20:04:58.784351",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Buying",
|
||||||
|
"name": "Supplier Quotation Comparison",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"ref_doctype": "Supplier Quotation",
|
||||||
|
"report_name": "Supplier Quotation Comparison",
|
||||||
|
"report_type": "Script Report",
|
||||||
|
"roles": [
|
||||||
|
{
|
||||||
|
"role": "Manufacturing Manager"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "Purchase Manager"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "Purchase User"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "Stock User"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -12,9 +12,9 @@ def execute(filters=None):
|
|||||||
if not filters:
|
if not filters:
|
||||||
return [], []
|
return [], []
|
||||||
|
|
||||||
|
columns = get_columns(filters)
|
||||||
conditions = get_conditions(filters)
|
conditions = get_conditions(filters)
|
||||||
supplier_quotation_data = get_data(filters, conditions)
|
supplier_quotation_data = get_data(filters, conditions)
|
||||||
columns = get_columns()
|
|
||||||
|
|
||||||
data, chart_data = prepare_data(supplier_quotation_data, filters)
|
data, chart_data = prepare_data(supplier_quotation_data, filters)
|
||||||
message = get_message()
|
message = get_message()
|
||||||
@ -41,9 +41,13 @@ def get_conditions(filters):
|
|||||||
return conditions
|
return conditions
|
||||||
|
|
||||||
def get_data(filters, conditions):
|
def get_data(filters, conditions):
|
||||||
supplier_quotation_data = frappe.db.sql("""SELECT
|
supplier_quotation_data = frappe.db.sql("""
|
||||||
sqi.parent, sqi.item_code, sqi.qty, sqi.rate, sqi.uom, sqi.request_for_quotation,
|
SELECT
|
||||||
sqi.lead_time_days, sq.supplier, sq.valid_till
|
sqi.parent, sqi.item_code,
|
||||||
|
sqi.qty, sqi.stock_qty, sqi.rate,
|
||||||
|
sqi.uom, sqi.stock_uom,
|
||||||
|
sqi.request_for_quotation,
|
||||||
|
sqi.lead_time_days, sq.supplier as supplier_name, sq.valid_till
|
||||||
FROM
|
FROM
|
||||||
`tabSupplier Quotation Item` sqi,
|
`tabSupplier Quotation Item` sqi,
|
||||||
`tabSupplier Quotation` sq
|
`tabSupplier Quotation` sq
|
||||||
@ -58,16 +62,18 @@ def get_data(filters, conditions):
|
|||||||
return supplier_quotation_data
|
return supplier_quotation_data
|
||||||
|
|
||||||
def prepare_data(supplier_quotation_data, filters):
|
def prepare_data(supplier_quotation_data, filters):
|
||||||
out, suppliers, qty_list, chart_data = [], [], [], []
|
out, groups, qty_list, suppliers, chart_data = [], [], [], [], []
|
||||||
supplier_wise_map = defaultdict(list)
|
group_wise_map = defaultdict(list)
|
||||||
supplier_qty_price_map = {}
|
supplier_qty_price_map = {}
|
||||||
|
|
||||||
|
group_by_field = "supplier_name" if filters.get("group_by") == "Group by Supplier" else "item_code"
|
||||||
company_currency = frappe.db.get_default("currency")
|
company_currency = frappe.db.get_default("currency")
|
||||||
float_precision = cint(frappe.db.get_default("float_precision")) or 2
|
float_precision = cint(frappe.db.get_default("float_precision")) or 2
|
||||||
|
|
||||||
for data in supplier_quotation_data:
|
for data in supplier_quotation_data:
|
||||||
supplier = data.get("supplier")
|
group = data.get(group_by_field) # get item or supplier value for this row
|
||||||
supplier_currency = frappe.db.get_value("Supplier", data.get("supplier"), "default_currency")
|
|
||||||
|
supplier_currency = frappe.db.get_value("Supplier", data.get("supplier_name"), "default_currency")
|
||||||
|
|
||||||
if supplier_currency:
|
if supplier_currency:
|
||||||
exchange_rate = get_exchange_rate(supplier_currency, company_currency)
|
exchange_rate = get_exchange_rate(supplier_currency, company_currency)
|
||||||
@ -75,38 +81,55 @@ def prepare_data(supplier_quotation_data, filters):
|
|||||||
exchange_rate = 1
|
exchange_rate = 1
|
||||||
|
|
||||||
row = {
|
row = {
|
||||||
"item_code": data.get('item_code'),
|
"item_code": "" if group_by_field=="item_code" else data.get("item_code"), # leave blank if group by field
|
||||||
|
"supplier_name": "" if group_by_field=="supplier_name" else data.get("supplier_name"),
|
||||||
"quotation": data.get("parent"),
|
"quotation": data.get("parent"),
|
||||||
"qty": data.get("qty"),
|
"qty": data.get("qty"),
|
||||||
"price": flt(data.get("rate") * exchange_rate, float_precision),
|
"price": flt(data.get("rate") * exchange_rate, float_precision),
|
||||||
"uom": data.get("uom"),
|
"uom": data.get("uom"),
|
||||||
|
"stock_uom": data.get('stock_uom'),
|
||||||
"request_for_quotation": data.get("request_for_quotation"),
|
"request_for_quotation": data.get("request_for_quotation"),
|
||||||
"valid_till": data.get('valid_till'),
|
"valid_till": data.get('valid_till'),
|
||||||
"lead_time_days": data.get('lead_time_days')
|
"lead_time_days": data.get('lead_time_days')
|
||||||
}
|
}
|
||||||
|
row["price_per_unit"] = flt(row["price"]) / (flt(data.get("stock_qty")) or 1)
|
||||||
|
|
||||||
# map for report view of form {'supplier1':[{},{},...]}
|
# map for report view of form {'supplier1'/'item1':[{},{},...]}
|
||||||
supplier_wise_map[supplier].append(row)
|
group_wise_map[group].append(row)
|
||||||
|
|
||||||
# map for chart preparation of the form {'supplier1': {'qty': 'price'}}
|
# map for chart preparation of the form {'supplier1': {'qty': 'price'}}
|
||||||
|
supplier = data.get("supplier_name")
|
||||||
if filters.get("item_code"):
|
if filters.get("item_code"):
|
||||||
if not supplier in supplier_qty_price_map:
|
if not supplier in supplier_qty_price_map:
|
||||||
supplier_qty_price_map[supplier] = {}
|
supplier_qty_price_map[supplier] = {}
|
||||||
supplier_qty_price_map[supplier][row["qty"]] = row["price"]
|
supplier_qty_price_map[supplier][row["qty"]] = row["price"]
|
||||||
|
|
||||||
|
groups.append(group)
|
||||||
suppliers.append(supplier)
|
suppliers.append(supplier)
|
||||||
qty_list.append(data.get("qty"))
|
qty_list.append(data.get("qty"))
|
||||||
|
|
||||||
|
groups = list(set(groups))
|
||||||
suppliers = list(set(suppliers))
|
suppliers = list(set(suppliers))
|
||||||
qty_list = list(set(qty_list))
|
qty_list = list(set(qty_list))
|
||||||
|
|
||||||
|
highlight_min_price = group_by_field == "item_code"
|
||||||
|
|
||||||
# final data format for report view
|
# final data format for report view
|
||||||
for supplier in suppliers:
|
for group in groups:
|
||||||
supplier_wise_map[supplier][0].update({"supplier_name": supplier})
|
group_entries = group_wise_map[group] # all entries pertaining to item/supplier
|
||||||
for entry in supplier_wise_map[supplier]:
|
group_entries[0].update({group_by_field : group})
|
||||||
|
|
||||||
|
if highlight_min_price:
|
||||||
|
prices = [group_entry["price_per_unit"] for group_entry in group_entries]
|
||||||
|
min_price = min(prices)
|
||||||
|
|
||||||
|
for entry in group_entries:
|
||||||
|
if highlight_min_price and entry["price_per_unit"] == min_price:
|
||||||
|
entry["min"] = 1
|
||||||
out.append(entry)
|
out.append(entry)
|
||||||
|
|
||||||
if filters.get("item_code"):
|
if filters.get("item_code"):
|
||||||
|
# render chart only for one item comparison
|
||||||
chart_data = prepare_chart_data(suppliers, qty_list, supplier_qty_price_map)
|
chart_data = prepare_chart_data(suppliers, qty_list, supplier_qty_price_map)
|
||||||
|
|
||||||
return out, chart_data
|
return out, chart_data
|
||||||
@ -145,8 +168,9 @@ def prepare_chart_data(suppliers, qty_list, supplier_qty_price_map):
|
|||||||
|
|
||||||
return chart_data
|
return chart_data
|
||||||
|
|
||||||
def get_columns():
|
def get_columns(filters):
|
||||||
columns = [{
|
group_by_columns = [
|
||||||
|
{
|
||||||
"fieldname": "supplier_name",
|
"fieldname": "supplier_name",
|
||||||
"label": _("Supplier"),
|
"label": _("Supplier"),
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
@ -158,8 +182,10 @@ def get_columns():
|
|||||||
"label": _("Item"),
|
"label": _("Item"),
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"options": "Item",
|
"options": "Item",
|
||||||
"width": 200
|
"width": 150
|
||||||
},
|
}]
|
||||||
|
|
||||||
|
columns = [
|
||||||
{
|
{
|
||||||
"fieldname": "uom",
|
"fieldname": "uom",
|
||||||
"label": _("UOM"),
|
"label": _("UOM"),
|
||||||
@ -180,6 +206,20 @@ def get_columns():
|
|||||||
"options": "Company:company:default_currency",
|
"options": "Company:company:default_currency",
|
||||||
"width": 110
|
"width": 110
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "stock_uom",
|
||||||
|
"label": _("Stock UOM"),
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "UOM",
|
||||||
|
"width": 90
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "price_per_unit",
|
||||||
|
"label": _("Price per Unit (Stock UOM)"),
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"options": "Company:company:default_currency",
|
||||||
|
"width": 120
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "quotation",
|
"fieldname": "quotation",
|
||||||
"label": _("Supplier Quotation"),
|
"label": _("Supplier Quotation"),
|
||||||
@ -205,9 +245,12 @@ def get_columns():
|
|||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"options": "Request for Quotation",
|
"options": "Request for Quotation",
|
||||||
"width": 150
|
"width": 150
|
||||||
}
|
}]
|
||||||
]
|
|
||||||
|
|
||||||
|
if filters.get("group_by") == "Group by Item":
|
||||||
|
group_by_columns.reverse()
|
||||||
|
|
||||||
|
columns[0:0] = group_by_columns # add positioned group by columns to the report
|
||||||
return columns
|
return columns
|
||||||
|
|
||||||
def get_message():
|
def get_message():
|
Loading…
x
Reference in New Issue
Block a user