From 021acd0a0113a8a46013d8766cd50f45f3009977 Mon Sep 17 00:00:00 2001 From: marination Date: Thu, 14 May 2020 13:20:43 +0530 Subject: [PATCH 1/8] chore: Stock Ageing and Item Shortage Reports with Charts --- .../item_shortage_report.js | 26 +++ .../item_shortage_report.json | 41 ++--- .../item_shortage_report.py | 162 ++++++++++++++++++ .../stock/report/stock_ageing/stock_ageing.py | 32 +++- 4 files changed, 240 insertions(+), 21 deletions(-) create mode 100644 erpnext/stock/report/item_shortage_report/item_shortage_report.js create mode 100644 erpnext/stock/report/item_shortage_report/item_shortage_report.py diff --git a/erpnext/stock/report/item_shortage_report/item_shortage_report.js b/erpnext/stock/report/item_shortage_report/item_shortage_report.js new file mode 100644 index 0000000000..ca42a331e9 --- /dev/null +++ b/erpnext/stock/report/item_shortage_report/item_shortage_report.js @@ -0,0 +1,26 @@ +// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt +/* eslint-disable */ + +frappe.query_reports["Item Shortage Report"] = { + "filters": [ + { + "fieldname": "company", + "label": __("Company"), + "fieldtype": "Link", + "width": "80", + "options": "Company", + "reqd": 1, + "default": frappe.defaults.get_default("company") + }, + { + "fieldname": "warehouse", + "label": __("Warehouse"), + "fieldtype": "MultiSelectList", + "width": "100", + get_data: function(txt) { + return frappe.db.get_link_options('Warehouse', txt); + } + } + ] +}; diff --git a/erpnext/stock/report/item_shortage_report/item_shortage_report.json b/erpnext/stock/report/item_shortage_report/item_shortage_report.json index 577a8530b7..17285c09de 100644 --- a/erpnext/stock/report/item_shortage_report/item_shortage_report.json +++ b/erpnext/stock/report/item_shortage_report/item_shortage_report.json @@ -1,29 +1,30 @@ { - "add_total_row": 0, - "apply_user_permissions": 1, - "creation": "2013-08-20 13:43:30", - "disabled": 0, - "docstatus": 0, - "doctype": "Report", - "idx": 3, - "is_standard": "Yes", - "json": "{\"add_total_row\": 0, \"sort_by\": \"Bin.projected_qty\", \"sort_order\": \"asc\", \"sort_by_next\": \"\", \"filters\": [[\"Bin\", \"projected_qty\", \"<\", \"0\"]], \"sort_order_next\": \"desc\", \"columns\": [[\"warehouse\", \"Bin\"], [\"item_code\", \"Bin\"], [\"actual_qty\", \"Bin\"], [\"ordered_qty\", \"Bin\"], [\"planned_qty\", \"Bin\"], [\"reserved_qty\", \"Bin\"], [\"projected_qty\", \"Bin\"]]}", - "modified": "2017-02-24 20:00:46.439935", - "modified_by": "Administrator", - "module": "Stock", - "name": "Item Shortage Report", - "owner": "Administrator", - "query": "SELECT bin.warehouse as \"Warehouse:Link/Warehouse:150\",\n\tbin.item_code as \"Item Code:Link/Item:100\",\n\tbin.actual_qty as \"Actual Quantity:Float:120\",\n\tbin.ordered_qty as \"Ordered Quantity:Float:120\",\n\tbin.planned_qty as \"Planned Quantity:Float:120\",\n\tbin.reserved_qty as \"Reserved Quantity:Float:120\",\n\tbin.projected_qty as \"Project Quantity:Float:120\",\n\titem.item_name as \"Item Name:Data:150\",\n\titem.description as \"Description::200\"\nFROM tabBin as bin\nINNER JOIN tabItem as item\nON bin.item_code=item.name\nWHERE bin.projected_qty<0\nORDER BY bin.projected_qty;", - "ref_doctype": "Bin", - "report_name": "Item Shortage Report", - "report_type": "Query Report", + "add_total_row": 0, + "creation": "2013-08-20 13:43:30", + "disable_prepared_report": 0, + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "idx": 3, + "is_standard": "Yes", + "json": "{\"add_total_row\": 0, \"sort_by\": \"Bin.projected_qty\", \"sort_order\": \"asc\", \"sort_by_next\": \"\", \"filters\": [[\"Bin\", \"projected_qty\", \"<\", \"0\"]], \"sort_order_next\": \"desc\", \"columns\": [[\"warehouse\", \"Bin\"], [\"item_code\", \"Bin\"], [\"actual_qty\", \"Bin\"], [\"ordered_qty\", \"Bin\"], [\"planned_qty\", \"Bin\"], [\"reserved_qty\", \"Bin\"], [\"projected_qty\", \"Bin\"]]}", + "modified": "2020-05-14 12:32:07.158991", + "modified_by": "Administrator", + "module": "Stock", + "name": "Item Shortage Report", + "owner": "Administrator", + "prepared_report": 0, + "query": "", + "ref_doctype": "Bin", + "report_name": "Item Shortage Report", + "report_type": "Script Report", "roles": [ { "role": "Sales User" - }, + }, { "role": "Purchase User" - }, + }, { "role": "Stock User" } diff --git a/erpnext/stock/report/item_shortage_report/item_shortage_report.py b/erpnext/stock/report/item_shortage_report/item_shortage_report.py new file mode 100644 index 0000000000..07749ebec5 --- /dev/null +++ b/erpnext/stock/report/item_shortage_report/item_shortage_report.py @@ -0,0 +1,162 @@ +# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +import frappe +from frappe import _ + +def execute(filters=None): + columns = get_columns() + conditions = get_conditions(filters) + data = get_data(conditions, filters) + + if not data: + return [], [] + + chart_data = get_chart_data(data) + + return columns, data, None, chart_data + +def get_conditions(filters): + conditions = "" + + if filters.get("warehouse"): + conditions += "AND warehouse in %(warehouse)s" + if filters.get("company"): + conditions += "AND company = %(company)s" + + return conditions + +def get_data(conditions, filters): + data = frappe.db.sql(""" + SELECT + bin.warehouse, + bin.item_code, + bin.actual_qty , + bin.ordered_qty , + bin.planned_qty , + bin.reserved_qty , + bin.reserved_qty_for_production, + bin.projected_qty , + warehouse.company, + item.item_name , + item.description + FROM + `tabBin` bin, + `tabWarehouse` warehouse, + `tabItem` item + WHERE + bin.projected_qty<0 + AND warehouse.name = bin.warehouse + AND bin.item_code=item.name + {0} + ORDER BY bin.projected_qty;""".format(conditions), filters, as_dict=1) + + return data + +def get_chart_data(data): + labels, datapoints = [], [] + + for row in data: + labels.append(row.get("item_code")) + datapoints.append(row.get("projected_qty")) + + if len(data) > 10: + labels = labels[:10] + datapoints = datapoints[:10] + + return { + "data": { + "labels": labels, + "datasets":[ + { + "name": _("Projected Qty"), + "values": datapoints + } + ] + }, + "type": "bar" + } + +def get_columns(): + columns = [ + { + "label": _("Warehouse"), + "fieldname": "warehouse", + "fieldtype": "Link", + "options": "Warehouse", + "width": 150 + }, + { + "label": _("Item"), + "fieldname": "item_code", + "fieldtype": "Link", + "options": "Item", + "width": 150 + }, + { + "label": _("Actual Quantity"), + "fieldname": "actual_qty", + "fieldtype": "Float", + "width": 120, + "convertible": "qty" + }, + { + "label": _("Ordered Quantity"), + "fieldname": "ordered_qty", + "fieldtype": "Float", + "width": 120, + "convertible": "qty" + }, + { + "label": _("Planned Quantity"), + "fieldname": "planned_qty", + "fieldtype": "Float", + "width": 120, + "convertible": "qty" + }, + { + "label": _("Reserved Quantity"), + "fieldname": "reserved_qty", + "fieldtype": "Float", + "width": 120, + "convertible": "qty" + }, + { + "label": _("Reserved Quantity for Production"), + "fieldname": "reserved_qty_for_production", + "fieldtype": "Float", + "width": 120, + "convertible": "qty" + }, + { + "label": _("Projected Quantity"), + "fieldname": "projected_qty", + "fieldtype": "Float", + "width": 120, + "convertible": "qty" + }, + { + "label": _("Company"), + "fieldname": "company", + "fieldtype": "Link", + "options": "Company", + "width": 120 + }, + { + "label": _("Item Name"), + "fieldname": "item_name", + "fieldtype": "Data", + "width": 100 + }, + { + "label": _("Description"), + "fieldname": "description", + "fieldtype": "Data", + "width": 120 + } + ] + + return columns + + diff --git a/erpnext/stock/report/stock_ageing/stock_ageing.py b/erpnext/stock/report/stock_ageing/stock_ageing.py index 803a5c81a3..4ce967d972 100644 --- a/erpnext/stock/report/stock_ageing/stock_ageing.py +++ b/erpnext/stock/report/stock_ageing/stock_ageing.py @@ -37,7 +37,9 @@ def execute(filters=None): data.append(row) - return columns, data + chart_data = get_chart_data(data, filters) + + return columns, data, None, chart_data def get_average_age(fifo_queue, to_date): batch_age = age_qty = total_qty = 0.0 @@ -230,3 +232,31 @@ def get_sle_conditions(filters): where wh.lft >= {0} and rgt <= {1})""".format(lft, rgt)) return "and {}".format(" and ".join(conditions)) if conditions else "" + +def get_chart_data(data, filters): + labels, datapoints = [], [] + + if filters.get("show_warehouse_wise_stock"): + return {} + + if len(data) > 10: + data = data[:10] + + for row in data: + labels.append(row[0]) + datapoints.append(row[6]) + + print(labels) + print(datapoints) + return { + "data" : { + "labels": labels, + "datasets": [ + { + "name": _("Average Age"), + "values": datapoints + } + ] + }, + "type" : "bar" + } \ No newline at end of file From 10bd2417ff9d01866e48cf2569532903c2e3dfb6 Mon Sep 17 00:00:00 2001 From: marination Date: Thu, 14 May 2020 15:35:18 +0530 Subject: [PATCH 2/8] feat: Custom Dashboard 'Warehouse wise Stock Value' with Chart Source --- .../stock/dashboard_chart_source/__init__.py | 0 .../warehouse_wise_stock_value/__init__.py | 0 .../warehouse_wise_stock_value.js | 14 ++++++ .../warehouse_wise_stock_value.json | 13 ++++++ .../warehouse_wise_stock_value.py | 44 +++++++++++++++++++ .../stock/report/stock_ageing/stock_ageing.py | 2 - 6 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 erpnext/stock/dashboard_chart_source/__init__.py create mode 100644 erpnext/stock/dashboard_chart_source/warehouse_wise_stock_value/__init__.py create mode 100644 erpnext/stock/dashboard_chart_source/warehouse_wise_stock_value/warehouse_wise_stock_value.js create mode 100644 erpnext/stock/dashboard_chart_source/warehouse_wise_stock_value/warehouse_wise_stock_value.json create mode 100644 erpnext/stock/dashboard_chart_source/warehouse_wise_stock_value/warehouse_wise_stock_value.py diff --git a/erpnext/stock/dashboard_chart_source/__init__.py b/erpnext/stock/dashboard_chart_source/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/stock/dashboard_chart_source/warehouse_wise_stock_value/__init__.py b/erpnext/stock/dashboard_chart_source/warehouse_wise_stock_value/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/stock/dashboard_chart_source/warehouse_wise_stock_value/warehouse_wise_stock_value.js b/erpnext/stock/dashboard_chart_source/warehouse_wise_stock_value/warehouse_wise_stock_value.js new file mode 100644 index 0000000000..a4137547f7 --- /dev/null +++ b/erpnext/stock/dashboard_chart_source/warehouse_wise_stock_value/warehouse_wise_stock_value.js @@ -0,0 +1,14 @@ +frappe.provide('frappe.dashboards.chart_sources'); + +frappe.dashboards.chart_sources["Warehouse wise Stock Value"] = { + method: "erpnext.stock.dashboard_chart_source.warehouse_wise_stock_value.warehouse_wise_stock_value.get", + filters: [ + { + fieldname: "company", + label: __("Company"), + fieldtype: "Link", + options: "Company", + default: frappe.defaults.get_user_default("Company") + } + ] +}; \ No newline at end of file diff --git a/erpnext/stock/dashboard_chart_source/warehouse_wise_stock_value/warehouse_wise_stock_value.json b/erpnext/stock/dashboard_chart_source/warehouse_wise_stock_value/warehouse_wise_stock_value.json new file mode 100644 index 0000000000..6d967c0fc0 --- /dev/null +++ b/erpnext/stock/dashboard_chart_source/warehouse_wise_stock_value/warehouse_wise_stock_value.json @@ -0,0 +1,13 @@ +{ + "creation": "2020-05-14 14:27:44.108017", + "docstatus": 0, + "doctype": "Dashboard Chart Source", + "idx": 0, + "modified": "2020-05-14 14:27:44.108017", + "modified_by": "Administrator", + "module": "Stock", + "name": "Warehouse wise Stock Value", + "owner": "Administrator", + "source_name": "Warehouse wise Stock Value ", + "timeseries": 0 +} \ No newline at end of file diff --git a/erpnext/stock/dashboard_chart_source/warehouse_wise_stock_value/warehouse_wise_stock_value.py b/erpnext/stock/dashboard_chart_source/warehouse_wise_stock_value/warehouse_wise_stock_value.py new file mode 100644 index 0000000000..0ee0a6cc77 --- /dev/null +++ b/erpnext/stock/dashboard_chart_source/warehouse_wise_stock_value/warehouse_wise_stock_value.py @@ -0,0 +1,44 @@ +# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import frappe, json +from frappe import _ +from frappe.utils.dashboard import cache_source +from erpnext.stock.utils import get_stock_value_from_bin + +@frappe.whitelist() +@cache_source +def get(chart_name = None, chart = None, no_cache = None, filters = None, from_date = None, + to_date = None, timespan = None, time_interval = None): + labels, datapoints = [], [] + filters = frappe.parse_json(filters) + + warehouse_filters = [['is_group', '=', 0]] + if filters and filters.get("company"): + warehouse_filters.append(['company', '=', filters.get("company")]) + + warehouses = frappe.get_list("Warehouse", fields=['name'], filters=warehouse_filters, order_by='name') + + for wh in warehouses: + balance = get_stock_value_from_bin(warehouse=wh.name) + wh["balance"] = balance[0][0] + + warehouses = [x for x in warehouses if not (x.get('balance') == None)] + sorted_warehouse_map = sorted(warehouses, key = lambda i: i['balance'],reverse=True) + + if len(sorted_warehouse_map) > 10: + sorted_warehouse_map = sorted_warehouse_map[:10] + + for warehouse in sorted_warehouse_map: + labels.append(_(warehouse.get("name"))) + datapoints.append(warehouse.get("balance")) + + return{ + "labels": labels, + "datasets": [{ + "name": _("Stock Value"), + "values": datapoints + }], + "type": "bar" + } \ No newline at end of file diff --git a/erpnext/stock/report/stock_ageing/stock_ageing.py b/erpnext/stock/report/stock_ageing/stock_ageing.py index 4ce967d972..48f22c2c24 100644 --- a/erpnext/stock/report/stock_ageing/stock_ageing.py +++ b/erpnext/stock/report/stock_ageing/stock_ageing.py @@ -246,8 +246,6 @@ def get_chart_data(data, filters): labels.append(row[0]) datapoints.append(row[6]) - print(labels) - print(datapoints) return { "data" : { "labels": labels, From bb95cd5fd83ea5572940eed4ffde94891065589d Mon Sep 17 00:00:00 2001 From: marination Date: Fri, 15 May 2020 01:33:43 +0530 Subject: [PATCH 3/8] chore: Added Dynamic Charts to DN and PR Trends Reports --- erpnext/public/js/purchase_trends_filters.js | 5 ++- erpnext/public/js/sales_trends_filters.js | 5 ++- .../warehouse_wise_stock_value.py | 2 +- .../delivery_note_trends.py | 31 +++++++++++++++++-- .../purchase_receipt_trends.py | 30 +++++++++++++++++- 5 files changed, 67 insertions(+), 6 deletions(-) diff --git a/erpnext/public/js/purchase_trends_filters.js b/erpnext/public/js/purchase_trends_filters.js index cd767f5d16..d95507b7d1 100644 --- a/erpnext/public/js/purchase_trends_filters.js +++ b/erpnext/public/js/purchase_trends_filters.js @@ -51,7 +51,10 @@ erpnext.get_purchase_trends_filters = function() { { "value": "Supplier Group", "label": __("Supplier Group") }, { "value": "Project", "label": __("Project") } ], - "default": "Item" + "default": "Item", + "dashboard_config": { + "read_only": 1, + } }, { "fieldname":"group_by", diff --git a/erpnext/public/js/sales_trends_filters.js b/erpnext/public/js/sales_trends_filters.js index b272fdd5fb..b9c4dca913 100644 --- a/erpnext/public/js/sales_trends_filters.js +++ b/erpnext/public/js/sales_trends_filters.js @@ -27,7 +27,10 @@ erpnext.get_sales_trends_filters = function() { { "value": "Territory", "label": __("Territory") }, { "value": "Project", "label": __("Project") } ], - "default": "Item" + "default": "Item", + "dashboard_config": { + "read_only": 1, + } }, { "fieldname":"group_by", diff --git a/erpnext/stock/dashboard_chart_source/warehouse_wise_stock_value/warehouse_wise_stock_value.py b/erpnext/stock/dashboard_chart_source/warehouse_wise_stock_value/warehouse_wise_stock_value.py index 0ee0a6cc77..da2f9350c6 100644 --- a/erpnext/stock/dashboard_chart_source/warehouse_wise_stock_value/warehouse_wise_stock_value.py +++ b/erpnext/stock/dashboard_chart_source/warehouse_wise_stock_value/warehouse_wise_stock_value.py @@ -10,7 +10,7 @@ from erpnext.stock.utils import get_stock_value_from_bin @frappe.whitelist() @cache_source def get(chart_name = None, chart = None, no_cache = None, filters = None, from_date = None, - to_date = None, timespan = None, time_interval = None): + to_date = None, timespan = None, time_interval = None, heatmap_year = None): labels, datapoints = [], [] filters = frappe.parse_json(filters) diff --git a/erpnext/stock/report/delivery_note_trends/delivery_note_trends.py b/erpnext/stock/report/delivery_note_trends/delivery_note_trends.py index 27cf6b66cc..2108b51afc 100644 --- a/erpnext/stock/report/delivery_note_trends/delivery_note_trends.py +++ b/erpnext/stock/report/delivery_note_trends/delivery_note_trends.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals import frappe +from frappe import _ from erpnext.controllers.trends import get_columns,get_data def execute(filters=None): @@ -10,5 +11,31 @@ def execute(filters=None): data = [] conditions = get_columns(filters, "Delivery Note") data = get_data(filters, conditions) - - return conditions["columns"], data \ No newline at end of file + + chart_data = get_chart_data(data) + + return conditions["columns"], data, None, chart_data + +def get_chart_data(data): + labels, datapoints = [], [] + + if len(data) > 10: + data = sorted(data, key = lambda i: i[-1],reverse=True) + data = data[:10] + + for row in data: + labels.append(row[0]) + datapoints.append(row[-1]) + + return { + "data": { + "labels" : labels, + "datasets" : [ + { + "name": _("Total Revenue"), + "values": datapoints + } + ] + }, + "type" : "bar" + } \ No newline at end of file diff --git a/erpnext/stock/report/purchase_receipt_trends/purchase_receipt_trends.py b/erpnext/stock/report/purchase_receipt_trends/purchase_receipt_trends.py index 0e58920725..ac235f74e1 100644 --- a/erpnext/stock/report/purchase_receipt_trends/purchase_receipt_trends.py +++ b/erpnext/stock/report/purchase_receipt_trends/purchase_receipt_trends.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals import frappe +from frappe import _ from erpnext.controllers.trends import get_columns,get_data def execute(filters=None): @@ -11,4 +12,31 @@ def execute(filters=None): conditions = get_columns(filters, "Purchase Receipt") data = get_data(filters, conditions) - return conditions["columns"], data \ No newline at end of file + chart_data = get_chart_data(data) + + return conditions["columns"], data, None, chart_data + +def get_chart_data(data): + labels, datapoints = [], [] + + if len(data) > 10: + data = sorted(data, key = lambda i: i[-1],reverse=True) + data = data[:10] + + for row in data: + labels.append(row[0]) + datapoints.append(row[-1]) + + return { + "data": { + "labels" : labels, + "datasets" : [ + { + "name": _("Total Expenditure"), + "values": datapoints + } + ] + }, + "type" : "bar", + "colors":["#5e64ff"] + } \ No newline at end of file From 3f7678416f76cb86157c1df4a744b064d55190de Mon Sep 17 00:00:00 2001 From: marination Date: Fri, 15 May 2020 03:58:09 +0530 Subject: [PATCH 4/8] chore: Stock Onboarding --- erpnext/stock/desk_page/stock/stock.json | 54 ++++++++++++++----- .../doctype/stock_settings/stock_settings.js | 34 ++++++++++++ .../stock/module_onboarding/stock/stock.json | 54 +++++++++++++++++++ .../buying_settings/buying_settings.json | 19 +++++++ .../create_a_price_list.json | 19 +++++++ .../create_a_product/create_a_product.json | 19 +++++++ .../create_a_stock_entry.json | 19 +++++++ .../create_a_warehouse.json | 19 +++++++ ...oduction_to_price_list_and_item_price.json | 19 +++++++ .../introduction_to_stock_entry.json | 19 +++++++ .../stock_settings/stock_settings.json | 19 +++++++ 11 files changed, 281 insertions(+), 13 deletions(-) create mode 100644 erpnext/stock/module_onboarding/stock/stock.json create mode 100644 erpnext/stock/onboarding_step/buying_settings/buying_settings.json create mode 100644 erpnext/stock/onboarding_step/create_a_price_list/create_a_price_list.json create mode 100644 erpnext/stock/onboarding_step/create_a_product/create_a_product.json create mode 100644 erpnext/stock/onboarding_step/create_a_stock_entry/create_a_stock_entry.json create mode 100644 erpnext/stock/onboarding_step/create_a_warehouse/create_a_warehouse.json create mode 100644 erpnext/stock/onboarding_step/introduction_to_price_list_and_item_price/introduction_to_price_list_and_item_price.json create mode 100644 erpnext/stock/onboarding_step/introduction_to_stock_entry/introduction_to_stock_entry.json create mode 100644 erpnext/stock/onboarding_step/stock_settings/stock_settings.json diff --git a/erpnext/stock/desk_page/stock/stock.json b/erpnext/stock/desk_page/stock/stock.json index 38475a6f26..6b93449ecd 100644 --- a/erpnext/stock/desk_page/stock/stock.json +++ b/erpnext/stock/desk_page/stock/stock.json @@ -1,9 +1,14 @@ { "cards": [ + { + "hidden": 0, + "label": "Items and Pricing", + "links": "[\n {\n \"label\": \"Item\",\n \"name\": \"Item\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Item Group\",\n \"link\": \"Tree/Item Group\",\n \"name\": \"Item Group\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Product Bundle\",\n \"name\": \"Product Bundle\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Price List\",\n \"name\": \"Price List\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Price\",\n \"name\": \"Item Price\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Shipping Rule\",\n \"name\": \"Shipping Rule\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Pricing Rule\",\n \"name\": \"Pricing Rule\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Alternative\",\n \"name\": \"Item Alternative\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Manufacturer\",\n \"name\": \"Item Manufacturer\",\n \"type\": \"doctype\"\n }\n]" + }, { "hidden": 0, "label": "Stock Transactions", - "links": "[\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"label\": \"Stock Entry\",\n \"name\": \"Stock Entry\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"Customer\"\n ],\n \"label\": \"Delivery Note\",\n \"name\": \"Delivery Note\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"Supplier\"\n ],\n \"label\": \"Purchase Receipt\",\n \"name\": \"Purchase Receipt\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"label\": \"Material Request\",\n \"name\": \"Material Request\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"label\": \"Pick List\",\n \"name\": \"Pick List\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Delivery Trip\",\n \"name\": \"Delivery Trip\",\n \"type\": \"doctype\"\n }\n]" + "links": "[\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"label\": \"Material Request\",\n \"name\": \"Material Request\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"label\": \"Stock Entry\",\n \"name\": \"Stock Entry\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"Customer\"\n ],\n \"label\": \"Delivery Note\",\n \"name\": \"Delivery Note\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"Supplier\"\n ],\n \"label\": \"Purchase Receipt\",\n \"name\": \"Purchase Receipt\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"label\": \"Pick List\",\n \"name\": \"Pick List\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Delivery Trip\",\n \"name\": \"Delivery Trip\",\n \"type\": \"doctype\"\n }\n]" }, { "hidden": 0, @@ -13,12 +18,7 @@ { "hidden": 0, "label": "Settings", - "links": "[\n {\n \"label\": \"Stock Settings\",\n \"name\": \"Stock Settings\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Warehouse\",\n \"name\": \"Warehouse\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Unit of Measure (UOM)\",\n \"name\": \"UOM\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Brand\",\n \"name\": \"Brand\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Attribute\",\n \"name\": \"Item Attribute\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Variant Settings\",\n \"name\": \"Item Variant Settings\",\n \"type\": \"doctype\"\n }\n]" - }, - { - "hidden": 0, - "label": "Items and Pricing", - "links": "[\n {\n \"label\": \"Item\",\n \"name\": \"Item\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Product Bundle\",\n \"name\": \"Product Bundle\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Item Group\",\n \"link\": \"Tree/Item Group\",\n \"name\": \"Item Group\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Price List\",\n \"name\": \"Price List\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Price\",\n \"name\": \"Item Price\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Shipping Rule\",\n \"name\": \"Shipping Rule\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Pricing Rule\",\n \"name\": \"Pricing Rule\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Alternative\",\n \"name\": \"Item Alternative\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Manufacturer\",\n \"name\": \"Item Manufacturer\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Variant Settings\",\n \"name\": \"Item Variant Settings\",\n \"type\": \"doctype\"\n }\n]" + "links": "[\n {\n \"label\": \"Stock Settings\",\n \"name\": \"Stock Settings\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Warehouse\",\n \"name\": \"Warehouse\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Unit of Measure (UOM)\",\n \"name\": \"UOM\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Variant Settings\",\n \"name\": \"Item Variant Settings\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Brand\",\n \"name\": \"Brand\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Attribute\",\n \"name\": \"Item Attribute\",\n \"type\": \"doctype\"\n }\n]" }, { "hidden": 0, @@ -41,34 +41,45 @@ "links": "[\n {\n \"dependencies\": [\n \"Material Request\"\n ],\n \"doctype\": \"Material Request\",\n \"is_query_report\": true,\n \"label\": \"Requested Items To Be Transferred\",\n \"name\": \"Requested Items To Be Transferred\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Stock Ledger Entry\"\n ],\n \"doctype\": \"Stock Ledger Entry\",\n \"is_query_report\": true,\n \"label\": \"Batch Item Expiry Status\",\n \"name\": \"Batch Item Expiry Status\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Price List\"\n ],\n \"doctype\": \"Price List\",\n \"is_query_report\": true,\n \"label\": \"Item Prices\",\n \"name\": \"Item Prices\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"doctype\": \"Item\",\n \"is_query_report\": true,\n \"label\": \"Itemwise Recommended Reorder Level\",\n \"name\": \"Itemwise Recommended Reorder Level\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"doctype\": \"Item\",\n \"is_query_report\": true,\n \"label\": \"Item Variant Details\",\n \"name\": \"Item Variant Details\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Order\"\n ],\n \"doctype\": \"Purchase Order\",\n \"is_query_report\": true,\n \"label\": \"Subcontracted Raw Materials To Be Transferred\",\n \"name\": \"Subcontracted Raw Materials To Be Transferred\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Order\"\n ],\n \"doctype\": \"Purchase Order\",\n \"is_query_report\": true,\n \"label\": \"Subcontracted Item To Be Received\",\n \"name\": \"Subcontracted Item To Be Received\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Stock Ledger Entry\"\n ],\n \"doctype\": \"Stock Ledger Entry\",\n \"is_query_report\": true,\n \"label\": \"Stock and Account Value Comparison\",\n \"name\": \"Stock and Account Value Comparison\",\n \"type\": \"report\"\n }\n]" } ], + "cards_label": "Masters & Reports", "category": "Modules", - "charts": [], + "charts": [ + { + "chart_name": "Warehouse wise Stock Value" + } + ], "creation": "2020-03-02 15:43:10.096528", "developer_mode_only": 0, "disable_user_customization": 0, "docstatus": 0, "doctype": "Desk Page", "extends_another_page": 0, - "icon": "", "idx": 0, "is_standard": 1, "label": "Stock", - "modified": "2020-04-01 11:28:51.148421", + "modified": "2020-05-15 04:11:36.326013", "modified_by": "Administrator", "module": "Stock", "name": "Stock", + "onboarding": "Stock", "owner": "Administrator", "pin_to_bottom": 0, "pin_to_top": 0, "shortcuts": [ { + "color": "#cef6d1", + "format": "{} available", "label": "Item", "link_to": "Item", + "stats_filter": "{\n \"disabled\" : 0\n}", "type": "DocType" }, { - "label": "Pricing Rule", - "link_to": "Pricing Rule", + "color": "#ffe8cd", + "format": "{} Pending", + "label": "Material Request", + "link_to": "Material Request", + "stats_filter": "{\n \"company\": [\"like\", '%' + frappe.defaults.get_global_default(\"company\") + '%'],\n \"status\": \"Pending\"\n}", "type": "DocType" }, { @@ -76,6 +87,22 @@ "link_to": "Stock Entry", "type": "DocType" }, + { + "color": "#ffe8cd", + "format": "{} to Bill", + "label": "Purchase Receipt", + "link_to": "Purchase Receipt", + "stats_filter": "{\n \"company\": [\"like\", '%' + frappe.defaults.get_global_default(\"company\") + '%'],\n \"status\": \"To Bill\"\n}", + "type": "DocType" + }, + { + "color": "#ffe8cd", + "format": "{} to Bill", + "label": "Delivery Note", + "link_to": "Delivery Note", + "stats_filter": "{\n \"company\": [\"like\", '%' + frappe.defaults.get_global_default(\"company\") + '%'],\n \"status\": \"To Bill\"\n}", + "type": "DocType" + }, { "label": "Stock Ledger", "link_to": "Stock Ledger", @@ -86,5 +113,6 @@ "link_to": "Stock Balance", "type": "Report" } - ] + ], + "shortcuts_label": "Quick Access" } \ No newline at end of file diff --git a/erpnext/stock/doctype/stock_settings/stock_settings.js b/erpnext/stock/doctype/stock_settings/stock_settings.js index cc0e2cfc42..81c6067946 100644 --- a/erpnext/stock/doctype/stock_settings/stock_settings.js +++ b/erpnext/stock/doctype/stock_settings/stock_settings.js @@ -15,3 +15,37 @@ frappe.ui.form.on('Stock Settings', { frm.set_query("sample_retention_warehouse", filters); } }); + +frappe.tour['Stock Settings'] = [ + { + fieldname: "item_naming_by", + title: __("Item Naming By"), + description: __("By default, the Item Name is set as per the Item Code entered. If you want Items to be named by a set Naming Series choose the 'Naming Series' option.") + }, + { + fieldname: "valuation_method", + title: __("Valuation Method"), + description: __("Choose between FIFO and Moving Average Valuation Methods. Click") + "here" + __("to understand them") + }, + { + fieldname: "show_barcode_field", + title: __("Show Barcode Field"), + description: __("Show 'Scan Barcode' field above every child table to insert Items with ease.") + }, + { + fieldname: "default_warehouse", + title: __("Default Warehouse"), + description: __("Set a Default Warehouse for Inventory Transactions. This will be fetched into the Default Warehouse in the Item master:") + }, + { + fieldname: "allow_negative_stock", + title: __("Allow Negative Stock"), + description: __("This will allow stock items to be displayed in negative values. Using this option depends on your use case. With this option unchecked, the system warns before obstructing a transaction that is causing negative stock.") + + }, + { + fieldname: "automatically_set_serial_nos_based_on_fifo", + title: __("Automatically Set Serial Nos based on FIFO"), + description: __("Serial numbers for stock will be set automatically based on the Items entered based on first in first out in transactions like Purchase/Sales Invoices, Delivery Notes, etc.") + } +]; diff --git a/erpnext/stock/module_onboarding/stock/stock.json b/erpnext/stock/module_onboarding/stock/stock.json new file mode 100644 index 0000000000..28d8f67285 --- /dev/null +++ b/erpnext/stock/module_onboarding/stock/stock.json @@ -0,0 +1,54 @@ +{ + "allow_roles": [ + { + "role": "Manufacturing Manager" + }, + { + "role": "Stock Manager" + }, + { + "role": "Manufacturing User" + }, + { + "role": "Stock User" + } + ], + "creation": "2020-05-15 03:18:44.400108", + "docstatus": 0, + "doctype": "Module Onboarding", + "documentation_url": "https://docs.erpnext.com/docs/user/manual/en/stock", + "idx": 0, + "is_complete": 0, + "modified": "2020-05-15 04:02:23.634655", + "modified_by": "Administrator", + "module": "Stock", + "name": "Stock", + "owner": "Administrator", + "steps": [ + { + "step": "Create a Warehouse" + }, + { + "step": "Create a Product" + }, + { + "step": "Stock Settings" + }, + { + "step": "Introduction to Stock Entry" + }, + { + "step": "Create a Stock Entry" + }, + { + "step": "Introduction to Price List and Item Price" + }, + { + "step": "Create a Price List" + } + ], + "subtitle": "Inventory, Warehouses, Analysis and more.", + "success_message": "The Stock Module is all set up!", + "title": "Let's Setup the Stock Module.", + "user_can_dismiss": 1 +} \ No newline at end of file diff --git a/erpnext/stock/onboarding_step/buying_settings/buying_settings.json b/erpnext/stock/onboarding_step/buying_settings/buying_settings.json new file mode 100644 index 0000000000..a788ccd4cc --- /dev/null +++ b/erpnext/stock/onboarding_step/buying_settings/buying_settings.json @@ -0,0 +1,19 @@ +{ + "action": "Update Settings", + "creation": "2020-05-06 15:53:44.667414", + "docstatus": 0, + "doctype": "Onboarding Step", + "idx": 0, + "is_complete": 0, + "is_mandatory": 0, + "is_single": 0, + "is_skipped": 0, + "modified": "2020-05-12 18:30:06.323797", + "modified_by": "Administrator", + "name": "Buying Settings", + "owner": "Administrator", + "reference_document": "Buying Settings", + "show_full_form": 0, + "title": "Configure Buying Settings.", + "validate_action": 1 +} \ No newline at end of file diff --git a/erpnext/stock/onboarding_step/create_a_price_list/create_a_price_list.json b/erpnext/stock/onboarding_step/create_a_price_list/create_a_price_list.json new file mode 100644 index 0000000000..ce5b5ecf86 --- /dev/null +++ b/erpnext/stock/onboarding_step/create_a_price_list/create_a_price_list.json @@ -0,0 +1,19 @@ +{ + "action": "Create Entry", + "creation": "2020-05-15 03:26:41.917046", + "docstatus": 0, + "doctype": "Onboarding Step", + "idx": 0, + "is_complete": 0, + "is_mandatory": 0, + "is_single": 0, + "is_skipped": 0, + "modified": "2020-05-15 03:33:09.305991", + "modified_by": "Administrator", + "name": "Create a Price List", + "owner": "Administrator", + "reference_document": "Price List", + "show_full_form": 1, + "title": "Create a Price List", + "validate_action": 1 +} \ No newline at end of file diff --git a/erpnext/stock/onboarding_step/create_a_product/create_a_product.json b/erpnext/stock/onboarding_step/create_a_product/create_a_product.json new file mode 100644 index 0000000000..d2068e167b --- /dev/null +++ b/erpnext/stock/onboarding_step/create_a_product/create_a_product.json @@ -0,0 +1,19 @@ +{ + "action": "Create Entry", + "creation": "2020-05-12 18:16:06.624554", + "docstatus": 0, + "doctype": "Onboarding Step", + "idx": 0, + "is_complete": 0, + "is_mandatory": 0, + "is_single": 0, + "is_skipped": 0, + "modified": "2020-05-12 18:30:02.489949", + "modified_by": "Administrator", + "name": "Create a Product", + "owner": "Administrator", + "reference_document": "Item", + "show_full_form": 0, + "title": "Create a Product", + "validate_action": 1 +} \ No newline at end of file diff --git a/erpnext/stock/onboarding_step/create_a_stock_entry/create_a_stock_entry.json b/erpnext/stock/onboarding_step/create_a_stock_entry/create_a_stock_entry.json new file mode 100644 index 0000000000..2b83f657d6 --- /dev/null +++ b/erpnext/stock/onboarding_step/create_a_stock_entry/create_a_stock_entry.json @@ -0,0 +1,19 @@ +{ + "action": "Create Entry", + "creation": "2020-05-15 03:20:16.277043", + "docstatus": 0, + "doctype": "Onboarding Step", + "idx": 0, + "is_complete": 0, + "is_mandatory": 0, + "is_single": 0, + "is_skipped": 0, + "modified": "2020-05-15 03:30:58.047696", + "modified_by": "Administrator", + "name": "Create a Stock Entry", + "owner": "Administrator", + "reference_document": "Stock Entry", + "show_full_form": 1, + "title": "Create a Stock Entry", + "validate_action": 1 +} \ No newline at end of file diff --git a/erpnext/stock/onboarding_step/create_a_warehouse/create_a_warehouse.json b/erpnext/stock/onboarding_step/create_a_warehouse/create_a_warehouse.json new file mode 100644 index 0000000000..3269125efc --- /dev/null +++ b/erpnext/stock/onboarding_step/create_a_warehouse/create_a_warehouse.json @@ -0,0 +1,19 @@ +{ + "action": "Create Entry", + "creation": "2020-05-12 18:00:03.027704", + "docstatus": 0, + "doctype": "Onboarding Step", + "idx": 0, + "is_complete": 0, + "is_mandatory": 0, + "is_single": 0, + "is_skipped": 0, + "modified": "2020-05-12 18:27:44.128737", + "modified_by": "Administrator", + "name": "Create a Warehouse", + "owner": "Administrator", + "reference_document": "Warehouse", + "show_full_form": 0, + "title": "Setup your Purchase Warehouse", + "validate_action": 1 +} \ No newline at end of file diff --git a/erpnext/stock/onboarding_step/introduction_to_price_list_and_item_price/introduction_to_price_list_and_item_price.json b/erpnext/stock/onboarding_step/introduction_to_price_list_and_item_price/introduction_to_price_list_and_item_price.json new file mode 100644 index 0000000000..f75523ab29 --- /dev/null +++ b/erpnext/stock/onboarding_step/introduction_to_price_list_and_item_price/introduction_to_price_list_and_item_price.json @@ -0,0 +1,19 @@ +{ + "action": "Watch Video", + "creation": "2020-05-15 03:26:01.386069", + "docstatus": 0, + "doctype": "Onboarding Step", + "idx": 0, + "is_complete": 0, + "is_mandatory": 0, + "is_single": 0, + "is_skipped": 0, + "modified": "2020-05-15 03:31:01.267728", + "modified_by": "Administrator", + "name": "Introduction to Price List and Item Price", + "owner": "Administrator", + "show_full_form": 0, + "title": "Let's take a brief look at Price List and Item Price", + "validate_action": 1, + "video_url": "https://www.youtube.com/watch?v=lY6hAQM1I28" +} \ No newline at end of file diff --git a/erpnext/stock/onboarding_step/introduction_to_stock_entry/introduction_to_stock_entry.json b/erpnext/stock/onboarding_step/introduction_to_stock_entry/introduction_to_stock_entry.json new file mode 100644 index 0000000000..229bcd49cf --- /dev/null +++ b/erpnext/stock/onboarding_step/introduction_to_stock_entry/introduction_to_stock_entry.json @@ -0,0 +1,19 @@ +{ + "action": "Watch Video", + "creation": "2020-05-15 02:47:17.958806", + "docstatus": 0, + "doctype": "Onboarding Step", + "idx": 0, + "is_complete": 0, + "is_mandatory": 0, + "is_single": 0, + "is_skipped": 0, + "modified": "2020-05-15 03:30:39.606147", + "modified_by": "Administrator", + "name": "Introduction to Stock Entry", + "owner": "Administrator", + "show_full_form": 0, + "title": "Introduction to the backbone of Stock, Stock Entry.", + "validate_action": 1, + "video_url": "https://www.youtube.com/watch?v=Njt107hlY3I" +} \ No newline at end of file diff --git a/erpnext/stock/onboarding_step/stock_settings/stock_settings.json b/erpnext/stock/onboarding_step/stock_settings/stock_settings.json new file mode 100644 index 0000000000..7591bff538 --- /dev/null +++ b/erpnext/stock/onboarding_step/stock_settings/stock_settings.json @@ -0,0 +1,19 @@ +{ + "action": "Show Form Tour", + "creation": "2020-05-15 02:53:57.209967", + "docstatus": 0, + "doctype": "Onboarding Step", + "idx": 0, + "is_complete": 0, + "is_mandatory": 0, + "is_single": 1, + "is_skipped": 0, + "modified": "2020-05-15 03:55:15.444151", + "modified_by": "Administrator", + "name": "Stock Settings", + "owner": "Administrator", + "reference_document": "Stock Settings", + "show_full_form": 0, + "title": "Explore Stock Settings", + "validate_action": 1 +} \ No newline at end of file From be5c45a9ae1fc0ddc48de5107e624a2ba144f63c Mon Sep 17 00:00:00 2001 From: marination Date: Fri, 15 May 2020 13:21:58 +0530 Subject: [PATCH 5/8] chore: Fixtures and empty state handling in chart widgets --- .../warehouse_wise_stock_value.py | 4 + erpnext/stock/dashboard_fixtures.py | 207 ++++++++++++++++++ .../delivery_note_trends.py | 3 + .../item_shortage_report.py | 2 +- .../purchase_receipt_trends.py | 3 + .../stock/report/stock_ageing/stock_ageing.py | 3 + 6 files changed, 221 insertions(+), 1 deletion(-) create mode 100644 erpnext/stock/dashboard_fixtures.py diff --git a/erpnext/stock/dashboard_chart_source/warehouse_wise_stock_value/warehouse_wise_stock_value.py b/erpnext/stock/dashboard_chart_source/warehouse_wise_stock_value/warehouse_wise_stock_value.py index da2f9350c6..05a5068752 100644 --- a/erpnext/stock/dashboard_chart_source/warehouse_wise_stock_value/warehouse_wise_stock_value.py +++ b/erpnext/stock/dashboard_chart_source/warehouse_wise_stock_value/warehouse_wise_stock_value.py @@ -25,6 +25,10 @@ def get(chart_name = None, chart = None, no_cache = None, filters = None, from_d wh["balance"] = balance[0][0] warehouses = [x for x in warehouses if not (x.get('balance') == None)] + + if not warehouses: + return [] + sorted_warehouse_map = sorted(warehouses, key = lambda i: i['balance'],reverse=True) if len(sorted_warehouse_map) > 10: diff --git a/erpnext/stock/dashboard_fixtures.py b/erpnext/stock/dashboard_fixtures.py new file mode 100644 index 0000000000..db955c39c9 --- /dev/null +++ b/erpnext/stock/dashboard_fixtures.py @@ -0,0 +1,207 @@ +# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt + +import frappe +import json +from frappe.utils import nowdate +from erpnext.accounts.utils import get_fiscal_year + +def get_data(): + return frappe._dict({ + "dashboards": get_dashboards(), + "charts": get_charts(), + "number_cards": get_number_cards(), + }) + +def get_company_for_dashboards(): + company = frappe.defaults.get_defaults().company + if company: + return company + else: + company_list = frappe.get_list("Company") + if company_list: + return company_list[0].name + return None + +company = frappe.get_doc("Company", get_company_for_dashboards()) +fiscal_year = get_fiscal_year(nowdate(), as_dict=1).get("name") + +def get_dashboards(): + return [{ + "name": "Stock", + "dashboard_name": "Stock", + "charts": [ + { "chart": "Item Shortage Summary", "width": "Half"}, + { "chart": "Stock Ageing", "width": "Half"}, + { "chart": "Item Wise Annual Revenue", "width": "Half"}, + { "chart": "Item Wise Annual Expenditure", "width": "Half"}, + { "chart": "Warehouse wise Stock Value", "width": "Full"} + ], + "cards": [ + { "card": "Purchase Receipts to Bill"}, + { "card": "Amount Payable against Receipt"}, + { "card": "Delivery Notes to Bill"}, + { "card": "Amount Receivable against Delivery"} + ] + }] + +def get_charts(): + return [ + { + "name": "Item Shortage Summary", + "chart_name": "Item Shortage Summary", + "chart_type": "Report", + "doctype": "Dashboard Chart", + "filters_json": json.dumps({ + "company": company.name + }), + "is_custom": 1, + "is_public": 1, + "owner": "Administrator", + "report_name": "Item Shortage Report", + "type": "Bar" + }, + { + "name": "Stock Ageing", + "chart_name": "Stock Ageing", + "chart_type": "Report", + "custom_options": json.dumps({ + "colors": ["#5e64ff"] + }), + "doctype": "Dashboard Chart", + "filters_json": json.dumps({ + "company": company.name, + "to_date": nowdate(), + "show_warehouse_wise_stock": 0 + }), + "is_custom": 1, + "is_public": 1, + "owner": "Administrator", + "report_name": "Stock Ageing", + "type": "Bar" + }, + { + "name": "Item Wise Annual Revenue", + "chart_name": "Item Wise Annual Revenue", + "chart_type": "Report", + "custom_options": json.dumps({ + "axisOptions": {"shortenYAxisNumbers": 1}, + "tooltipOptions": {}, + "colors":["#5e64ff"] + }), + "doctype": "Dashboard Chart", + "filters_json": json.dumps({ + "period": "Monthly", + "based_on": "Item", + "fiscal_year": fiscal_year, + "company": company.name + }), + "is_custom": 1, + "is_public": 1, + "owner": "Administrator", + "report_name": "Delivery Note Trends", + "type": "Bar" + }, + { + "name": "Item Wise Annual Expenditure", + "chart_name": "Item Wise Annual Expenditure", + "chart_type": "Report", + "custom_options": json.dumps({ + "axisOptions": {"shortenYAxisNumbers": 1}, + "tooltipOptions": {}, + "colors":["#5e64ff"] + }), + "doctype": "Dashboard Chart", + "filters_json": json.dumps({ + "period": "Monthly", + "based_on": "Item", + "fiscal_year": fiscal_year, + "company": company.name, + "period_based_on": "posting_date" + }), + "is_custom": 1, + "is_public": 1, + "owner": "Administrator", + "report_name": "Purchase Receipt Trends", + "type": "Bar" + }, + { + "name": "Warehouse wise Stock Value", + "chart_name": "Warehouse wise Stock Value", + "chart_type": "Custom", + "doctype": "Dashboard Chart", + "filters_json": json.dumps({}), + "is_custom": 0, + "is_public": 1, + "owner": "Administrator", + "source": "Warehouse wise Stock Value", + "type": "Bar" + } + + ] + +def get_number_cards(): + return [ + { + "name": "Amount Payable against Receipt", + "label": "Amount Payable against Receipt", + "function": "Sum", + "aggregate_function_based_on": "base_grand_total", + "doctype": "Number Card", + "document_type": "Purchase Receipt", + "filters_json": json.dumps( + [["Purchase Receipt","status","=","To Bill",False], + ["Purchase Receipt","company","=", company.name, False]] + ), + "is_public": 1, + "owner": "Administrator", + "show_percentage_stats": 1, + "stats_time_interval": "Daily" + }, + { + "name": "Amount Receivable against Delivery", + "label": "Amount Receivable against Delivery", + "function": "Sum", + "aggregate_function_based_on": "base_grand_total", + "doctype": "Number Card", + "document_type": "Delivery Note", + "filters_json": json.dumps( + [["Delivery Note","company","=",company.name,False], + ["Delivery Note","status","=","To Bill",False]] + ), + "is_public": 1, + "owner": "Administrator", + "show_percentage_stats": 1, + "stats_time_interval": "Daily" + }, + { + "name": "Purchase Receipts to Bill", + "label": "Purchase Receipts to Bill", + "function": "Count", + "doctype": "Number Card", + "document_type": "Purchase Receipt", + "filters_json": json.dumps( + [["Purchase Receipt","status","=","To Bill",False], + ["Purchase Receipt","company","=", company.name, False]] + ), + "is_public": 1, + "owner": "Administrator", + "show_percentage_stats": 1, + "stats_time_interval": "Daily" + }, + { + "name": "Delivery Notes to Bill", + "label": "Delivery Notes to Bill", + "function": "Count", + "doctype": "Number Card", + "document_type": "Delivery Note", + "filters_json": json.dumps( + [["Delivery Note","company","=",company.name,False], + ["Delivery Note","status","=","To Bill",False]] + ), + "is_public": 1, + "owner": "Administrator", + "show_percentage_stats": 1, + "stats_time_interval": "Daily" + } + ] \ No newline at end of file diff --git a/erpnext/stock/report/delivery_note_trends/delivery_note_trends.py b/erpnext/stock/report/delivery_note_trends/delivery_note_trends.py index 2108b51afc..d088b0020d 100644 --- a/erpnext/stock/report/delivery_note_trends/delivery_note_trends.py +++ b/erpnext/stock/report/delivery_note_trends/delivery_note_trends.py @@ -17,6 +17,9 @@ def execute(filters=None): return conditions["columns"], data, None, chart_data def get_chart_data(data): + if not data: + return [] + labels, datapoints = [], [] if len(data) > 10: diff --git a/erpnext/stock/report/item_shortage_report/item_shortage_report.py b/erpnext/stock/report/item_shortage_report/item_shortage_report.py index 07749ebec5..086d833bbc 100644 --- a/erpnext/stock/report/item_shortage_report/item_shortage_report.py +++ b/erpnext/stock/report/item_shortage_report/item_shortage_report.py @@ -11,7 +11,7 @@ def execute(filters=None): data = get_data(conditions, filters) if not data: - return [], [] + return [], [], None, [] chart_data = get_chart_data(data) diff --git a/erpnext/stock/report/purchase_receipt_trends/purchase_receipt_trends.py b/erpnext/stock/report/purchase_receipt_trends/purchase_receipt_trends.py index ac235f74e1..627c23b105 100644 --- a/erpnext/stock/report/purchase_receipt_trends/purchase_receipt_trends.py +++ b/erpnext/stock/report/purchase_receipt_trends/purchase_receipt_trends.py @@ -17,6 +17,9 @@ def execute(filters=None): return conditions["columns"], data, None, chart_data def get_chart_data(data): + if not data: + return [] + labels, datapoints = [], [] if len(data) > 10: diff --git a/erpnext/stock/report/stock_ageing/stock_ageing.py b/erpnext/stock/report/stock_ageing/stock_ageing.py index 48f22c2c24..c5b8f43f96 100644 --- a/erpnext/stock/report/stock_ageing/stock_ageing.py +++ b/erpnext/stock/report/stock_ageing/stock_ageing.py @@ -234,6 +234,9 @@ def get_sle_conditions(filters): return "and {}".format(" and ".join(conditions)) if conditions else "" def get_chart_data(data, filters): + if not data: + return [] + labels, datapoints = [], [] if filters.get("show_warehouse_wise_stock"): From a5fcaf66f9e6a8a9935af5da680bf1f48e1eca9e Mon Sep 17 00:00:00 2001 From: marination Date: Tue, 19 May 2020 13:05:22 +0530 Subject: [PATCH 6/8] fix: Added filters in number Cards --- erpnext/stock/dashboard_fixtures.py | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/erpnext/stock/dashboard_fixtures.py b/erpnext/stock/dashboard_fixtures.py index db955c39c9..d1a3a146a2 100644 --- a/erpnext/stock/dashboard_fixtures.py +++ b/erpnext/stock/dashboard_fixtures.py @@ -24,7 +24,10 @@ def get_company_for_dashboards(): return None company = frappe.get_doc("Company", get_company_for_dashboards()) -fiscal_year = get_fiscal_year(nowdate(), as_dict=1).get("name") +fiscal_year = get_fiscal_year(nowdate(), as_dict=1) +fiscal_year_name = fiscal_year.get("name") +start_date = str(fiscal_year.get("year_start_date")) +end_date = str(fiscal_year.get("year_end_date")) def get_dashboards(): return [{ @@ -93,7 +96,7 @@ def get_charts(): "filters_json": json.dumps({ "period": "Monthly", "based_on": "Item", - "fiscal_year": fiscal_year, + "fiscal_year": fiscal_year_name, "company": company.name }), "is_custom": 1, @@ -108,14 +111,13 @@ def get_charts(): "chart_type": "Report", "custom_options": json.dumps({ "axisOptions": {"shortenYAxisNumbers": 1}, - "tooltipOptions": {}, - "colors":["#5e64ff"] + "tooltipOptions": {} }), "doctype": "Dashboard Chart", "filters_json": json.dumps({ "period": "Monthly", "based_on": "Item", - "fiscal_year": fiscal_year, + "fiscal_year": fiscal_year_name, "company": company.name, "period_based_on": "posting_date" }), @@ -151,7 +153,8 @@ def get_number_cards(): "document_type": "Purchase Receipt", "filters_json": json.dumps( [["Purchase Receipt","status","=","To Bill",False], - ["Purchase Receipt","company","=", company.name, False]] + ["Purchase Receipt","company","=", company.name, False], + ["Purchase Receipt", "posting_date", "Between", [start_date,end_date], False]] ), "is_public": 1, "owner": "Administrator", @@ -167,7 +170,8 @@ def get_number_cards(): "document_type": "Delivery Note", "filters_json": json.dumps( [["Delivery Note","company","=",company.name,False], - ["Delivery Note","status","=","To Bill",False]] + ["Delivery Note","status","=","To Bill",False], + ["Delivery Note", "posting_date", "Between", [start_date,end_date], False]] ), "is_public": 1, "owner": "Administrator", @@ -182,7 +186,8 @@ def get_number_cards(): "document_type": "Purchase Receipt", "filters_json": json.dumps( [["Purchase Receipt","status","=","To Bill",False], - ["Purchase Receipt","company","=", company.name, False]] + ["Purchase Receipt","company","=", company.name, False], + ["Purchase Receipt", "posting_date", "Between", [start_date,end_date], False]] ), "is_public": 1, "owner": "Administrator", @@ -197,7 +202,8 @@ def get_number_cards(): "document_type": "Delivery Note", "filters_json": json.dumps( [["Delivery Note","company","=",company.name,False], - ["Delivery Note","status","=","To Bill",False]] + ["Delivery Note","status","=","To Bill",False], + ["Delivery Note", "posting_date", "Between", [start_date,end_date], False]] ), "is_public": 1, "owner": "Administrator", From 64b36dba4fef5e2db71f27fbf3b0f37e889443cb Mon Sep 17 00:00:00 2001 From: marination Date: Tue, 19 May 2020 13:27:10 +0530 Subject: [PATCH 7/8] fix: Changed Form Tour order and grammar fixes. --- .../doctype/stock_settings/stock_settings.js | 22 +++++++++---------- .../stock/module_onboarding/stock/stock.json | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/erpnext/stock/doctype/stock_settings/stock_settings.js b/erpnext/stock/doctype/stock_settings/stock_settings.js index 81c6067946..6f9757274d 100644 --- a/erpnext/stock/doctype/stock_settings/stock_settings.js +++ b/erpnext/stock/doctype/stock_settings/stock_settings.js @@ -22,20 +22,10 @@ frappe.tour['Stock Settings'] = [ title: __("Item Naming By"), description: __("By default, the Item Name is set as per the Item Code entered. If you want Items to be named by a set Naming Series choose the 'Naming Series' option.") }, - { - fieldname: "valuation_method", - title: __("Valuation Method"), - description: __("Choose between FIFO and Moving Average Valuation Methods. Click") + "here" + __("to understand them") - }, - { - fieldname: "show_barcode_field", - title: __("Show Barcode Field"), - description: __("Show 'Scan Barcode' field above every child table to insert Items with ease.") - }, { fieldname: "default_warehouse", title: __("Default Warehouse"), - description: __("Set a Default Warehouse for Inventory Transactions. This will be fetched into the Default Warehouse in the Item master:") + description: __("Set a Default Warehouse for Inventory Transactions. This will be fetched into the Default Warehouse in the Item master.") }, { fieldname: "allow_negative_stock", @@ -43,6 +33,16 @@ frappe.tour['Stock Settings'] = [ description: __("This will allow stock items to be displayed in negative values. Using this option depends on your use case. With this option unchecked, the system warns before obstructing a transaction that is causing negative stock.") }, + { + fieldname: "valuation_method", + title: __("Valuation Method"), + description: __("Choose between FIFO and Moving Average Valuation Methods. Click ") + "here" + __(" to know more about them.") + }, + { + fieldname: "show_barcode_field", + title: __("Show Barcode Field"), + description: __("Show 'Scan Barcode' field above every child table to insert Items with ease.") + }, { fieldname: "automatically_set_serial_nos_based_on_fifo", title: __("Automatically Set Serial Nos based on FIFO"), diff --git a/erpnext/stock/module_onboarding/stock/stock.json b/erpnext/stock/module_onboarding/stock/stock.json index 28d8f67285..5208dcbbf8 100644 --- a/erpnext/stock/module_onboarding/stock/stock.json +++ b/erpnext/stock/module_onboarding/stock/stock.json @@ -19,7 +19,7 @@ "documentation_url": "https://docs.erpnext.com/docs/user/manual/en/stock", "idx": 0, "is_complete": 0, - "modified": "2020-05-15 04:02:23.634655", + "modified": "2020-05-19 13:13:19.157316", "modified_by": "Administrator", "module": "Stock", "name": "Stock", From 658f29915a2bf70ec722aa84b9cebcb8b7875da8 Mon Sep 17 00:00:00 2001 From: marination Date: Tue, 19 May 2020 13:58:13 +0530 Subject: [PATCH 8/8] fix: PR and DN trend report charts, group by fixes --- .../report/delivery_note_trends/delivery_note_trends.py | 9 +++++++-- .../purchase_receipt_trends/purchase_receipt_trends.py | 9 +++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/erpnext/stock/report/delivery_note_trends/delivery_note_trends.py b/erpnext/stock/report/delivery_note_trends/delivery_note_trends.py index d088b0020d..40a639bc09 100644 --- a/erpnext/stock/report/delivery_note_trends/delivery_note_trends.py +++ b/erpnext/stock/report/delivery_note_trends/delivery_note_trends.py @@ -12,17 +12,22 @@ def execute(filters=None): conditions = get_columns(filters, "Delivery Note") data = get_data(filters, conditions) - chart_data = get_chart_data(data) + chart_data = get_chart_data(data, filters) return conditions["columns"], data, None, chart_data -def get_chart_data(data): +def get_chart_data(data, filters): if not data: return [] labels, datapoints = [], [] + if filters.get("group_by"): + # consider only consolidated row + data = [row for row in data if row[0]] + if len(data) > 10: + # get top 10 if data too long data = sorted(data, key = lambda i: i[-1],reverse=True) data = data[:10] diff --git a/erpnext/stock/report/purchase_receipt_trends/purchase_receipt_trends.py b/erpnext/stock/report/purchase_receipt_trends/purchase_receipt_trends.py index 627c23b105..3b8d8d2dcd 100644 --- a/erpnext/stock/report/purchase_receipt_trends/purchase_receipt_trends.py +++ b/erpnext/stock/report/purchase_receipt_trends/purchase_receipt_trends.py @@ -12,17 +12,22 @@ def execute(filters=None): conditions = get_columns(filters, "Purchase Receipt") data = get_data(filters, conditions) - chart_data = get_chart_data(data) + chart_data = get_chart_data(data, filters) return conditions["columns"], data, None, chart_data -def get_chart_data(data): +def get_chart_data(data, filters): if not data: return [] labels, datapoints = [], [] + if filters.get("group_by"): + # consider only consolidated row + data = [row for row in data if row[0]] + if len(data) > 10: + # get top 10 if data too long data = sorted(data, key = lambda i: i[-1],reverse=True) data = data[:10]