feat: stock module dashboard and onboarding

This commit is contained in:
Nabin Hait 2020-05-19 19:08:30 +05:30
parent 8db28b5647
commit 8b686a5721
13 changed files with 132 additions and 161 deletions

View File

@ -81,7 +81,7 @@ def get_charts():
"timespan": "Last Year", "timespan": "Last Year",
"color": "#a83333", "color": "#a83333",
"value_based_on": "base_net_total", "value_based_on": "base_net_total",
"filters_json": json.dumps({"docstatus": 1}), "filters_json": json.dumps([["Purchase Invoice", "docstatus", "=", 1]]),
"chart_type": "Sum", "chart_type": "Sum",
"timeseries": 1, "timeseries": 1,
"based_on": "posting_date", "based_on": "posting_date",
@ -99,7 +99,7 @@ def get_charts():
"timespan": "Last Year", "timespan": "Last Year",
"color": "#7b933d", "color": "#7b933d",
"value_based_on": "base_net_total", "value_based_on": "base_net_total",
"filters_json": json.dumps({"docstatus": 1}), "filters_json": json.dumps([["Sales Invoice", "docstatus", "=", 1]]),
"chart_type": "Sum", "chart_type": "Sum",
"timeseries": 1, "timeseries": 1,
"based_on": "posting_date", "based_on": "posting_date",

View File

@ -29,7 +29,7 @@ def get(chart_name = None, chart = None, no_cache = None, filters = None, from_d
if not warehouses: if not warehouses:
return [] return []
sorted_warehouse_map = sorted(warehouses, key = lambda i: i['balance'],reverse=True) sorted_warehouse_map = sorted(warehouses, key = lambda i: i['balance'], reverse=True)
if len(sorted_warehouse_map) > 10: if len(sorted_warehouse_map) > 10:
sorted_warehouse_map = sorted_warehouse_map[:10] sorted_warehouse_map = sorted_warehouse_map[:10]

View File

@ -3,6 +3,7 @@
import frappe import frappe
import json import json
from frappe import _
from frappe.utils import nowdate from frappe.utils import nowdate
from erpnext.accounts.utils import get_fiscal_year from erpnext.accounts.utils import get_fiscal_year
@ -34,39 +35,72 @@ def get_dashboards():
"name": "Stock", "name": "Stock",
"dashboard_name": "Stock", "dashboard_name": "Stock",
"charts": [ "charts": [
{ "chart": "Item Shortage Summary", "width": "Half"}, { "chart": "Warehouse wise Stock Value", "width": "Full"},
{ "chart": "Stock Ageing", "width": "Half"}, { "chart": "Purchase Receipt Trends", "width": "Half"},
{ "chart": "Item Wise Annual Revenue", "width": "Half"}, { "chart": "Delivery Trends", "width": "Half"},
{ "chart": "Item Wise Annual Expenditure", "width": "Half"}, { "chart": "Oldest Items", "width": "Half"},
{ "chart": "Warehouse wise Stock Value", "width": "Full"} { "chart": "Item Shortage Summary", "width": "Half"}
], ],
"cards": [ "cards": [
{ "card": "Purchase Receipts to Bill"}, { "card": "Total Active Items"},
{ "card": "Amount Payable against Receipt"}, { "card": "Total Warehouses"},
{ "card": "Delivery Notes to Bill"}, { "card": "Total Stock Value"}
{ "card": "Amount Receivable against Delivery"}
] ]
}] }]
def get_charts(): def get_charts():
return [ return [
{ {
"name": "Item Shortage Summary",
"chart_name": "Item Shortage Summary",
"chart_type": "Report",
"doctype": "Dashboard Chart", "doctype": "Dashboard Chart",
"filters_json": json.dumps({ "name": "Purchase Receipt Trends",
"company": company.name "time_interval": "Monthly",
}), "chart_name": _("Purchase Receipt Trends"),
"is_custom": 1, "timespan": "Last Year",
"color": "#7b933d",
"value_based_on": "base_net_total",
"filters_json": json.dumps([["Purchase Receipt", "docstatus", "=", 1]]),
"chart_type": "Sum",
"timeseries": 1,
"based_on": "posting_date",
"owner": "Administrator",
"document_type": "Purchase Receipt",
"type": "Bar",
"width": "Half",
"is_public": 1
},
{
"doctype": "Dashboard Chart",
"name": "Delivery Trends",
"time_interval": "Monthly",
"chart_name": _("Delivery Trends"),
"timespan": "Last Year",
"color": "#7b933d",
"value_based_on": "base_net_total",
"filters_json": json.dumps([["Delivery Note", "docstatus", "=", 1]]),
"chart_type": "Sum",
"timeseries": 1,
"based_on": "posting_date",
"owner": "Administrator",
"document_type": "Delivery Note",
"type": "Bar",
"width": "Half",
"is_public": 1
},
{
"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, "is_public": 1,
"owner": "Administrator", "owner": "Administrator",
"report_name": "Item Shortage Report", "source": "Warehouse wise Stock Value",
"type": "Bar" "type": "Bar"
}, },
{ {
"name": "Stock Ageing", "name": "Oldest Items",
"chart_name": "Stock Ageing", "chart_name": _("Oldest Items"),
"chart_type": "Report", "chart_type": "Report",
"custom_options": json.dumps({ "custom_options": json.dumps({
"colors": ["#5e64ff"] "colors": ["#5e64ff"]
@ -84,127 +118,55 @@ def get_charts():
"type": "Bar" "type": "Bar"
}, },
{ {
"name": "Item Wise Annual Revenue", "name": "Item Shortage Summary",
"chart_name": "Item Wise Annual Revenue", "chart_name": _("Item Shortage Summary"),
"chart_type": "Report", "chart_type": "Report",
"custom_options": json.dumps({
"axisOptions": {"shortenYAxisNumbers": 1},
"tooltipOptions": {},
"colors":["#5e64ff"]
}),
"doctype": "Dashboard Chart", "doctype": "Dashboard Chart",
"filters_json": json.dumps({ "filters_json": json.dumps({
"period": "Monthly",
"based_on": "Item",
"fiscal_year": fiscal_year_name,
"company": company.name "company": company.name
}), }),
"is_custom": 1, "is_custom": 1,
"is_public": 1, "is_public": 1,
"owner": "Administrator", "owner": "Administrator",
"report_name": "Delivery Note Trends", "report_name": "Item Shortage Report",
"type": "Bar"
},
{
"name": "Item Wise Annual Expenditure",
"chart_name": "Item Wise Annual Expenditure",
"chart_type": "Report",
"custom_options": json.dumps({
"axisOptions": {"shortenYAxisNumbers": 1},
"tooltipOptions": {}
}),
"doctype": "Dashboard Chart",
"filters_json": json.dumps({
"period": "Monthly",
"based_on": "Item",
"fiscal_year": fiscal_year_name,
"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" "type": "Bar"
} }
] ]
def get_number_cards(): def get_number_cards():
return [ return [
{ {
"name": "Amount Payable against Receipt", "name": "Total Active Items",
"label": "Amount Payable against Receipt", "label": _("Total Active Items"),
"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],
["Purchase Receipt", "posting_date", "Between", [start_date,end_date], 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],
["Delivery Note", "posting_date", "Between", [start_date,end_date], 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", "function": "Count",
"doctype": "Number Card", "doctype": "Number Card",
"document_type": "Purchase Receipt", "document_type": "Item",
"filters_json": json.dumps( "filters_json": json.dumps([["Item", "disabled", "=", 0]]),
[["Purchase Receipt","status","=","To Bill",False],
["Purchase Receipt","company","=", company.name, False],
["Purchase Receipt", "posting_date", "Between", [start_date,end_date], False]]
),
"is_public": 1, "is_public": 1,
"owner": "Administrator", "owner": "Administrator",
"show_percentage_stats": 1, "show_percentage_stats": 1,
"stats_time_interval": "Daily" "stats_time_interval": "Monthly"
}, },
{ {
"name": "Delivery Notes to Bill", "name": "Total Warehouses",
"label": "Delivery Notes to Bill", "label": _("Total Warehouses"),
"function": "Count", "function": "Count",
"doctype": "Number Card", "doctype": "Number Card",
"document_type": "Delivery Note", "document_type": "Warehouse",
"filters_json": json.dumps( "filters_json": json.dumps([["Warehouse", "disabled", "=", 0]]),
[["Delivery Note","company","=",company.name,False], "is_public": 1,
["Delivery Note","status","=","To Bill",False], "owner": "Administrator",
["Delivery Note", "posting_date", "Between", [start_date,end_date], False]] "show_percentage_stats": 1,
), "stats_time_interval": "Monthly"
},
{
"name": "Total Stock Value",
"label": _("Total Stock Value"),
"function": "Sum",
"aggregate_function_based_on": "stock_value",
"doctype": "Number Card",
"document_type": "Bin",
"filters_json": json.dumps([]),
"is_public": 1, "is_public": 1,
"owner": "Administrator", "owner": "Administrator",
"show_percentage_stats": 1, "show_percentage_stats": 1,

View File

@ -54,10 +54,11 @@
"docstatus": 0, "docstatus": 0,
"doctype": "Desk Page", "doctype": "Desk Page",
"extends_another_page": 0, "extends_another_page": 0,
"hide_custom": 0,
"idx": 0, "idx": 0,
"is_standard": 1, "is_standard": 1,
"label": "Stock", "label": "Stock",
"modified": "2020-05-15 04:11:36.326013", "modified": "2020-05-19 17:36:08.185652",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Stock", "module": "Stock",
"name": "Stock", "name": "Stock",
@ -112,6 +113,11 @@
"label": "Stock Balance", "label": "Stock Balance",
"link_to": "Stock Balance", "link_to": "Stock Balance",
"type": "Report" "type": "Report"
},
{
"label": "Stock Dashboard",
"link_to": "Stock",
"type": "Dashboard"
} }
], ],
"shortcuts_label": "Quick Access" "shortcuts_label": "Quick Access"

View File

@ -19,21 +19,18 @@
"documentation_url": "https://docs.erpnext.com/docs/user/manual/en/stock", "documentation_url": "https://docs.erpnext.com/docs/user/manual/en/stock",
"idx": 0, "idx": 0,
"is_complete": 0, "is_complete": 0,
"modified": "2020-05-19 13:13:19.157316", "modified": "2020-05-19 19:03:23.602423",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Stock", "module": "Stock",
"name": "Stock", "name": "Stock",
"owner": "Administrator", "owner": "Administrator",
"steps": [ "steps": [
{ {
"step": "Create a Warehouse" "step": "Setup your Warehouse"
}, },
{ {
"step": "Create a Product" "step": "Create a Product"
}, },
{
"step": "Stock Settings"
},
{ {
"step": "Introduction to Stock Entry" "step": "Introduction to Stock Entry"
}, },
@ -41,10 +38,13 @@
"step": "Create a Stock Entry" "step": "Create a Stock Entry"
}, },
{ {
"step": "Introduction to Price List and Item Price" "step": "Create a Supplier"
}, },
{ {
"step": "Create a Price List" "step": "Create a Purchase Receipt"
},
{
"step": "Stock Settings"
} }
], ],
"subtitle": "Inventory, Warehouses, Analysis and more.", "subtitle": "Inventory, Warehouses, Analysis and more.",

View File

@ -1,6 +1,6 @@
{ {
"action": "Create Entry", "action": "Create Entry",
"creation": "2020-05-15 03:26:41.917046", "creation": "2020-05-19 18:59:13.266713",
"docstatus": 0, "docstatus": 0,
"doctype": "Onboarding Step", "doctype": "Onboarding Step",
"idx": 0, "idx": 0,
@ -8,12 +8,12 @@
"is_mandatory": 0, "is_mandatory": 0,
"is_single": 0, "is_single": 0,
"is_skipped": 0, "is_skipped": 0,
"modified": "2020-05-15 03:33:09.305991", "modified": "2020-05-19 18:59:13.266713",
"modified_by": "Administrator", "modified_by": "Administrator",
"name": "Create a Price List", "name": "Create a Purchase Receipt",
"owner": "Administrator", "owner": "Administrator",
"reference_document": "Price List", "reference_document": "Purchase Receipt",
"show_full_form": 1, "show_full_form": 1,
"title": "Create a Price List", "title": "Create a Purchase Receipt",
"validate_action": 1 "validate_action": 1
} }

View File

@ -1,6 +1,6 @@
{ {
"action": "Create Entry", "action": "Create Entry",
"creation": "2020-05-12 18:00:03.027704", "creation": "2020-05-14 22:09:10.043554",
"docstatus": 0, "docstatus": 0,
"doctype": "Onboarding Step", "doctype": "Onboarding Step",
"idx": 0, "idx": 0,
@ -8,12 +8,12 @@
"is_mandatory": 0, "is_mandatory": 0,
"is_single": 0, "is_single": 0,
"is_skipped": 0, "is_skipped": 0,
"modified": "2020-05-12 18:27:44.128737", "modified": "2020-05-14 22:09:10.043554",
"modified_by": "Administrator", "modified_by": "Administrator",
"name": "Create a Warehouse", "name": "Create a Supplier",
"owner": "Administrator", "owner": "Administrator",
"reference_document": "Warehouse", "reference_document": "Supplier",
"show_full_form": 0, "show_full_form": 0,
"title": "Setup your Purchase Warehouse", "title": "Create a Supplier",
"validate_action": 1 "validate_action": 1
} }

View File

@ -1,19 +0,0 @@
{
"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"
}

View File

@ -8,12 +8,12 @@
"is_mandatory": 0, "is_mandatory": 0,
"is_single": 0, "is_single": 0,
"is_skipped": 0, "is_skipped": 0,
"modified": "2020-05-15 03:30:39.606147", "modified": "2020-05-19 18:55:41.457289",
"modified_by": "Administrator", "modified_by": "Administrator",
"name": "Introduction to Stock Entry", "name": "Introduction to Stock Entry",
"owner": "Administrator", "owner": "Administrator",
"show_full_form": 0, "show_full_form": 0,
"title": "Introduction to the backbone of Stock, Stock Entry.", "title": "Introduction to the multi-purpose stock transaction",
"validate_action": 1, "validate_action": 1,
"video_url": "https://www.youtube.com/watch?v=Njt107hlY3I" "video_url": "https://www.youtube.com/watch?v=Njt107hlY3I"
} }

View File

@ -0,0 +1,20 @@
{
"action": "Go to Page",
"creation": "2020-05-19 18:54:19.383397",
"docstatus": 0,
"doctype": "Onboarding Step",
"idx": 0,
"is_complete": 0,
"is_mandatory": 0,
"is_single": 0,
"is_skipped": 0,
"modified": "2020-05-19 18:54:19.383397",
"modified_by": "Administrator",
"name": "Setup your Warehouse",
"owner": "Administrator",
"path": "Tree/Warehouse",
"reference_document": "Warehouse",
"show_full_form": 0,
"title": "Setup your Warehouse",
"validate_action": 1
}

View File

@ -40,7 +40,7 @@ def get_chart_data(data, filters):
"labels" : labels, "labels" : labels,
"datasets" : [ "datasets" : [
{ {
"name": _("Total Revenue"), "name": _("Total Delivered Amount"),
"values": datapoints "values": datapoints
} }
] ]

View File

@ -40,7 +40,7 @@ def get_chart_data(data, filters):
"labels" : labels, "labels" : labels,
"datasets" : [ "datasets" : [
{ {
"name": _("Total Expenditure"), "name": _("Total Received Amount"),
"values": datapoints "values": datapoints
} }
] ]

View File

@ -53,7 +53,7 @@ def get_average_age(fifo_queue, to_date):
age_qty += batch_age * 1 age_qty += batch_age * 1
total_qty += 1 total_qty += 1
return (age_qty / total_qty) if total_qty else 0.0 return flt(age_qty / total_qty, 2) if total_qty else 0.0
def get_columns(filters): def get_columns(filters):
columns = [ columns = [
@ -242,6 +242,8 @@ def get_chart_data(data, filters):
if filters.get("show_warehouse_wise_stock"): if filters.get("show_warehouse_wise_stock"):
return {} return {}
data.sort(key = lambda row: row[6], reverse=True)
if len(data) > 10: if len(data) > 10:
data = data[:10] data = data[:10]