feat: Selling Desk, Dashboard and Onboarding (#22055)
* feat: Selling Desk, Dashboard and Onboarding
* chore: Selling Onboarding and fixes in Other onboardings
* chore: Dashboard and Number card Fixtures
* fix: Escape filters and Reposition Accounts Dashboard shortcut.
Co-authored-by: Nabin Hait <nabinhait@gmail.com>
diff --git a/erpnext/accounts/desk_page/accounting/accounting.json b/erpnext/accounts/desk_page/accounting/accounting.json
index 42fb9f4..31315e4 100644
--- a/erpnext/accounts/desk_page/accounting/accounting.json
+++ b/erpnext/accounts/desk_page/accounting/accounting.json
@@ -13,7 +13,7 @@
{
"hidden": 0,
"label": "Accounts Receivable",
- "links": "[\n {\n \"description\": \"Bills raised to Customers.\",\n \"label\": \"Sales Invoice\",\n \"name\": \"Sales Invoice\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Customer database.\",\n \"label\": \"Customer\",\n \"name\": \"Customer\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Bank/Cash transactions against party or for internal transfer\",\n \"label\": \"Payment Entry\",\n \"name\": \"Payment Entry\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Payment Request\",\n \"label\": \"Payment Request\",\n \"name\": \"Payment Request\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Accounts Receivable\",\n \"name\": \"Accounts Receivable\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Accounts Receivable Summary\",\n \"name\": \"Accounts Receivable Summary\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Sales Register\",\n \"name\": \"Sales Register\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Item-wise Sales Register\",\n \"name\": \"Item-wise Sales Register\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Ordered Items To Be Billed\",\n \"name\": \"Ordered Items To Be Billed\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Delivered Items To Be Billed\",\n \"name\": \"Delivered Items To Be Billed\",\n \"type\": \"report\"\n }\n]"
+ "links": "[\n {\n \"description\": \"Bills raised to Customers.\",\n \"label\": \"Sales Invoice\",\n \"name\": \"Sales Invoice\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Customer database.\",\n \"label\": \"Customer\",\n \"name\": \"Customer\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Bank/Cash transactions against party or for internal transfer\",\n \"label\": \"Payment Entry\",\n \"name\": \"Payment Entry\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Payment Request\",\n \"label\": \"Payment Request\",\n \"name\": \"Payment Request\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Accounts Receivable\",\n \"name\": \"Accounts Receivable\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Accounts Receivable Summary\",\n \"name\": \"Accounts Receivable Summary\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Sales Register\",\n \"name\": \"Sales Register\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Item-wise Sales Register\",\n \"name\": \"Item-wise Sales Register\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Sales Order Analysis\",\n \"name\": \"Sales Order Analysis\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Delivered Items To Be Billed\",\n \"name\": \"Delivered Items To Be Billed\",\n \"type\": \"report\"\n }\n]"
},
{
"hidden": 0,
@@ -98,7 +98,7 @@
"idx": 0,
"is_standard": 1,
"label": "Accounting",
- "modified": "2020-05-27 20:34:50.949772",
+ "modified": "2020-06-19 12:42:44.054598",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounting",
@@ -123,11 +123,6 @@
"type": "DocType"
},
{
- "label": "Dashboard",
- "link_to": "Accounts",
- "type": "Dashboard"
- },
- {
"label": "Journal Entry",
"link_to": "Journal Entry",
"type": "DocType"
@@ -151,6 +146,11 @@
"label": "Trial Balance",
"link_to": "Trial Balance",
"type": "Report"
+ },
+ {
+ "label": "Dashboard",
+ "link_to": "Accounts",
+ "type": "Dashboard"
}
]
}
\ No newline at end of file
diff --git a/erpnext/accounts/report/ordered_items_to_be_billed/ordered_items_to_be_billed.js b/erpnext/accounts/report/ordered_items_to_be_billed/ordered_items_to_be_billed.js
deleted file mode 100644
index 6e13d67..0000000
--- a/erpnext/accounts/report/ordered_items_to_be_billed/ordered_items_to_be_billed.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.query_reports["Ordered Items To Be Billed"] = {
- "filters": [
-
- ]
-}
diff --git a/erpnext/accounts/report/ordered_items_to_be_billed/ordered_items_to_be_billed.json b/erpnext/accounts/report/ordered_items_to_be_billed/ordered_items_to_be_billed.json
deleted file mode 100644
index c983dc9..0000000
--- a/erpnext/accounts/report/ordered_items_to_be_billed/ordered_items_to_be_billed.json
+++ /dev/null
@@ -1,27 +0,0 @@
-{
- "add_total_row": 1,
- "apply_user_permissions": 1,
- "creation": "2013-02-21 14:26:44",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Report",
- "idx": 3,
- "is_standard": "Yes",
- "modified": "2017-11-06 13:04:51.559061",
- "modified_by": "Administrator",
- "module": "Accounts",
- "name": "Ordered Items To Be Billed",
- "owner": "Administrator",
- "query": "select \n `tabSales Order`.`name` as \"Sales Order:Link/Sales Order:120\",\n `tabSales Order`.`customer` as \"Customer:Link/Customer:120\",\n `tabSales Order`.`customer_name` as \"Customer Name:150\",\n`tabSales Order`.`status` as \"Status\",\n `tabSales Order`.`transaction_date` as \"Date:Date\",\n `tabSales Order`.`project` as \"Project\",\n `tabSales Order Item`.item_code as \"Item:Link/Item:120\",\n `tabSales Order Item`.base_amount as \"Amount:Currency:110\",\n (`tabSales Order Item`.billed_amt * ifnull(`tabSales Order`.conversion_rate, 1)) as \"Billed Amount:Currency:110\",\n (`tabSales Order Item`.base_amount - (`tabSales Order Item`.billed_amt * ifnull(`tabSales Order`.conversion_rate, 1))) as \"Pending Amount:Currency:120\",\n `tabSales Order Item`.item_name as \"Item Name::150\",\n `tabSales Order Item`.description as \"Description::200\",\n `tabSales Order`.`company` as \"Company:Link/Company:\"\nfrom\n `tabSales Order`, `tabSales Order Item`\nwhere\n `tabSales Order Item`.`parent` = `tabSales Order`.`name`\n and `tabSales Order`.docstatus = 1\n and `tabSales Order`.status != \"Closed\"\n and `tabSales Order Item`.amount > 0\n and `tabSales Order Item`.billed_amt < `tabSales Order Item`.amount\norder by `tabSales Order`.transaction_date asc",
- "ref_doctype": "Sales Invoice",
- "report_name": "Ordered Items To Be Billed",
- "report_type": "Script Report",
- "roles": [
- {
- "role": "Accounts Manager"
- },
- {
- "role": "Accounts User"
- }
- ]
-}
\ No newline at end of file
diff --git a/erpnext/accounts/report/ordered_items_to_be_billed/ordered_items_to_be_billed.py b/erpnext/accounts/report/ordered_items_to_be_billed/ordered_items_to_be_billed.py
deleted file mode 100644
index ec0d2f3..0000000
--- a/erpnext/accounts/report/ordered_items_to_be_billed/ordered_items_to_be_billed.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# 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 _
-from erpnext.accounts.report.non_billed_report import get_ordered_to_be_billed_data
-
-def execute(filters=None):
- columns = get_column()
- args = get_args()
- data = get_ordered_to_be_billed_data(args)
- return columns, data
-
-def get_column():
- return [
- _("Sales Order") + ":Link/Sales Order:120", _("Status") + "::120", _("Date") + ":Date:100",
- _("Suplier") + ":Link/Customer:120", _("Customer Name") + "::120",
- _("Project") + ":Link/Project:120", _("Item Code") + ":Link/Item:120",
- _("Amount") + ":Currency:100", _("Billed Amount") + ":Currency:100", _("Pending Amount") + ":Currency:100",
- _("Item Name") + "::120", _("Description") + "::120", _("Company") + ":Link/Company:120",
- ]
-
-def get_args():
- return {'doctype': 'Sales Order', 'party': 'customer',
- 'date': 'transaction_date', 'order': 'transaction_date', 'order_by': 'asc'}
\ No newline at end of file
diff --git a/erpnext/buying/dashboard_fixtures.py b/erpnext/buying/dashboard_fixtures.py
index 172c936..c6e2ffa 100644
--- a/erpnext/buying/dashboard_fixtures.py
+++ b/erpnext/buying/dashboard_fixtures.py
@@ -155,8 +155,7 @@
["Purchase Order", "transaction_date", "Between", [start_date, end_date], False],
["Purchase Order", "status", "not in", ["Draft", "Cancelled", "Closed", None], False],
["Purchase Order", "docstatus", "=", 1, False],
- ["Purchase Order", "company", "=", company.name, False],
- ["Purchase Order", "transaction_date", "Between", [start_date,end_date], False]
+ ["Purchase Order", "company", "=", company.name, False]
]),
"function": "Sum",
"is_public": 1,
diff --git a/erpnext/buying/doctype/buying_settings/buying_settings.js b/erpnext/buying/doctype/buying_settings/buying_settings.js
index 01b40cd..e496e96 100644
--- a/erpnext/buying/doctype/buying_settings/buying_settings.js
+++ b/erpnext/buying/doctype/buying_settings/buying_settings.js
@@ -11,21 +11,21 @@
{
fieldname: "supp_master_name",
title: "Supplier 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 ") + "<a href='https://docs.erpnext.com/docs/user/manual/en/setting-up/settings/naming-series' target='_blank'>Naming Series</a>" + __(" choose the 'Naming Series' option."),
+ description: __("By default, the Supplier Name is set as per the Supplier Name entered. If you want Suppliers to be named by a ") + "<a href='https://docs.erpnext.com/docs/user/manual/en/setting-up/settings/naming-series' target='_blank'>Naming Series</a>" + __(" choose the 'Naming Series' option."),
},
{
fieldname: "buying_price_list",
title: "Default Buying Price List",
- description: __("Configure the default Price List when creating a new Buying transaction, the default is set as 'Standard Buying'. Item prices will be fetched from this Price List.")
+ description: __("Configure the default Price List when creating a new Purchase transaction. Item prices will be fetched from this Price List.")
},
{
fieldname: "po_required",
title: "Purchase Order Required for Purchase Invoice & Receipt Creation",
- description: __("If this option is configured 'Yes', ERPNext will prevent you from creating a Purchase Invoice or Receipt without creating a Purchase Order first. This configuration can be overridden for a particular supplier by enabling the 'Allow Purchase Invoice Creation Without Purchase Order' checkbox in supplier master.")
+ description: __("If this option is configured 'Yes', ERPNext will prevent you from creating a Purchase Invoice or Receipt without creating a Purchase Order first. This configuration can be overridden for a particular supplier by enabling the 'Allow Purchase Invoice Creation Without Purchase Order' checkbox in the Supplier master.")
},
{
fieldname: "pr_required",
title: "Purchase Receipt Required for Purchase Invoice Creation",
- description: __("If this option is configured 'Yes', ERPNext will prevent you from creating a Purchase Invoice without creating a Purchase Receipt first. This configuration can be overridden for a particular supplier by enabling the 'Allow Purchase Invoice Creation Without Purchase Receipt' checkbox in supplier master.")
+ description: __("If this option is configured 'Yes', ERPNext will prevent you from creating a Purchase Invoice without creating a Purchase Receipt first. This configuration can be overridden for a particular supplier by enabling the 'Allow Purchase Invoice Creation Without Purchase Receipt' checkbox in the Supplier master.")
}
];
\ No newline at end of file
diff --git a/erpnext/buying/module_onboarding/buying/buying.json b/erpnext/buying/module_onboarding/buying/buying.json
index 8fe2f38..6e4bbc9 100644
--- a/erpnext/buying/module_onboarding/buying/buying.json
+++ b/erpnext/buying/module_onboarding/buying/buying.json
@@ -19,7 +19,7 @@
"documentation_url": "https://docs.erpnext.com/docs/user/manual/en/buying",
"idx": 0,
"is_complete": 0,
- "modified": "2020-05-27 17:17:52.075947",
+ "modified": "2020-06-01 12:55:09.234944",
"modified_by": "Administrator",
"module": "Buying",
"name": "Buying",
diff --git a/erpnext/buying/onboarding_step/buying_settings/buying_settings.json b/erpnext/buying/onboarding_step/buying_settings/buying_settings.json
index a788ccd..6d765af 100644
--- a/erpnext/buying/onboarding_step/buying_settings/buying_settings.json
+++ b/erpnext/buying/onboarding_step/buying_settings/buying_settings.json
@@ -1,19 +1,19 @@
{
- "action": "Update Settings",
+ "action": "Show Form Tour",
"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_mandatory": 1,
+ "is_single": 1,
"is_skipped": 0,
- "modified": "2020-05-12 18:30:06.323797",
+ "modified": "2020-06-01 12:52:57.668870",
"modified_by": "Administrator",
"name": "Buying Settings",
"owner": "Administrator",
"reference_document": "Buying Settings",
"show_full_form": 0,
"title": "Configure Buying Settings.",
- "validate_action": 1
+ "validate_action": 0
}
\ No newline at end of file
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 15c4080..a7395a4 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -700,4 +700,5 @@
erpnext.patches.v13_0.update_sla_enhancements
erpnext.patches.v12_0.update_address_template_for_india
erpnext.patches.v12_0.set_multi_uom_in_rfq
-execute:frappe.delete_doc_if_exists("DocType", "Bank Reconciliation")
+erpnext.patches.v13_0.delete_old_sales_reports
+execute:frappe.delete_doc_if_exists("DocType", "Bank Reconciliation")
\ No newline at end of file
diff --git a/erpnext/patches/v13_0/delete_old_sales_reports.py b/erpnext/patches/v13_0/delete_old_sales_reports.py
new file mode 100644
index 0000000..0f44865
--- /dev/null
+++ b/erpnext/patches/v13_0/delete_old_sales_reports.py
@@ -0,0 +1,21 @@
+# Copyright (c) 2019, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+
+import frappe
+
+def execute():
+ reports_to_delete = ["Ordered Items To Be Delivered", "Ordered Items To Be Billed"]
+
+ for report in reports_to_delete:
+ if frappe.db.exists("Report", report):
+ delete_auto_email_reports(report)
+
+ frappe.delete_doc("Report", report)
+
+def delete_auto_email_reports(report):
+ """ Check for one or multiple Auto Email Reports and delete """
+ auto_email_reports = frappe.db.get_values("Auto Email Report", {"report": report}, ["name"])
+ for auto_email_report in auto_email_reports:
+ frappe.delete_doc("Auto Email Report", auto_email_report[0])
\ No newline at end of file
diff --git a/erpnext/selling/dashboard_fixtures.py b/erpnext/selling/dashboard_fixtures.py
new file mode 100644
index 0000000..889cb88
--- /dev/null
+++ b/erpnext/selling/dashboard_fixtures.py
@@ -0,0 +1,198 @@
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+import frappe
+import json
+from frappe import _
+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)
+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 [{
+ "name": "Selling",
+ "dashboard_name": "Selling",
+ "charts": [
+ { "chart": "Sales Order Trends", "width": "Full"},
+ { "chart": "Top Customers", "width": "Half"},
+ { "chart": "Sales Order Analysis", "width": "Half"},
+ { "chart": "Item-wise Annual Sales", "width": "Full"}
+ ],
+ "cards": [
+ { "card": "Annual Sales"},
+ { "card": "Sales Orders to Deliver"},
+ { "card": "Sales Orders to Bill"},
+ { "card": "Active Customers"}
+ ]
+ }]
+
+def get_charts():
+ return [
+ {
+ "name": "Sales Order Analysis",
+ "chart_name": _("Sales Order Analysis"),
+ "chart_type": "Report",
+ "custom_options": json.dumps({
+ "type": "donut",
+ "height": 300,
+ "axisOptions": {"shortenYAxisNumbers": 1}
+ }),
+ "doctype": "Dashboard Chart",
+ "filters_json": json.dumps({
+ "company": company.name,
+ "from_date": start_date,
+ "to_date": end_date
+ }),
+ "is_custom": 1,
+ "is_public": 1,
+ "owner": "Administrator",
+ "report_name": "Sales Order Analysis",
+ "type": "Donut"
+ },
+ {
+ "name": "Item-wise Annual Sales",
+ "chart_name": _("Item-wise Annual Sales"),
+ "chart_type": "Report",
+ "doctype": "Dashboard Chart",
+ "filters_json": json.dumps({
+ "company": company.name,
+ "from_date": start_date,
+ "to_date": end_date
+ }),
+ "is_custom": 1,
+ "is_public": 1,
+ "owner": "Administrator",
+ "report_name": "Item-wise Sales History",
+ "type": "Bar"
+ },
+ {
+ "name": "Sales Order Trends",
+ "chart_name": _("Sales Order Trends"),
+ "chart_type": "Report",
+ "custom_options": json.dumps({
+ "type": "line",
+ "axisOptions": {"shortenYAxisNumbers": 1},
+ "tooltipOptions": {},
+ "lineOptions": {
+ "regionFill": 1
+ }
+ }),
+ "doctype": "Dashboard Chart",
+ "filters_json": json.dumps({
+ "company": company.name,
+ "period": "Monthly",
+ "fiscal_year": fiscal_year_name,
+ "based_on": "Item"
+ }),
+ "is_custom": 1,
+ "is_public": 1,
+ "owner": "Administrator",
+ "report_name": "Sales Order Trends",
+ "type": "Line"
+ },
+ {
+ "name": "Top Customers",
+ "chart_name": _("Top Customers"),
+ "chart_type": "Report",
+ "doctype": "Dashboard Chart",
+ "filters_json": json.dumps({
+ "company": company.name,
+ "period": "Monthly",
+ "fiscal_year": fiscal_year_name,
+ "based_on": "Customer"
+ }),
+ "is_custom": 1,
+ "is_public": 1,
+ "owner": "Administrator",
+ "report_name": "Delivery Note Trends",
+ "type": "Bar"
+ }
+ ]
+
+def get_number_cards():
+ return [
+ {
+ "name": "Annual Sales",
+ "aggregate_function_based_on": "base_net_total",
+ "doctype": "Number Card",
+ "document_type": "Sales Order",
+ "filters_json": json.dumps([
+ ["Sales Order", "transaction_date", "Between", [start_date, end_date], False],
+ ["Sales Order", "status", "not in", ["Draft", "Cancelled", "Closed", None], False],
+ ["Sales Order", "docstatus", "=", 1, False],
+ ["Sales Order", "company", "=", company.name, False]
+ ]),
+ "function": "Sum",
+ "is_public": 1,
+ "label": _("Annual Sales"),
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Monthly"
+ },
+ {
+ "name": "Sales Orders to Deliver",
+ "doctype": "Number Card",
+ "document_type": "Sales Order",
+ "filters_json": json.dumps([
+ ["Sales Order", "status", "in", ["To Deliver and Bill", "To Deliver", None], False],
+ ["Sales Order", "docstatus", "=", 1, False],
+ ["Sales Order", "company", "=", company.name, False]
+ ]),
+ "function": "Count",
+ "is_public": 1,
+ "label": _("Sales Orders to Deliver"),
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Weekly"
+ },
+ {
+ "name": "Sales Orders to Bill",
+ "doctype": "Number Card",
+ "document_type": "Sales Order",
+ "filters_json": json.dumps([
+ ["Sales Order", "status", "in", ["To Deliver and Bill", "To Bill", None], False],
+ ["Sales Order", "docstatus", "=", 1, False],
+ ["Sales Order", "company", "=", company.name, False]
+ ]),
+ "function": "Count",
+ "is_public": 1,
+ "label": _("Sales Orders to Bill"),
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Weekly"
+ },
+ {
+ "name": "Active Customers",
+ "doctype": "Number Card",
+ "document_type": "Customer",
+ "filters_json": json.dumps([["Customer", "disabled", "=", "0"]]),
+ "function": "Count",
+ "is_public": 1,
+ "label": "Active Customers",
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Monthly"
+ }
+ ]
\ No newline at end of file
diff --git a/erpnext/selling/desk_page/selling/selling.json b/erpnext/selling/desk_page/selling/selling.json
index 9ec6343..60b1532 100644
--- a/erpnext/selling/desk_page/selling/selling.json
+++ b/erpnext/selling/desk_page/selling/selling.json
@@ -2,6 +2,11 @@
"cards": [
{
"hidden": 0,
+ "label": "Selling",
+ "links": "[\n {\n \"description\": \"Customer Database.\",\n \"label\": \"Customer\",\n \"name\": \"Customer\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"Customer\"\n ],\n \"description\": \"Quotes to Leads or Customers.\",\n \"label\": \"Quotation\",\n \"name\": \"Quotation\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"Customer\"\n ],\n \"description\": \"Confirmed orders from Customers.\",\n \"label\": \"Sales Order\",\n \"name\": \"Sales Order\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"Customer\"\n ],\n \"label\": \"Sales Invoice\",\n \"name\": \"Sales Invoice\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"Customer\"\n ],\n \"description\": \"Blanket Orders from Costumers.\",\n \"label\": \"Blanket Order\",\n \"name\": \"Blanket Order\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"description\": \"Manage Sales Partners.\",\n \"label\": \"Sales Partner\",\n \"name\": \"Sales Partner\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"Customer\"\n ],\n \"description\": \"Manage Sales Person Tree.\",\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Sales Person\",\n \"link\": \"Tree/Sales Person\",\n \"name\": \"Sales Person\",\n \"type\": \"doctype\"\n }\n]"
+ },
+ {
+ "hidden": 0,
"label": "Items and Pricing",
"links": "[\n {\n \"description\": \"All Products or Services.\",\n \"label\": \"Item\",\n \"name\": \"Item\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"Price List\"\n ],\n \"description\": \"Multiple Item prices.\",\n \"label\": \"Item Price\",\n \"name\": \"Item Price\",\n \"onboard\": 1,\n \"route\": \"#Report/Item Price\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Price List master.\",\n \"label\": \"Price List\",\n \"name\": \"Price List\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Tree of Item Groups.\",\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 \"dependencies\": [\n \"Item\"\n ],\n \"description\": \"Bundle items at time of sale.\",\n \"label\": \"Product Bundle\",\n \"name\": \"Product Bundle\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Rules for applying different promotional schemes.\",\n \"label\": \"Promotional Scheme\",\n \"name\": \"Promotional Scheme\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"description\": \"Rules for applying pricing and discount.\",\n \"label\": \"Pricing Rule\",\n \"name\": \"Pricing Rule\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Rules for adding shipping costs.\",\n \"label\": \"Shipping Rule\",\n \"name\": \"Shipping Rule\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Define coupon codes.\",\n \"label\": \"Coupon Code\",\n \"name\": \"Coupon Code\",\n \"type\": \"doctype\"\n }\n]"
},
@@ -12,27 +17,23 @@
},
{
"hidden": 0,
- "label": "Other Reports",
- "links": "[\n {\n \"dependencies\": [\n \"Lead\"\n ],\n \"doctype\": \"Lead\",\n \"is_query_report\": true,\n \"label\": \"Lead Details\",\n \"name\": \"Lead Details\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Address\"\n ],\n \"doctype\": \"Address\",\n \"is_query_report\": true,\n \"label\": \"Customer Addresses And Contacts\",\n \"name\": \"Address And Contacts\",\n \"route_options\": {\n \"party_type\": \"Customer\"\n },\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"BOM\"\n ],\n \"doctype\": \"BOM\",\n \"is_query_report\": true,\n \"label\": \"BOM Search\",\n \"name\": \"BOM Search\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"doctype\": \"Item\",\n \"is_query_report\": true,\n \"label\": \"Available Stock for Packing Items\",\n \"name\": \"Available Stock for Packing Items\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Order\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Pending SO Items For Purchase Request\",\n \"name\": \"Pending SO Items For Purchase Request\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Customer\"\n ],\n \"doctype\": \"Customer\",\n \"is_query_report\": true,\n \"label\": \"Customer Credit Balance\",\n \"name\": \"Customer Credit Balance\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Customer\"\n ],\n \"doctype\": \"Customer\",\n \"is_query_report\": true,\n \"label\": \"Customers Without Any Sales Transactions\",\n \"name\": \"Customers Without Any Sales Transactions\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Customer\"\n ],\n \"doctype\": \"Customer\",\n \"is_query_report\": true,\n \"label\": \"Sales Partners Commission\",\n \"name\": \"Sales Partners Commission\",\n \"type\": \"report\"\n }\n]"
- },
- {
- "hidden": 0,
- "label": "Sales",
- "links": "[\n {\n \"description\": \"Customer Database.\",\n \"label\": \"Customer\",\n \"name\": \"Customer\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"Customer\"\n ],\n \"description\": \"Quotes to Leads or Customers.\",\n \"label\": \"Quotation\",\n \"name\": \"Quotation\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"Customer\"\n ],\n \"description\": \"Confirmed orders from Customers.\",\n \"label\": \"Sales Order\",\n \"name\": \"Sales Order\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"Customer\"\n ],\n \"description\": \"Invoices for Costumers.\",\n \"label\": \"Sales Invoice\",\n \"name\": \"Sales Invoice\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"Customer\"\n ],\n \"description\": \"Blanket Orders from Costumers.\",\n \"label\": \"Blanket Order\",\n \"name\": \"Blanket Order\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"description\": \"Manage Sales Partners.\",\n \"label\": \"Sales Partner\",\n \"name\": \"Sales Partner\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Item\",\n \"Customer\"\n ],\n \"description\": \"Manage Sales Person Tree.\",\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Sales Person\",\n \"link\": \"Tree/Sales Person\",\n \"name\": \"Sales Person\",\n \"type\": \"doctype\"\n }\n]"
- },
- {
- "hidden": 0,
"label": "Key Reports",
- "links": "[\n {\n \"dependencies\": [\n \"Sales Order\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Sales Analytics\",\n \"name\": \"Sales Analytics\",\n \"onboard\": 1,\n \"type\": \"report\"\n },\n {\n \"icon\": \"fa fa-bar-chart\",\n \"label\": \"Sales Funnel\",\n \"name\": \"sales-funnel\",\n \"onboard\": 1,\n \"type\": \"page\"\n },\n {\n \"dependencies\": [\n \"Customer\"\n ],\n \"doctype\": \"Customer\",\n \"icon\": \"fa fa-bar-chart\",\n \"is_query_report\": true,\n \"label\": \"Customer Acquisition and Loyalty\",\n \"name\": \"Customer Acquisition and Loyalty\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Order\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Inactive Customers\",\n \"name\": \"Inactive Customers\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Order\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Ordered Items To Be Delivered\",\n \"name\": \"Ordered Items To Be Delivered\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Order\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Sales Person-wise Transaction Summary\",\n \"name\": \"Sales Person-wise Transaction Summary\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"doctype\": \"Item\",\n \"is_query_report\": true,\n \"label\": \"Item-wise Sales History\",\n \"name\": \"Item-wise Sales History\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Quotation\"\n ],\n \"doctype\": \"Quotation\",\n \"is_query_report\": true,\n \"label\": \"Quotation Trends\",\n \"name\": \"Quotation Trends\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Order\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Sales Order Trends\",\n \"name\": \"Sales Order Trends\",\n \"type\": \"report\"\n }\n]"
+ "links": "[\n {\n \"dependencies\": [\n \"Sales Order\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Sales Analytics\",\n \"name\": \"Sales Analytics\",\n \"onboard\": 1,\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Order\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Sales Order Analysis\",\n \"name\": \"Sales Order Analysis\",\n \"onboard\": 1,\n \"type\": \"report\"\n },\n {\n \"icon\": \"fa fa-bar-chart\",\n \"label\": \"Sales Funnel\",\n \"name\": \"sales-funnel\",\n \"onboard\": 1,\n \"type\": \"page\"\n },\n {\n \"dependencies\": [\n \"Sales Order\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Sales Order Trends\",\n \"name\": \"Sales Order Trends\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Quotation\"\n ],\n \"doctype\": \"Quotation\",\n \"is_query_report\": true,\n \"label\": \"Quotation Trends\",\n \"name\": \"Quotation Trends\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Customer\"\n ],\n \"doctype\": \"Customer\",\n \"icon\": \"fa fa-bar-chart\",\n \"is_query_report\": true,\n \"label\": \"Customer Acquisition and Loyalty\",\n \"name\": \"Customer Acquisition and Loyalty\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Order\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Inactive Customers\",\n \"name\": \"Inactive Customers\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Order\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Sales Person-wise Transaction Summary\",\n \"name\": \"Sales Person-wise Transaction Summary\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"doctype\": \"Item\",\n \"is_query_report\": true,\n \"label\": \"Item-wise Sales History\",\n \"name\": \"Item-wise Sales History\",\n \"type\": \"report\"\n }\n]"
+ },
+ {
+ "hidden": 0,
+ "label": "Other Reports",
+ "links": "[\n {\n \"dependencies\": [\n \"Lead\"\n ],\n \"doctype\": \"Lead\",\n \"is_query_report\": true,\n \"label\": \"Lead Details\",\n \"name\": \"Lead Details\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Address\"\n ],\n \"doctype\": \"Address\",\n \"is_query_report\": true,\n \"label\": \"Customer Addresses And Contacts\",\n \"name\": \"Address And Contacts\",\n \"route_options\": {\n \"party_type\": \"Customer\"\n },\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"doctype\": \"Item\",\n \"is_query_report\": true,\n \"label\": \"Available Stock for Packing Items\",\n \"name\": \"Available Stock for Packing Items\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Order\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Pending SO Items For Purchase Request\",\n \"name\": \"Pending SO Items For Purchase Request\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Customer\"\n ],\n \"doctype\": \"Customer\",\n \"is_query_report\": true,\n \"label\": \"Customer Credit Balance\",\n \"name\": \"Customer Credit Balance\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Customer\"\n ],\n \"doctype\": \"Customer\",\n \"is_query_report\": true,\n \"label\": \"Customers Without Any Sales Transactions\",\n \"name\": \"Customers Without Any Sales Transactions\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Customer\"\n ],\n \"doctype\": \"Customer\",\n \"is_query_report\": true,\n \"label\": \"Sales Partners Commission\",\n \"name\": \"Sales Partners Commission\",\n \"type\": \"report\"\n }\n]"
}
],
"category": "Modules",
"charts": [
{
- "chart_name": "Incoming Bills (Purchase Invoice)",
- "label": "Income"
+ "chart_name": "Sales Order Trends",
+ "label": "Sales Order Trends"
}
],
+ "charts_label": "Selling ",
"creation": "2020-01-28 11:49:12.092882",
"developer_mode_only": 0,
"disable_user_customization": 0,
@@ -43,52 +44,49 @@
"idx": 0,
"is_standard": 1,
"label": "Selling",
- "modified": "2020-06-03 13:23:24.861706",
+ "modified": "2020-06-19 13:23:24.861706",
"modified_by": "Administrator",
"module": "Selling",
"name": "Selling",
+ "onboarding": "Selling",
"owner": "Administrator",
"pin_to_bottom": 0,
"pin_to_top": 0,
"shortcuts": [
{
- "color": "#ffe8cd",
- "format": "{} Draft",
- "label": "Sales Invoice",
- "link_to": "Sales Invoice",
- "stats_filter": "{ \"status\": \"Draft\" }",
+ "color": "#cef6d1",
+ "format": "{} Available",
+ "label": "Item",
+ "link_to": "Item",
+ "stats_filter": "{\n \"disabled\":0\n}",
"type": "DocType"
},
{
"color": "#ffe8cd",
- "format": "{} To Deliver",
+ "format": "{} To Deliver",
"label": "Sales Order",
"link_to": "Sales Order",
- "stats_filter": "{\"Status\": \"To Deliver and Bill\"}",
+ "stats_filter": "{\n \"company\": [\"like\", '%' + frappe.defaults.get_global_default(\"company\") + '%'],\n \"status\":[\"in\", [\"To Deliver\", \"To Deliver and Bill\"]]\n}",
"type": "DocType"
},
{
"color": "#cef6d1",
"format": "{} Open",
- "label": "Quotation",
- "link_to": "Quotation",
+ "label": "Sales Analytics",
+ "link_to": "Sales Analytics",
"stats_filter": "{ \"Status\": \"Open\" }",
- "type": "DocType"
- },
- {
- "label": "Delivery Note",
- "link_to": "Delivery Note",
- "type": "DocType"
- },
- {
- "label": "Accounts Receivable",
- "link_to": "Accounts Receivable",
"type": "Report"
},
{
- "label": "Sales Register",
- "link_to": "Sales Register",
+ "label": "Sales Order Analysis",
+ "link_to": "Sales Order Analysis",
"type": "Report"
+ },
+ {
+ "label": "Dashboard",
+ "link_to": "Selling",
+ "type": "Dashboard"
}
- ]
+ ],
+ "shortcuts_label": "Quick Access"
}
\ No newline at end of file
diff --git a/erpnext/selling/doctype/selling_settings/selling_settings.js b/erpnext/selling/doctype/selling_settings/selling_settings.js
index cf6fb28..95a4243 100644
--- a/erpnext/selling/doctype/selling_settings/selling_settings.js
+++ b/erpnext/selling/doctype/selling_settings/selling_settings.js
@@ -6,3 +6,26 @@
}
});
+
+frappe.tour['Selling Settings'] = [
+ {
+ fieldname: "cust_master_name",
+ title: "Customer Naming By",
+ description: __("By default, the Customer Name is set as per the Full Name entered. If you want Customers to be named by a ") + "<a href='https://docs.erpnext.com/docs/user/manual/en/setting-up/settings/naming-series' target='_blank'>Naming Series</a>" + __(" choose the 'Naming Series' option."),
+ },
+ {
+ fieldname: "selling_price_list",
+ title: "Default Selling Price List",
+ description: __("Configure the default Price List when creating a new Sales transaction. Item prices will be fetched from this Price List.")
+ },
+ {
+ fieldname: "so_required",
+ title: "Sales Order Required for Sales Invoice & Delivery Note Creation",
+ description: __("If this option is configured 'Yes', ERPNext will prevent you from creating a Sales Invoice or Delivery Note without creating a Sales Order first. This configuration can be overridden for a particular Customer by enabling the 'Allow Sales Invoice Creation Without Sales Order' checkbox in the Customer master.")
+ },
+ {
+ fieldname: "dn_required",
+ title: "Delivery Note Required for Sales Invoice Creation",
+ description: __("If this option is configured 'Yes', ERPNext will prevent you from creating a Sales Invoice without creating a Delivery Note first. This configuration can be overridden for a particular Customer by enabling the 'Allow Sales Invoice Creation Without Delivery Note' checkbox in the Customer master.")
+ }
+];
\ No newline at end of file
diff --git a/erpnext/selling/doctype/selling_settings/selling_settings.json b/erpnext/selling/doctype/selling_settings/selling_settings.json
index c04bfd2..dcbc074 100644
--- a/erpnext/selling/doctype/selling_settings/selling_settings.json
+++ b/erpnext/selling/doctype/selling_settings/selling_settings.json
@@ -1,4 +1,5 @@
{
+ "actions": [],
"creation": "2013-06-25 10:25:16",
"description": "Settings for Selling Module",
"doctype": "DocType",
@@ -79,13 +80,13 @@
{
"fieldname": "so_required",
"fieldtype": "Select",
- "label": "Sales Order Required",
+ "label": "Sales Order Required for Sales Invoice & Delivery Note Creation",
"options": "No\nYes"
},
{
"fieldname": "dn_required",
"fieldtype": "Select",
- "label": "Delivery Note Required",
+ "label": "Delivery Note Required for Sales Invoice Creation",
"options": "No\nYes"
},
{
@@ -137,7 +138,8 @@
"icon": "fa fa-cog",
"idx": 1,
"issingle": 1,
- "modified": "2019-12-09 13:38:36.486298",
+ "links": [],
+ "modified": "2020-06-01 13:58:35.637858",
"modified_by": "Administrator",
"module": "Selling",
"name": "Selling Settings",
diff --git a/erpnext/selling/module_onboarding/selling/selling.json b/erpnext/selling/module_onboarding/selling/selling.json
new file mode 100644
index 0000000..10a33c9
--- /dev/null
+++ b/erpnext/selling/module_onboarding/selling/selling.json
@@ -0,0 +1,54 @@
+{
+ "allow_roles": [
+ {
+ "role": "Sales Manager"
+ },
+ {
+ "role": "Sales User"
+ },
+ {
+ "role": "Stock Manager"
+ },
+ {
+ "role": "Stock User"
+ }
+ ],
+ "creation": "2020-06-01 12:44:42.589930",
+ "docstatus": 0,
+ "doctype": "Module Onboarding",
+ "documentation_url": "https://docs.erpnext.com/docs/user/manual/en/selling",
+ "idx": 0,
+ "is_complete": 0,
+ "modified": "2020-06-01 13:35:16.100512",
+ "modified_by": "Administrator",
+ "module": "Selling",
+ "name": "Selling",
+ "owner": "Administrator",
+ "steps": [
+ {
+ "step": "Introduction to Selling"
+ },
+ {
+ "step": "Create a Customer"
+ },
+ {
+ "step": "Setup your Warehouse"
+ },
+ {
+ "step": "Create a Product"
+ },
+ {
+ "step": "Create a Quotation"
+ },
+ {
+ "step": "Create your first Sales Order"
+ },
+ {
+ "step": "Selling Settings"
+ }
+ ],
+ "subtitle": "Products, Sales, Analysis and more.",
+ "success_message": "The Selling Module is all set up!",
+ "title": "Let's Set Up the Selling Module.",
+ "user_can_dismiss": 1
+}
\ No newline at end of file
diff --git a/erpnext/selling/onboarding_step/create_a_customer/create_a_customer.json b/erpnext/selling/onboarding_step/create_a_customer/create_a_customer.json
new file mode 100644
index 0000000..5a403b0
--- /dev/null
+++ b/erpnext/selling/onboarding_step/create_a_customer/create_a_customer.json
@@ -0,0 +1,19 @@
+{
+ "action": "Create Entry",
+ "creation": "2020-05-14 17:46:41.831517",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "idx": 0,
+ "is_complete": 0,
+ "is_mandatory": 0,
+ "is_single": 0,
+ "is_skipped": 0,
+ "modified": "2020-06-01 13:16:19.731719",
+ "modified_by": "Administrator",
+ "name": "Create a Customer",
+ "owner": "Administrator",
+ "reference_document": "Customer",
+ "show_full_form": 0,
+ "title": "Create a Customer",
+ "validate_action": 1
+}
\ No newline at end of file
diff --git a/erpnext/selling/onboarding_step/create_a_product/create_a_product.json b/erpnext/selling/onboarding_step/create_a_product/create_a_product.json
new file mode 100644
index 0000000..d2068e1
--- /dev/null
+++ b/erpnext/selling/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/selling/onboarding_step/create_a_quotation/create_a_quotation.json b/erpnext/selling/onboarding_step/create_a_quotation/create_a_quotation.json
new file mode 100644
index 0000000..27253d1
--- /dev/null
+++ b/erpnext/selling/onboarding_step/create_a_quotation/create_a_quotation.json
@@ -0,0 +1,19 @@
+{
+ "action": "Create Entry",
+ "creation": "2020-06-01 13:34:58.958641",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "idx": 0,
+ "is_complete": 0,
+ "is_mandatory": 0,
+ "is_single": 0,
+ "is_skipped": 0,
+ "modified": "2020-06-01 13:34:58.958641",
+ "modified_by": "Administrator",
+ "name": "Create a Quotation",
+ "owner": "Administrator",
+ "reference_document": "Quotation",
+ "show_full_form": 1,
+ "title": "Create a Quotation",
+ "validate_action": 1
+}
\ No newline at end of file
diff --git a/erpnext/selling/onboarding_step/create_product/create_product.json b/erpnext/selling/onboarding_step/create_product/create_product.json
new file mode 100644
index 0000000..0ffa301
--- /dev/null
+++ b/erpnext/selling/onboarding_step/create_product/create_product.json
@@ -0,0 +1,19 @@
+{
+ "action": "Create Entry",
+ "creation": "2020-05-05 16:42:31.476275",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "idx": 0,
+ "is_complete": 0,
+ "is_mandatory": 1,
+ "is_single": 0,
+ "is_skipped": 0,
+ "modified": "2020-05-19 12:50:59.010439",
+ "modified_by": "Administrator",
+ "name": "Create Product",
+ "owner": "Administrator",
+ "reference_document": "Item",
+ "show_full_form": 0,
+ "title": "Create a Finished Good",
+ "validate_action": 1
+}
\ No newline at end of file
diff --git a/erpnext/selling/onboarding_step/create_your_first_sales_order/create_your_first_sales_order.json b/erpnext/selling/onboarding_step/create_your_first_sales_order/create_your_first_sales_order.json
new file mode 100644
index 0000000..5b601a7
--- /dev/null
+++ b/erpnext/selling/onboarding_step/create_your_first_sales_order/create_your_first_sales_order.json
@@ -0,0 +1,19 @@
+{
+ "action": "Create Entry",
+ "creation": "2020-06-01 12:52:27.181841",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "idx": 0,
+ "is_complete": 0,
+ "is_mandatory": 1,
+ "is_single": 0,
+ "is_skipped": 0,
+ "modified": "2020-06-01 12:52:27.181841",
+ "modified_by": "Administrator",
+ "name": "Create your first Sales Order",
+ "owner": "Administrator",
+ "reference_document": "Sales Order",
+ "show_full_form": 1,
+ "title": "Create your first Sales Order",
+ "validate_action": 1
+}
\ No newline at end of file
diff --git a/erpnext/selling/onboarding_step/introduction_to_selling/introduction_to_selling.json b/erpnext/selling/onboarding_step/introduction_to_selling/introduction_to_selling.json
new file mode 100644
index 0000000..d21c1f4
--- /dev/null
+++ b/erpnext/selling/onboarding_step/introduction_to_selling/introduction_to_selling.json
@@ -0,0 +1,19 @@
+{
+ "action": "Watch Video",
+ "creation": "2020-06-01 12:44:32.089234",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "idx": 0,
+ "is_complete": 0,
+ "is_mandatory": 0,
+ "is_single": 0,
+ "is_skipped": 0,
+ "modified": "2020-06-01 13:29:13.703177",
+ "modified_by": "Administrator",
+ "name": "Introduction to Selling",
+ "owner": "Administrator",
+ "show_full_form": 0,
+ "title": "Introduction to Selling",
+ "validate_action": 1,
+ "video_url": "https://youtu.be/1eP90MWoDQM"
+}
\ No newline at end of file
diff --git a/erpnext/selling/onboarding_step/selling_settings/selling_settings.json b/erpnext/selling/onboarding_step/selling_settings/selling_settings.json
new file mode 100644
index 0000000..7996d7b
--- /dev/null
+++ b/erpnext/selling/onboarding_step/selling_settings/selling_settings.json
@@ -0,0 +1,19 @@
+{
+ "action": "Show Form Tour",
+ "creation": "2020-06-01 13:01:45.615189",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "idx": 0,
+ "is_complete": 0,
+ "is_mandatory": 0,
+ "is_single": 1,
+ "is_skipped": 0,
+ "modified": "2020-06-01 13:04:14.980743",
+ "modified_by": "Administrator",
+ "name": "Selling Settings",
+ "owner": "Administrator",
+ "reference_document": "Selling Settings",
+ "show_full_form": 0,
+ "title": "Configure Selling Settings.",
+ "validate_action": 0
+}
\ No newline at end of file
diff --git a/erpnext/selling/onboarding_step/setup_your_warehouse/setup_your_warehouse.json b/erpnext/selling/onboarding_step/setup_your_warehouse/setup_your_warehouse.json
new file mode 100644
index 0000000..557c905
--- /dev/null
+++ b/erpnext/selling/onboarding_step/setup_your_warehouse/setup_your_warehouse.json
@@ -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
+}
\ No newline at end of file
diff --git a/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.js b/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.js
index daca2e3..f47d67f 100644
--- a/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.js
+++ b/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.js
@@ -13,12 +13,6 @@
reqd: 1
},
{
- fieldname:"item_group",
- label: __("Item Group"),
- fieldtype: "Link",
- options: "Item Group"
- },
- {
fieldname:"from_date",
reqd: 1,
label: __("From Date"),
@@ -32,6 +26,38 @@
label: __("To Date"),
fieldtype: "Date",
},
+ {
+ fieldname:"item_group",
+ label: __("Item Group"),
+ fieldtype: "Link",
+ options: "Item Group"
+ },
+ {
+ fieldname:"item_code",
+ label: __("Item"),
+ fieldtype: "Link",
+ options: "Item",
+ get_query: () => {
+ return {
+ query: "erpnext.controllers.queries.item_query"
+ }
+ }
+ },
+ {
+ fieldname:"customer",
+ label: __("Customer"),
+ fieldtype: "Link",
+ options: "Customer"
+ }
+ ],
- ]
+ "formatter": function (value, row, column, data, default_formatter) {
+ value = default_formatter(value, row, column, data);
+ let format_fields = ["delivered_quantity", "billed_amount"];
+
+ if (in_list(format_fields, column.fieldname) && data && data[column.fieldname] > 0) {
+ value = "<span style='color:green;'>" + value + "</span>";
+ }
+ return value;
+ }
};
\ No newline at end of file
diff --git a/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py b/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py
index 08a98ba..bd59be6 100644
--- a/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py
+++ b/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py
@@ -11,7 +11,10 @@
filters = frappe._dict(filters or {})
columns = get_columns(filters)
data = get_data(filters)
- return columns, data
+
+ chart_data = get_chart_data(data)
+
+ return columns, data, None, chart_data
def get_columns(filters):
return [
@@ -181,6 +184,12 @@
if filters.get('to_date'):
conditions += "AND so.transaction_date <= '%s'" %filters.to_date
+ if filters.get("item_code"):
+ conditions += "AND so_item.item_code = '%s'" %frappe.db.escape(filters.item_code)
+
+ if filters.get("customer"):
+ conditions += "AND so.customer = '%s'" %frappe.db.escape(filters.customer)
+
return conditions
def get_customer_details():
@@ -212,3 +221,34 @@
AND so.company in ({0})
AND so.docstatus = 1 {1}
""".format(','.join(["%s"] * len(company_list)), conditions), tuple(company_list), as_dict=1)
+
+def get_chart_data(data):
+ item_wise_sales_map = {}
+ labels, datapoints = [], []
+
+ for row in data:
+ item_key = row.get("item_code")
+
+ if not item_key in item_wise_sales_map:
+ item_wise_sales_map[item_key] = 0
+
+ item_wise_sales_map[item_key] = flt(item_wise_sales_map[item_key]) + flt(row.get("amount"))
+
+ item_wise_sales_map = { item: value for item, value in (sorted(item_wise_sales_map.items(), key = lambda i: i[1], reverse=True))}
+
+ for key in item_wise_sales_map:
+ labels.append(key)
+ datapoints.append(item_wise_sales_map[key])
+
+ return {
+ "data" : {
+ "labels" : labels[:30], # show max of 30 items in chart
+ "datasets" : [
+ {
+ "name" : _(" Total Sales Amount"),
+ "values" : datapoints[:30]
+ }
+ ]
+ },
+ "type" : "bar"
+ }
\ No newline at end of file
diff --git a/erpnext/selling/report/quotation_trends/quotation_trends.py b/erpnext/selling/report/quotation_trends/quotation_trends.py
index 67375f9..968e2ff 100644
--- a/erpnext/selling/report/quotation_trends/quotation_trends.py
+++ b/erpnext/selling/report/quotation_trends/quotation_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,48 @@
conditions = get_columns(filters, "Quotation")
data = get_data(filters, conditions)
- return conditions["columns"], data
\ No newline at end of file
+ chart_data = get_chart_data(data, conditions, filters)
+
+ return conditions["columns"], data, None, chart_data
+
+def get_chart_data(data, conditions, filters):
+ if not (data and conditions):
+ return []
+
+ datapoints = []
+
+ start = 2 if filters.get("based_on") in ["Item", "Customer"] else 1
+ if filters.get("group_by"):
+ start += 1
+
+ # fetch only periodic columns as labels
+ columns = conditions.get("columns")[start:-2][1::2]
+ labels = [column.split(':')[0] for column in columns]
+ datapoints = [0] * len(labels)
+
+ for row in data:
+ # If group by filter, don't add first row of group (it's already summed)
+ if not row[start-1]:
+ continue
+ # Remove None values and compute only periodic data
+ row = [x if x else 0 for x in row[start:-2]]
+ row = row[1::2]
+
+ for i in range(len(row)):
+ datapoints[i] += row[i]
+
+ return {
+ "data" : {
+ "labels" : labels,
+ "datasets" : [
+ {
+ "name" : _("{0}").format(filters.get("period")) + _(" Quoted Amount"),
+ "values" : datapoints
+ }
+ ]
+ },
+ "type" : "line",
+ "lineOptions": {
+ "regionFill": 1
+ }
+ }
diff --git a/erpnext/accounts/report/ordered_items_to_be_billed/__init__.py b/erpnext/selling/report/sales_order_analysis/__init__.py
similarity index 100%
rename from erpnext/accounts/report/ordered_items_to_be_billed/__init__.py
rename to erpnext/selling/report/sales_order_analysis/__init__.py
diff --git a/erpnext/selling/report/sales_order_analysis/sales_order_analysis.js b/erpnext/selling/report/sales_order_analysis/sales_order_analysis.js
new file mode 100644
index 0000000..76a5bb5
--- /dev/null
+++ b/erpnext/selling/report/sales_order_analysis/sales_order_analysis.js
@@ -0,0 +1,85 @@
+// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+frappe.query_reports["Sales Order Analysis"] = {
+ "filters": [
+ {
+ "fieldname": "company",
+ "label": __("Company"),
+ "fieldtype": "Link",
+ "width": "80",
+ "options": "Company",
+ "reqd": 1,
+ "default": frappe.defaults.get_default("company")
+ },
+ {
+ "fieldname":"from_date",
+ "label": __("From Date"),
+ "fieldtype": "Date",
+ "width": "80",
+ "reqd": 1,
+ "default": frappe.datetime.add_months(frappe.datetime.get_today(), -1),
+ },
+ {
+ "fieldname":"to_date",
+ "label": __("To Date"),
+ "fieldtype": "Date",
+ "width": "80",
+ "reqd": 1,
+ "default": frappe.datetime.get_today()
+ },
+ {
+ "fieldname": "sales_order",
+ "label": __("Sales Order"),
+ "fieldtype": "MultiSelectList",
+ "width": "80",
+ "options": "Sales Order",
+ "get_data": function(txt) {
+ return frappe.db.get_link_options("Sales Order", txt);
+ },
+ "get_query": () =>{
+ return {
+ filters: { "docstatus": 1 }
+ }
+ }
+ },
+ {
+ "fieldname": "status",
+ "label": __("Status"),
+ "fieldtype": "MultiSelectList",
+ "width": "80",
+ get_data: function(txt) {
+ let status = ["To Bill", "To Deliver", "To Deliver and Bill", "Completed"]
+ let options = []
+ for (let option of status){
+ options.push({
+ "value": option,
+ "description": ""
+ })
+ }
+ return options
+ }
+ },
+ {
+ "fieldname": "group_by_so",
+ "label": __("Group by Sales Order"),
+ "fieldtype": "Check",
+ "default": 0
+ }
+ ],
+
+ "formatter": function (value, row, column, data, default_formatter) {
+ value = default_formatter(value, row, column, data);
+ let format_fields = ["delivered_qty", "billed_amount"];
+
+ if (in_list(format_fields, column.fieldname) && data && data[column.fieldname] > 0) {
+ value = "<span style='color:green;'>" + value + "</span>";
+ }
+
+ if (column.fieldname == "delay" && data && data[column.fieldname] > 0) {
+ value = "<span style='color:red;'>" + value + "</span>";
+ }
+ return value;
+ }
+};
diff --git a/erpnext/selling/report/sales_order_analysis/sales_order_analysis.json b/erpnext/selling/report/sales_order_analysis/sales_order_analysis.json
new file mode 100644
index 0000000..c0b1d9a
--- /dev/null
+++ b/erpnext/selling/report/sales_order_analysis/sales_order_analysis.json
@@ -0,0 +1,36 @@
+{
+ "add_total_row": 1,
+ "creation": "2020-05-29 14:54:53.591445",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "idx": 0,
+ "is_standard": "Yes",
+ "modified": "2020-05-29 14:54:53.591445",
+ "modified_by": "Administrator",
+ "module": "Selling",
+ "name": "Sales Order Analysis",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "Sales Order",
+ "report_name": "Sales Order Analysis",
+ "report_type": "Script Report",
+ "roles": [
+ {
+ "role": "Sales User"
+ },
+ {
+ "role": "Sales Manager"
+ },
+ {
+ "role": "Maintenance User"
+ },
+ {
+ "role": "Accounts User"
+ },
+ {
+ "role": "Stock User"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/erpnext/selling/report/sales_order_analysis/sales_order_analysis.py b/erpnext/selling/report/sales_order_analysis/sales_order_analysis.py
new file mode 100644
index 0000000..7e8e6e9
--- /dev/null
+++ b/erpnext/selling/report/sales_order_analysis/sales_order_analysis.py
@@ -0,0 +1,279 @@
+# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+import copy
+from frappe import _
+from frappe.utils import flt, date_diff, getdate
+
+def execute(filters=None):
+ if not filters:
+ return [], [], None, []
+
+ validate_filters(filters)
+
+ columns = get_columns(filters)
+ conditions = get_conditions(filters)
+ data = get_data(conditions, filters)
+
+ if not data:
+ return [], [], None, []
+
+ data, chart_data = prepare_data(data, filters)
+
+ return columns, data, None, chart_data
+
+def validate_filters(filters):
+ from_date, to_date = filters.get("from_date"), filters.get("to_date")
+
+ if not from_date and to_date:
+ frappe.throw(_("From and To Dates are required."))
+ elif date_diff(to_date, from_date) < 0:
+ frappe.throw(_("To Date cannot be before From Date."))
+
+def get_conditions(filters):
+ conditions = ""
+ if filters.get("from_date") and filters.get("to_date"):
+ conditions += " and so.transaction_date between %(from_date)s and %(to_date)s"
+
+ if filters.get("company"):
+ conditions += " and so.company = %(company)s"
+
+ if filters.get("sales_order"):
+ conditions += " and so.name in %(sales_order)s"
+
+ if filters.get("status"):
+ conditions += " and so.status in %(status)s"
+
+ return conditions
+
+def get_data(conditions, filters):
+ data = frappe.db.sql("""
+ SELECT
+ so.transaction_date as date,
+ soi.delivery_date as delivery_date,
+ so.name as sales_order,
+ so.status, so.customer, soi.item_code,
+ DATEDIFF(CURDATE(), soi.delivery_date) as delay_days,
+ IF(so.status in ('Completed','To Bill'), 0, (SELECT delay_days)) as delay,
+ soi.qty, soi.delivered_qty,
+ (soi.qty - soi.delivered_qty) AS pending_qty,
+ IFNULL(sii.qty, 0) as billed_qty,
+ soi.base_amount as amount,
+ (soi.delivered_qty * soi.base_rate) as delivered_qty_amount,
+ (soi.billed_amt * IFNULL(so.conversion_rate, 1)) as billed_amount,
+ (soi.base_amount - (soi.billed_amt * IFNULL(so.conversion_rate, 1))) as pending_amount,
+ soi.warehouse as warehouse,
+ so.company, soi.name
+ FROM
+ `tabSales Order` so,
+ `tabSales Order Item` soi
+ LEFT JOIN `tabSales Invoice Item` sii
+ ON sii.so_detail = soi.name
+ WHERE
+ soi.parent = so.name
+ and so.status not in ('Stopped', 'Closed', 'On Hold')
+ and so.docstatus = 1
+ {conditions}
+ GROUP BY soi.name
+ ORDER BY so.transaction_date ASC
+ """.format(conditions=conditions), filters, as_dict=1)
+
+ return data
+
+def prepare_data(data, filters):
+ completed, pending = 0, 0
+
+ if filters.get("group_by_so"):
+ sales_order_map = {}
+
+ for row in data:
+ # sum data for chart
+ completed += row["billed_amount"]
+ pending += row["pending_amount"]
+
+ # prepare data for report view
+ row["qty_to_bill"] = flt(row["qty"]) - flt(row["billed_qty"])
+
+ row["delay"] = 0 if row["delay"] < 0 else row["delay"]
+ if filters.get("group_by_so"):
+ so_name = row["sales_order"]
+
+ if not so_name in sales_order_map:
+ # create an entry
+ row_copy = copy.deepcopy(row)
+ sales_order_map[so_name] = row_copy
+ else:
+ # update existing entry
+ so_row = sales_order_map[so_name]
+ so_row["required_date"] = max(getdate(so_row["delivery_date"]), getdate(row["delivery_date"]))
+ so_row["delay"] = min(so_row["delay"], row["delay"])
+
+ # sum numeric columns
+ fields = ["qty", "delivered_qty", "pending_qty", "billed_qty", "qty_to_bill", "amount",
+ "delivered_qty_amount", "billed_amount", "pending_amount"]
+ for field in fields:
+ so_row[field] = flt(row[field]) + flt(so_row[field])
+
+ chart_data = prepare_chart_data(pending, completed)
+
+ if filters.get("group_by_so"):
+ data = []
+ for so in sales_order_map:
+ data.append(sales_order_map[so])
+ return data, chart_data
+
+ return data, chart_data
+
+def prepare_chart_data(pending, completed):
+ labels = ["Amount to Bill", "Billed Amount"]
+
+ return {
+ "data" : {
+ "labels": labels,
+ "datasets": [
+ {"values": [pending, completed]}
+ ]
+ },
+ "type": 'donut',
+ "height": 300
+ }
+
+def get_columns(filters):
+ columns = [
+ {
+ "label":_("Date"),
+ "fieldname": "date",
+ "fieldtype": "Date",
+ "width": 90
+ },
+ {
+ "label": _("Sales Order"),
+ "fieldname": "sales_order",
+ "fieldtype": "Link",
+ "options": "Sales Order",
+ "width": 160
+ },
+ {
+ "label":_("Status"),
+ "fieldname": "status",
+ "fieldtype": "Data",
+ "width": 130
+ },
+ {
+ "label": _("Customer"),
+ "fieldname": "customer",
+ "fieldtype": "Link",
+ "options": "Customer",
+ "width": 130
+ }]
+
+ if not filters.get("group_by_so"):
+ columns.append({
+ "label":_("Item Code"),
+ "fieldname": "item_code",
+ "fieldtype": "Link",
+ "options": "Item",
+ "width": 100
+ })
+
+ columns.extend([
+ {
+ "label": _("Qty"),
+ "fieldname": "qty",
+ "fieldtype": "Float",
+ "width": 120,
+ "convertible": "qty"
+ },
+ {
+ "label": _("Delivered Qty"),
+ "fieldname": "delivered_qty",
+ "fieldtype": "Float",
+ "width": 120,
+ "convertible": "qty"
+ },
+ {
+ "label": _("Qty to Deliver"),
+ "fieldname": "pending_qty",
+ "fieldtype": "Float",
+ "width": 120,
+ "convertible": "qty"
+ },
+ {
+ "label": _("Billed Qty"),
+ "fieldname": "billed_qty",
+ "fieldtype": "Float",
+ "width": 80,
+ "convertible": "qty"
+ },
+ {
+ "label": _("Qty to Bill"),
+ "fieldname": "qty_to_bill",
+ "fieldtype": "Float",
+ "width": 80,
+ "convertible": "qty"
+ },
+ {
+ "label": _("Amount"),
+ "fieldname": "amount",
+ "fieldtype": "Currency",
+ "width": 110,
+ "options": "Company:company:default_currency",
+ "convertible": "rate"
+ },
+ {
+ "label": _("Billed Amount"),
+ "fieldname": "billed_amount",
+ "fieldtype": "Currency",
+ "width": 110,
+ "options": "Company:company:default_currency",
+ "convertible": "rate"
+ },
+ {
+ "label": _("Pending Amount"),
+ "fieldname": "pending_amount",
+ "fieldtype": "Currency",
+ "width": 130,
+ "options": "Company:company:default_currency",
+ "convertible": "rate"
+ },
+ {
+ "label": _("Amount Delivered"),
+ "fieldname": "delivered_qty_amount",
+ "fieldtype": "Currency",
+ "width": 100,
+ "options": "Company:company:default_currency",
+ "convertible": "rate"
+ },
+ {
+ "label":_("Delivery Date"),
+ "fieldname": "delivery_date",
+ "fieldtype": "Date",
+ "width": 120
+ },
+ {
+ "label": _("Delay (in Days)"),
+ "fieldname": "delay",
+ "fieldtype": "Data",
+ "width": 100
+ }
+ ])
+ if not filters.get("group_by_so"):
+ columns.append({
+ "label": _("Warehouse"),
+ "fieldname": "warehouse",
+ "fieldtype": "Link",
+ "options": "Warehouse",
+ "width": 100
+ })
+ columns.append({
+ "label": _("Company"),
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "options": "Company",
+ "width": 100
+ })
+
+
+ return columns
\ No newline at end of file
diff --git a/erpnext/selling/report/sales_order_trends/sales_order_trends.py b/erpnext/selling/report/sales_order_trends/sales_order_trends.py
index c0a0f08..de7d3f2 100644
--- a/erpnext/selling/report/sales_order_trends/sales_order_trends.py
+++ b/erpnext/selling/report/sales_order_trends/sales_order_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,4 +11,48 @@
data = []
conditions = get_columns(filters, "Sales Order")
data = get_data(filters, conditions)
- return conditions["columns"], data
+ chart_data = get_chart_data(data, conditions, filters)
+
+ return conditions["columns"], data, None, chart_data
+
+def get_chart_data(data, conditions, filters):
+ if not (data and conditions):
+ return []
+
+ datapoints = []
+
+ start = 2 if filters.get("based_on") in ["Item", "Customer"] else 1
+ if filters.get("group_by"):
+ start += 1
+
+ # fetch only periodic columns as labels
+ columns = conditions.get("columns")[start:-2][1::2]
+ labels = [column.split(':')[0] for column in columns]
+ datapoints = [0] * len(labels)
+
+ for row in data:
+ # If group by filter, don't add first row of group (it's already summed)
+ if not row[start-1]:
+ continue
+ # Remove None values and compute only periodic data
+ row = [x if x else 0 for x in row[start:-2]]
+ row = row[1::2]
+
+ for i in range(len(row)):
+ datapoints[i] += row[i]
+
+ return {
+ "data" : {
+ "labels" : labels,
+ "datasets" : [
+ {
+ "name" : _("{0}").format(filters.get("period")) + _(" Sales Value"),
+ "values" : datapoints
+ }
+ ]
+ },
+ "type" : "line",
+ "lineOptions": {
+ "regionFill": 1
+ }
+ }
diff --git a/erpnext/stock/desk_page/stock/stock.json b/erpnext/stock/desk_page/stock/stock.json
index 9404292..1bf81f7 100644
--- a/erpnext/stock/desk_page/stock/stock.json
+++ b/erpnext/stock/desk_page/stock/stock.json
@@ -33,7 +33,7 @@
{
"hidden": 0,
"label": "Key Reports",
- "links": "[\n {\n \"dependencies\": [\n \"Item Price\"\n ],\n \"doctype\": \"Item Price\",\n \"is_query_report\": false,\n \"label\": \"Item-wise Price List Rate\",\n \"name\": \"Item-wise Price List Rate\",\n \"onboard\": 1,\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Stock Entry\"\n ],\n \"doctype\": \"Stock Entry\",\n \"is_query_report\": true,\n \"label\": \"Stock Analytics\",\n \"name\": \"Stock Analytics\",\n \"onboard\": 1,\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Delivery Note\"\n ],\n \"doctype\": \"Delivery Note\",\n \"is_query_report\": true,\n \"label\": \"Delivery Note Trends\",\n \"name\": \"Delivery Note Trends\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Receipt\"\n ],\n \"doctype\": \"Purchase Receipt\",\n \"is_query_report\": true,\n \"label\": \"Purchase Receipt Trends\",\n \"name\": \"Purchase Receipt Trends\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Delivery Note\"\n ],\n \"doctype\": \"Delivery Note\",\n \"is_query_report\": true,\n \"label\": \"Ordered Items To Be Delivered\",\n \"name\": \"Ordered Items To Be Delivered\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Order\"\n ],\n \"doctype\": \"Purchase Order\",\n \"is_query_report\": true,\n \"label\": \"Purchase Order Analysis\",\n \"name\": \"Purchase Order Analysis\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Bin\"\n ],\n \"doctype\": \"Bin\",\n \"is_query_report\": true,\n \"label\": \"Item Shortage Report\",\n \"name\": \"Item Shortage Report\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Batch\"\n ],\n \"doctype\": \"Batch\",\n \"is_query_report\": true,\n \"label\": \"Batch-Wise Balance History\",\n \"name\": \"Batch-Wise Balance History\",\n \"type\": \"report\"\n }\n]"
+ "links": "[\n {\n \"dependencies\": [\n \"Item Price\"\n ],\n \"doctype\": \"Item Price\",\n \"is_query_report\": false,\n \"label\": \"Item-wise Price List Rate\",\n \"name\": \"Item-wise Price List Rate\",\n \"onboard\": 1,\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Stock Entry\"\n ],\n \"doctype\": \"Stock Entry\",\n \"is_query_report\": true,\n \"label\": \"Stock Analytics\",\n \"name\": \"Stock Analytics\",\n \"onboard\": 1,\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Delivery Note\"\n ],\n \"doctype\": \"Delivery Note\",\n \"is_query_report\": true,\n \"label\": \"Delivery Note Trends\",\n \"name\": \"Delivery Note Trends\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Receipt\"\n ],\n \"doctype\": \"Purchase Receipt\",\n \"is_query_report\": true,\n \"label\": \"Purchase Receipt Trends\",\n \"name\": \"Purchase Receipt Trends\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Order\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Sales Order Analysis\",\n \"name\": \"Sales Order Analysis\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Order\"\n ],\n \"doctype\": \"Purchase Order\",\n \"is_query_report\": true,\n \"label\": \"Purchase Order Analysis\",\n \"name\": \"Purchase Order Analysis\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Bin\"\n ],\n \"doctype\": \"Bin\",\n \"is_query_report\": true,\n \"label\": \"Item Shortage Report\",\n \"name\": \"Item Shortage Report\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Batch\"\n ],\n \"doctype\": \"Batch\",\n \"is_query_report\": true,\n \"label\": \"Batch-Wise Balance History\",\n \"name\": \"Batch-Wise Balance History\",\n \"type\": \"report\"\n }\n]"
},
{
"hidden": 0,
@@ -58,7 +58,7 @@
"idx": 0,
"is_standard": 1,
"label": "Stock",
- "modified": "2020-05-27 20:38:25.255323",
+ "modified": "2020-05-30 17:32:11.062681",
"modified_by": "Administrator",
"module": "Stock",
"name": "Stock",
diff --git a/erpnext/stock/doctype/stock_settings/stock_settings.js b/erpnext/stock/doctype/stock_settings/stock_settings.js
index 877d0c3..d5049ac 100644
--- a/erpnext/stock/doctype/stock_settings/stock_settings.js
+++ b/erpnext/stock/doctype/stock_settings/stock_settings.js
@@ -20,7 +20,7 @@
{
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.")
+ description: __("By default, the Item Name is set as per the Item Code entered. If you want Items to be named by a") + "<a href='https://docs.erpnext.com/docs/user/manual/en/setting-up/settings/naming-series' target='_blank'>Naming Series</a>" + __(" choose the 'Naming Series' option."),
},
{
fieldname: "default_warehouse",
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 5a931e7..446d304 100644
--- a/erpnext/stock/report/delivery_note_trends/delivery_note_trends.py
+++ b/erpnext/stock/report/delivery_note_trends/delivery_note_trends.py
@@ -26,9 +26,10 @@
# consider only consolidated row
data = [row for row in data if row[0]]
+ data = sorted(data, key = lambda i: i[-1],reverse=True)
+
if len(data) > 10:
# get top 10 if data too long
- data = sorted(data, key = lambda i: i[-1],reverse=True)
data = data[:10]
for row in data:
diff --git a/erpnext/stock/report/ordered_items_to_be_delivered/__init__.py b/erpnext/stock/report/ordered_items_to_be_delivered/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/stock/report/ordered_items_to_be_delivered/__init__.py
+++ /dev/null
diff --git a/erpnext/stock/report/ordered_items_to_be_delivered/ordered_items_to_be_delivered.json b/erpnext/stock/report/ordered_items_to_be_delivered/ordered_items_to_be_delivered.json
deleted file mode 100644
index aa5fd0f..0000000
--- a/erpnext/stock/report/ordered_items_to_be_delivered/ordered_items_to_be_delivered.json
+++ /dev/null
@@ -1,34 +0,0 @@
-{
- "add_total_row": 1,
- "creation": "2018-01-09 18:38:23.540100",
- "disable_prepared_report": 0,
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Report",
- "idx": 0,
- "is_standard": "Yes",
- "modified": "2019-04-01 22:10:09.829361",
- "modified_by": "Administrator",
- "module": "Stock",
- "name": "Ordered Items To Be Delivered",
- "owner": "Administrator",
- "prepared_report": 0,
- "query": "select \n `tabSales Order`.`name` as \"Sales Order:Link/Sales Order:120\",\n `tabSales Order`.`status` as \"Status:Data:120\",\n `tabSales Order`.`customer` as \"Customer:Link/Customer:120\",\n `tabSales Order`.`customer_name` as \"Customer Name::150\",\n `tabSales Order`.`transaction_date` as \"Date:Date\",\n `tabSales Order`.`project` as \"Project:Link/Project:120\",\n `tabSales Order Item`.item_code as \"Item:Link/Item:120\",\n `tabSales Order Item`.qty as \"Qty:Float:140\",\n `tabSales Order Item`.delivered_qty as \"Delivered Qty:Float:140\",\n (`tabSales Order Item`.qty - ifnull(`tabSales Order Item`.delivered_qty, 0)) as \"Qty to Deliver:Float:140\",\n `tabSales Order Item`.base_rate as \"Rate:Float:140\",\n `tabSales Order Item`.base_amount as \"Amount:Float:140\",\n ((`tabSales Order Item`.qty - ifnull(`tabSales Order Item`.delivered_qty, 0))*`tabSales Order Item`.base_rate) as \"Amount to Deliver:Float:140\",\n `tabBin`.actual_qty as \"Available Qty:Float:120\",\n `tabBin`.projected_qty as \"Projected Qty:Float:120\",\n `tabSales Order Item`.`delivery_date` as \"Item Delivery Date:Date:120\",\n DATEDIFF(CURDATE(),`tabSales Order Item`.`delivery_date`) as \"Delay Days:Int:120\",\n `tabSales Order Item`.item_name as \"Item Name::150\",\n `tabSales Order Item`.description as \"Description::200\",\n `tabSales Order Item`.item_group as \"Item Group:Link/Item Group:120\",\n `tabSales Order Item`.warehouse as \"Warehouse:Link/Warehouse:200\"\nfrom\n `tabSales Order` JOIN `tabSales Order Item` \n LEFT JOIN `tabBin` ON (`tabBin`.item_code = `tabSales Order Item`.item_code\n and `tabBin`.warehouse = `tabSales Order Item`.warehouse)\nwhere\n `tabSales Order Item`.`parent` = `tabSales Order`.`name`\n and `tabSales Order`.docstatus = 1\n and `tabSales Order`.status not in (\"Stopped\", \"Closed\")\n and ifnull(`tabSales Order Item`.delivered_qty,0) < ifnull(`tabSales Order Item`.qty,0)\norder by `tabSales Order`.transaction_date asc",
- "ref_doctype": "Delivery Note",
- "report_name": "Ordered Items To Be Delivered",
- "report_type": "Query Report",
- "roles": [
- {
- "role": "Stock User"
- },
- {
- "role": "Stock Manager"
- },
- {
- "role": "Sales User"
- },
- {
- "role": "Accounts User"
- }
- ]
-}
\ No newline at end of file