From 4fb848d3c4e3ca7027fabd8a66e7adb4d99dd765 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Fri, 29 Nov 2013 15:15:34 +0530 Subject: [PATCH 1/3] [report] item-wise consumption in buying module --- buying/page/buying_home/buying_home.js | 5 ++ .../report/item_wise_consumption/__init__.py | 0 .../item_wise_consumption.js | 28 +++++++ .../item_wise_consumption.py | 81 +++++++++++++++++++ .../item_wise_consumption.txt | 22 +++++ 5 files changed, 136 insertions(+) create mode 100644 stock/report/item_wise_consumption/__init__.py create mode 100644 stock/report/item_wise_consumption/item_wise_consumption.js create mode 100644 stock/report/item_wise_consumption/item_wise_consumption.py create mode 100644 stock/report/item_wise_consumption/item_wise_consumption.txt diff --git a/buying/page/buying_home/buying_home.js b/buying/page/buying_home/buying_home.js index 5c5668ea31..1f2c9861a6 100644 --- a/buying/page/buying_home/buying_home.js +++ b/buying/page/buying_home/buying_home.js @@ -155,6 +155,11 @@ wn.module_page["Buying"] = [ route: "query-report/Supplier Addresses and Contacts", doctype: "Supplier" }, + { + "label":wn._("Item-Wise Consumption"), + route: "query-report/Item-wise Consumption", + doctype: "Stock Ledger Entry" + } ] } ] diff --git a/stock/report/item_wise_consumption/__init__.py b/stock/report/item_wise_consumption/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/stock/report/item_wise_consumption/item_wise_consumption.js b/stock/report/item_wise_consumption/item_wise_consumption.js new file mode 100644 index 0000000000..c967842902 --- /dev/null +++ b/stock/report/item_wise_consumption/item_wise_consumption.js @@ -0,0 +1,28 @@ +// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors +// License: GNU General Public License v3. See license.txt + +wn.query_reports["Item-wise Consumption"] = { + "filters": [ + { + "fieldname":"supplier", + "label": wn._("Supplier"), + "fieldtype": "Link", + "options": "Supplier", + "width": "80" + }, + { + "fieldname":"from_date", + "label": wn._("From Date"), + "fieldtype": "Date", + "width": "80", + "default": wn.datetime.month_start() + }, + { + "fieldname":"to_date", + "label": wn._("To Date"), + "fieldtype": "Date", + "width": "80", + "default": wn.datetime.month_end() + }, + ] +} \ No newline at end of file diff --git a/stock/report/item_wise_consumption/item_wise_consumption.py b/stock/report/item_wise_consumption/item_wise_consumption.py new file mode 100644 index 0000000000..406fcaeec1 --- /dev/null +++ b/stock/report/item_wise_consumption/item_wise_consumption.py @@ -0,0 +1,81 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import webnotes +from webnotes.utils import flt + +def execute(filters=None): + columns = get_columns(filters) + consumed_details = get_consumed_details(filters) + supplier_details = get_suppliers_details(filters) + material_transfer_vouchers = get_material_transfer_vouchers() + data = [] + + for item_code, suppliers in supplier_details.items(): + consumed_qty = consumed_amount = 0.0 + if consumed_details.get(item_code): + for cd in consumed_details.get(item_code): + if cd.voucher_no not in material_transfer_vouchers: + consumed_qty += abs(flt(cd.actual_qty)) + consumed_amount += abs(flt(cd.stock_value_difference)) + if consumed_qty or consumed_amount: + row = [cd.item_code, cd.item_name, cd.description, cd.stock_uom, \ + consumed_qty, consumed_amount, list(set(suppliers))] + data.append(row) + + return columns, data + +def get_columns(filters): + """return columns based on filters""" + + columns = ["Item:Link/Item:100"] + ["Item Name::150"] + ["Description::150"] + \ + ["UOM:Link/UOM:100"] + ["Consumed Qty:Float:130"] + ["Consumed Amount:Currency:130"] + \ + ["Supplier(s)::250"] + + return columns + +def get_conditions(filters): + conditions = "" + values = [] + + if filters.get('from_date') and filters.get('to_date'): + conditions = "and sle.posting_date>=%s and sle.posting_date<=%s" + values = [filters.get('from_date'), filters.get('to_date')] + + return conditions, values + +def get_consumed_details(filters): + conditions, values = get_conditions(filters) + consumed_details = {} + + for d in webnotes.conn.sql("""select sle.item_code, i.item_name, i.description, + i.stock_uom, sle.actual_qty, sle.stock_value_difference, sle.voucher_no + from `tabStock Ledger Entry` sle, `tabItem` i + where sle.item_code=i.name and sle.actual_qty < 0 %s""" % conditions, values, as_dict=1, debug=1): + consumed_details.setdefault(d.item_code, []).append(d) + + return consumed_details + +def get_suppliers_details(filters): + item_supplier_map = {} + conditions = "" + values = [] + + if (filters.get('supplier')): + conditions = "and pr.supplier=%s" + values = [filters.get('supplier')] + + for d in webnotes.conn.sql("""select pr.supplier, pri.item_code from + `tabPurchase Receipt` pr, `tabPurchase Receipt Item` pri + where pr.name=pri.parent and pr.docstatus=1 and + pri.item_code=(select name from `tabItem` where + ifnull(is_stock_item, 'Yes')='Yes' and name=pri.item_code) %s""" % conditions, + values, as_dict=1): + item_supplier_map.setdefault(d.item_code, []).append(d.supplier) + + return item_supplier_map + +def get_material_transfer_vouchers(): + return webnotes.conn.sql_list("""select name from `tabStock Entry` where + purpose='Material Transfer' and docstatus=1""") \ No newline at end of file diff --git a/stock/report/item_wise_consumption/item_wise_consumption.txt b/stock/report/item_wise_consumption/item_wise_consumption.txt new file mode 100644 index 0000000000..b4dd955efd --- /dev/null +++ b/stock/report/item_wise_consumption/item_wise_consumption.txt @@ -0,0 +1,22 @@ +[ + { + "creation": "2013-11-29 10:58:23", + "docstatus": 0, + "modified": "2013-11-29 12:26:49", + "modified_by": "Administrator", + "owner": "Administrator" + }, + { + "add_total_row": 1, + "doctype": "Report", + "is_standard": "Yes", + "name": "__common__", + "ref_doctype": "Stock Ledger Entry", + "report_name": "Item-wise Consumption", + "report_type": "Script Report" + }, + { + "doctype": "Report", + "name": "Item-wise Consumption" + } +] \ No newline at end of file From b1269b4a07ffd523117a0374b62d606815409fd3 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Fri, 29 Nov 2013 16:08:26 +0530 Subject: [PATCH 2/3] [report] item-wise consumption renamed to supplier-wise sales analytics --- buying/page/buying_home/buying_home.js | 4 +- .../__init__.py | 0 .../supplier_wise_sales_analytics.js} | 2 +- .../supplier_wise_sales_analytics.py} | 44 +++++++++++-------- .../supplier_wise_sales_analytics.txt} | 8 ++-- 5 files changed, 32 insertions(+), 26 deletions(-) rename stock/report/{item_wise_consumption => supplier_wise_sales_analytics}/__init__.py (100%) rename stock/report/{item_wise_consumption/item_wise_consumption.js => supplier_wise_sales_analytics/supplier_wise_sales_analytics.js} (91%) rename stock/report/{item_wise_consumption/item_wise_consumption.py => supplier_wise_sales_analytics/supplier_wise_sales_analytics.py} (64%) rename stock/report/{item_wise_consumption/item_wise_consumption.txt => supplier_wise_sales_analytics/supplier_wise_sales_analytics.txt} (63%) diff --git a/buying/page/buying_home/buying_home.js b/buying/page/buying_home/buying_home.js index 1f2c9861a6..811ed6fcf9 100644 --- a/buying/page/buying_home/buying_home.js +++ b/buying/page/buying_home/buying_home.js @@ -156,8 +156,8 @@ wn.module_page["Buying"] = [ doctype: "Supplier" }, { - "label":wn._("Item-Wise Consumption"), - route: "query-report/Item-wise Consumption", + "label":wn._("Supplier-Wise Sales Analytics"), + route: "query-report/Supplier-Wise Sales Analytics", doctype: "Stock Ledger Entry" } ] diff --git a/stock/report/item_wise_consumption/__init__.py b/stock/report/supplier_wise_sales_analytics/__init__.py similarity index 100% rename from stock/report/item_wise_consumption/__init__.py rename to stock/report/supplier_wise_sales_analytics/__init__.py diff --git a/stock/report/item_wise_consumption/item_wise_consumption.js b/stock/report/supplier_wise_sales_analytics/supplier_wise_sales_analytics.js similarity index 91% rename from stock/report/item_wise_consumption/item_wise_consumption.js rename to stock/report/supplier_wise_sales_analytics/supplier_wise_sales_analytics.js index c967842902..4384b70195 100644 --- a/stock/report/item_wise_consumption/item_wise_consumption.js +++ b/stock/report/supplier_wise_sales_analytics/supplier_wise_sales_analytics.js @@ -1,7 +1,7 @@ // Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors // License: GNU General Public License v3. See license.txt -wn.query_reports["Item-wise Consumption"] = { +wn.query_reports["Supplier-Wise Sales Analytics"] = { "filters": [ { "fieldname":"supplier", diff --git a/stock/report/item_wise_consumption/item_wise_consumption.py b/stock/report/supplier_wise_sales_analytics/supplier_wise_sales_analytics.py similarity index 64% rename from stock/report/item_wise_consumption/item_wise_consumption.py rename to stock/report/supplier_wise_sales_analytics/supplier_wise_sales_analytics.py index 406fcaeec1..144ddedad2 100644 --- a/stock/report/item_wise_consumption/item_wise_consumption.py +++ b/stock/report/supplier_wise_sales_analytics/supplier_wise_sales_analytics.py @@ -13,15 +13,22 @@ def execute(filters=None): data = [] for item_code, suppliers in supplier_details.items(): - consumed_qty = consumed_amount = 0.0 + consumed_qty = consumed_amount = delivered_qty = delivered_amount = 0.0 if consumed_details.get(item_code): for cd in consumed_details.get(item_code): - if cd.voucher_no not in material_transfer_vouchers: - consumed_qty += abs(flt(cd.actual_qty)) - consumed_amount += abs(flt(cd.stock_value_difference)) - if consumed_qty or consumed_amount: + + if (cd.voucher_no not in material_transfer_vouchers): + if cd.voucher_type=="Delivery Note": + delivered_qty += abs(flt(cd.actual_qty)) + delivered_amount += abs(flt(cd.stock_value_difference)) + elif cd.voucher_type!="Delivery Note": + consumed_qty += abs(flt(cd.actual_qty)) + consumed_amount += abs(flt(cd.stock_value_difference)) + + if consumed_qty or consumed_amount or delivered_qty or delivered_amount: row = [cd.item_code, cd.item_name, cd.description, cd.stock_uom, \ - consumed_qty, consumed_amount, list(set(suppliers))] + consumed_qty, consumed_amount, delivered_qty, delivered_amount, \ + list(set(suppliers))] data.append(row) return columns, data @@ -29,9 +36,9 @@ def execute(filters=None): def get_columns(filters): """return columns based on filters""" - columns = ["Item:Link/Item:100"] + ["Item Name::150"] + ["Description::150"] + \ - ["UOM:Link/UOM:100"] + ["Consumed Qty:Float:130"] + ["Consumed Amount:Currency:130"] + \ - ["Supplier(s)::250"] + columns = ["Item:Link/Item:100"] + ["Item Name::100"] + ["Description::150"] + \ + ["UOM:Link/UOM:70"] + ["Consumed Qty:Float:110"] + ["Consumed Amount:Currency:130"] + \ + ["Delivered Qty:Float:100"] + ["Delivered Amount:Currency:130"] + ["Supplier(s)::250"] return columns @@ -52,28 +59,27 @@ def get_consumed_details(filters): for d in webnotes.conn.sql("""select sle.item_code, i.item_name, i.description, i.stock_uom, sle.actual_qty, sle.stock_value_difference, sle.voucher_no from `tabStock Ledger Entry` sle, `tabItem` i - where sle.item_code=i.name and sle.actual_qty < 0 %s""" % conditions, values, as_dict=1, debug=1): + where sle.item_code=i.name and sle.actual_qty < 0 %s""" % conditions, values, as_dict=1): consumed_details.setdefault(d.item_code, []).append(d) return consumed_details def get_suppliers_details(filters): item_supplier_map = {} - conditions = "" - values = [] - - if (filters.get('supplier')): - conditions = "and pr.supplier=%s" - values = [filters.get('supplier')] + supplier = filters.get('supplier') for d in webnotes.conn.sql("""select pr.supplier, pri.item_code from `tabPurchase Receipt` pr, `tabPurchase Receipt Item` pri where pr.name=pri.parent and pr.docstatus=1 and pri.item_code=(select name from `tabItem` where - ifnull(is_stock_item, 'Yes')='Yes' and name=pri.item_code) %s""" % conditions, - values, as_dict=1): + ifnull(is_stock_item, 'Yes')='Yes' and name=pri.item_code)""", as_dict=1): item_supplier_map.setdefault(d.item_code, []).append(d.supplier) - + + if supplier: + for item_code, suppliers in item_supplier_map.items(): + if supplier not in suppliers: + del item_supplier_map[item_code] + return item_supplier_map def get_material_transfer_vouchers(): diff --git a/stock/report/item_wise_consumption/item_wise_consumption.txt b/stock/report/supplier_wise_sales_analytics/supplier_wise_sales_analytics.txt similarity index 63% rename from stock/report/item_wise_consumption/item_wise_consumption.txt rename to stock/report/supplier_wise_sales_analytics/supplier_wise_sales_analytics.txt index b4dd955efd..936292c2d9 100644 --- a/stock/report/item_wise_consumption/item_wise_consumption.txt +++ b/stock/report/supplier_wise_sales_analytics/supplier_wise_sales_analytics.txt @@ -1,8 +1,8 @@ [ { - "creation": "2013-11-29 10:58:23", + "creation": "2013-11-29 15:45:39", "docstatus": 0, - "modified": "2013-11-29 12:26:49", + "modified": "2013-11-29 15:45:40", "modified_by": "Administrator", "owner": "Administrator" }, @@ -12,11 +12,11 @@ "is_standard": "Yes", "name": "__common__", "ref_doctype": "Stock Ledger Entry", - "report_name": "Item-wise Consumption", + "report_name": "Supplier-Wise Sales Analytics", "report_type": "Script Report" }, { "doctype": "Report", - "name": "Item-wise Consumption" + "name": "Supplier-Wise Sales Analytics" } ] \ No newline at end of file From be948b8b40d78f49464302aa7b8069ec5a9f4160 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Fri, 29 Nov 2013 16:37:07 +0530 Subject: [PATCH 3/3] [fix] [minor] supplier wise sales analytics report totals added --- .../supplier_wise_sales_analytics.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/stock/report/supplier_wise_sales_analytics/supplier_wise_sales_analytics.py b/stock/report/supplier_wise_sales_analytics/supplier_wise_sales_analytics.py index 144ddedad2..254bd90660 100644 --- a/stock/report/supplier_wise_sales_analytics/supplier_wise_sales_analytics.py +++ b/stock/report/supplier_wise_sales_analytics/supplier_wise_sales_analytics.py @@ -14,6 +14,7 @@ def execute(filters=None): for item_code, suppliers in supplier_details.items(): consumed_qty = consumed_amount = delivered_qty = delivered_amount = 0.0 + total_qty = total_amount = 0.0 if consumed_details.get(item_code): for cd in consumed_details.get(item_code): @@ -26,9 +27,12 @@ def execute(filters=None): consumed_amount += abs(flt(cd.stock_value_difference)) if consumed_qty or consumed_amount or delivered_qty or delivered_amount: + total_qty += delivered_qty + consumed_qty + total_amount += delivered_amount + consumed_amount + row = [cd.item_code, cd.item_name, cd.description, cd.stock_uom, \ consumed_qty, consumed_amount, delivered_qty, delivered_amount, \ - list(set(suppliers))] + total_qty, total_amount, list(set(suppliers))] data.append(row) return columns, data @@ -36,9 +40,12 @@ def execute(filters=None): def get_columns(filters): """return columns based on filters""" - columns = ["Item:Link/Item:100"] + ["Item Name::100"] + ["Description::150"] + \ - ["UOM:Link/UOM:70"] + ["Consumed Qty:Float:110"] + ["Consumed Amount:Currency:130"] + \ - ["Delivered Qty:Float:100"] + ["Delivered Amount:Currency:130"] + ["Supplier(s)::250"] + columns = ["Item:Link/Item:100"] + ["Item Name::100"] + \ + ["Description::150"] + ["UOM:Link/UOM:90"] + \ + ["Consumed Qty:Float:110"] + ["Consumed Amount:Currency:130"] + \ + ["Delivered Qty:Float:110"] + ["Delivered Amount:Currency:130"] + \ + ["Total Qty:Float:110"] + ["Total Amount:Currency:130"] + \ + ["Supplier(s)::250"] return columns @@ -57,7 +64,8 @@ def get_consumed_details(filters): consumed_details = {} for d in webnotes.conn.sql("""select sle.item_code, i.item_name, i.description, - i.stock_uom, sle.actual_qty, sle.stock_value_difference, sle.voucher_no + i.stock_uom, sle.actual_qty, sle.stock_value_difference, + sle.voucher_no, sle.voucher_type from `tabStock Ledger Entry` sle, `tabItem` i where sle.item_code=i.name and sle.actual_qty < 0 %s""" % conditions, values, as_dict=1): consumed_details.setdefault(d.item_code, []).append(d)