From 3bd15d3aaa6b4e5020f66d84ecc5eadb8a73e76b Mon Sep 17 00:00:00 2001 From: prssanna Date: Thu, 22 Aug 2019 13:44:48 +0530 Subject: [PATCH 01/18] feat: remove leaderboard from erpnext --- erpnext/utilities/page/__init__.py | 0 .../utilities/page/leaderboard/__init__.py | 0 .../page/leaderboard/leaderboard.css | 54 --- .../utilities/page/leaderboard/leaderboard.js | 307 ------------------ .../page/leaderboard/leaderboard.json | 19 -- .../utilities/page/leaderboard/leaderboard.py | 153 --------- 6 files changed, 533 deletions(-) delete mode 100644 erpnext/utilities/page/__init__.py delete mode 100644 erpnext/utilities/page/leaderboard/__init__.py delete mode 100644 erpnext/utilities/page/leaderboard/leaderboard.css delete mode 100644 erpnext/utilities/page/leaderboard/leaderboard.js delete mode 100644 erpnext/utilities/page/leaderboard/leaderboard.json delete mode 100644 erpnext/utilities/page/leaderboard/leaderboard.py diff --git a/erpnext/utilities/page/__init__.py b/erpnext/utilities/page/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/utilities/page/leaderboard/__init__.py b/erpnext/utilities/page/leaderboard/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/utilities/page/leaderboard/leaderboard.css b/erpnext/utilities/page/leaderboard/leaderboard.css deleted file mode 100644 index 1f4fc5159a..0000000000 --- a/erpnext/utilities/page/leaderboard/leaderboard.css +++ /dev/null @@ -1,54 +0,0 @@ -.list-filters { - overflow-y: hidden; - padding: 5px -} - -.list-filter-item { - min-width: 150px; - float: left; - margin:5px; -} - -.list-item_content{ - flex: 1; - padding-right: 15px; - align-items: center; -} - -.select-time, .select-doctype, .select-filter, .select-sort { - background: #f0f4f7; -} - -.select-time:focus, .select-doctype:focus, .select-filter:focus, .select-sort:focus { - background: #f0f4f7; -} - -.header-btn-base{ - border:none; - outline:0; - vertical-align:middle; - overflow:hidden; - text-decoration:none; - color:inherit; - background-color:inherit; - cursor:pointer; - white-space:nowrap; -} - -.header-btn-grey,.header-btn-grey:hover{ - color:#000!important; - background-color:#bbb!important -} - -.header-btn-round{ - border-radius:4px -} - -.item-title-bold{ - font-weight: bold; -} - -/* -.header-btn-base:hover { - box-shadow:0 8px 16px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19) -}*/ diff --git a/erpnext/utilities/page/leaderboard/leaderboard.js b/erpnext/utilities/page/leaderboard/leaderboard.js deleted file mode 100644 index 43d0e6e948..0000000000 --- a/erpnext/utilities/page/leaderboard/leaderboard.js +++ /dev/null @@ -1,307 +0,0 @@ -frappe.pages["leaderboard"].on_page_load = function (wrapper) { - frappe.leaderboard = new frappe.Leaderboard(wrapper); -} - -frappe.Leaderboard = Class.extend({ - - init: function (parent) { - frappe.ui.make_app_page({ - parent: parent, - title: "Leaderboard", - single_column: false - }); - - this.parent = parent; - this.page = this.parent.page; - this.page.sidebar.html(``); - this.$sidebar_list = this.page.sidebar.find('ul'); - - // const list of doctypes - this.doctypes = ["Customer", "Item", "Supplier", "Sales Partner","Sales Person"]; - this.timespans = ["Week", "Month", "Quarter", "Year"]; - this.filters = { - "Customer": ["total_sales_amount", "total_qty_sold", "outstanding_amount", ], - "Item": ["total_sales_amount", "total_qty_sold", "total_purchase_amount", - "total_qty_purchased", "available_stock_qty", "available_stock_value"], - "Supplier": ["total_purchase_amount", "total_qty_purchased", "outstanding_amount"], - "Sales Partner": ["total_sales_amount", "total_commission"], - "Sales Person": ["total_sales_amount"], - }; - - // for saving current selected filters - // TODO: revert to 0 index for doctype and timespan, and remove preset down - const _initial_doctype = this.doctypes[0]; - const _initial_timespan = this.timespans[0]; - const _initial_filter = this.filters[_initial_doctype]; - - this.options = { - selected_doctype: _initial_doctype, - selected_filter: _initial_filter, - selected_filter_item: _initial_filter[0], - selected_timespan: _initial_timespan, - }; - - this.message = null; - this.make(); - }, - - make: function () { - var me = this; - - var $container = $(`
-
-
-
`).appendTo(this.page.main); - - this.$graph_area = $container.find('.leaderboard-graph'); - - this.doctypes.map(doctype => { - this.get_sidebar_item(doctype).appendTo(this.$sidebar_list); - }); - - this.company_select = this.page.add_field({ - fieldname: 'company', - label: __('Company'), - fieldtype:'Link', - options:'Company', - default:frappe.defaults.get_default('company'), - reqd: 1, - change: function() { - me.options.selected_company = this.value; - me.make_request($container); - } - }); - this.timespan_select = this.page.add_select(__("Timespan"), - this.timespans.map(d => { - return {"label": __(d), value: d } - }) - ); - - this.type_select = this.page.add_select(__("Type"), - me.options.selected_filter.map(d => { - return {"label": __(frappe.model.unscrub(d)), value: d } - }) - ); - - this.$sidebar_list.on('click', 'li', function(e) { - let $li = $(this); - let doctype = $li.find('span').attr("doctype-value"); - - me.options.selected_company = frappe.defaults.get_default('company'); - me.options.selected_doctype = doctype; - me.options.selected_filter = me.filters[doctype]; - me.options.selected_filter_item = me.filters[doctype][0]; - - me.type_select.empty().add_options( - me.options.selected_filter.map(d => { - return {"label": __(frappe.model.unscrub(d)), value: d } - }) - ); - - me.$sidebar_list.find('li').removeClass('active'); - $li.addClass('active'); - - me.make_request($container); - }); - - this.timespan_select.on("change", function() { - me.options.selected_timespan = this.value; - me.make_request($container); - }); - - this.type_select.on("change", function() { - me.options.selected_filter_item = this.value - me.make_request($container); - }); - - // now get leaderboard - this.$sidebar_list.find('li:first').trigger('click'); - }, - - make_request: function ($container) { - var me = this; - - frappe.model.with_doctype(me.options.selected_doctype, function () { - me.get_leaderboard(me.get_leaderboard_data, $container); - }); - }, - - get_leaderboard: function (notify, $container) { - var me = this; - if(!me.options.selected_company) { - frappe.throw(__("Please select Company")); - } - frappe.call({ - method: "erpnext.utilities.page.leaderboard.leaderboard.get_leaderboard", - args: { - doctype: me.options.selected_doctype, - timespan: me.options.selected_timespan, - company: me.options.selected_company, - field: me.options.selected_filter_item, - }, - callback: function (r) { - let results = r.message || []; - - let graph_items = results.slice(0, 10); - - me.$graph_area.show().empty(); - let args = { - data: { - datasets: [ - { - values: graph_items.map(d=>d.value) - } - ], - labels: graph_items.map(d=>d.name) - }, - colors: ['light-green'], - format_tooltip_x: d=>d[me.options.selected_filter_item], - type: 'bar', - height: 140 - }; - new frappe.Chart('.leaderboard-graph', args); - - notify(me, r, $container); - } - }); - }, - - get_leaderboard_data: function (me, res, $container) { - if (res && res.message) { - me.message = null; - $container.find(".leaderboard-list").html(me.render_list_view(res.message)); - } else { - me.$graph_area.hide(); - me.message = __("No items found."); - $container.find(".leaderboard-list").html(me.render_list_view()); - } - }, - - render_list_view: function (items = []) { - var me = this; - - var html = - `${me.render_message()} -
- ${me.render_result(items)} -
`; - - return $(html); - }, - - render_result: function (items) { - var me = this; - - var html = - `${me.render_list_header()} - ${me.render_list_result(items)}`; - - return html; - }, - - render_list_header: function () { - var me = this; - const _selected_filter = me.options.selected_filter - .map(i => frappe.model.unscrub(i)); - const fields = ['name', me.options.selected_filter_item]; - - const html = - `
-
- ${ - fields.map(filter => { - const col = frappe.model.unscrub(filter); - return ( - `
- - ${col} - -
`); - }).join("") - } -
-
`; - return html; - }, - - render_list_result: function (items) { - var me = this; - - let _html = items.map((item, index) => { - const $value = $(me.get_item_html(item)); - - let item_class = ""; - if(index == 0) { - item_class = "first"; - } else if (index == 1) { - item_class = "second"; - } else if(index == 2) { - item_class = "third"; - } - const $item_container = $(`
`).append($value); - return $item_container[0].outerHTML; - }).join(""); - - let html = - `
-
- ${_html} -
-
`; - - return html; - }, - - render_message: function () { - var me = this; - - let html = - `
-
-

No Item found

-
-
`; - - return html; - }, - - get_item_html: function (item) { - var me = this; - const company = me.options.selected_company; - const currency = frappe.get_doc(":Company", company).default_currency; - const fields = ['name','value']; - - const html = - `
- ${ - fields.map(col => { - let val = item[col]; - if(col=="name") { - var formatted_value = ` ${val} ` - } else { - var formatted_value = ` - ${(me.options.selected_filter_item.indexOf('qty') == -1) ? format_currency(val, currency) : val}` - } - - return ( - `
- ${formatted_value} -
`); - }).join("") - } -
`; - - return html; - }, - - get_sidebar_item: function(item) { - return $(`
  • - - ${ __(item) } -
  • `); - } -}); diff --git a/erpnext/utilities/page/leaderboard/leaderboard.json b/erpnext/utilities/page/leaderboard/leaderboard.json deleted file mode 100644 index 8ccef7dcf6..0000000000 --- a/erpnext/utilities/page/leaderboard/leaderboard.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "content": null, - "creation": "2017-06-06 02:54:24.785360", - "docstatus": 0, - "doctype": "Page", - "idx": 0, - "modified": "2017-09-12 14:05:26.422064", - "modified_by": "Administrator", - "module": "Utilities", - "name": "leaderboard", - "owner": "Administrator", - "page_name": "leaderboard", - "roles": [], - "script": null, - "standard": "Yes", - "style": null, - "system_page": 0, - "title": "Leaderboard" -} \ No newline at end of file diff --git a/erpnext/utilities/page/leaderboard/leaderboard.py b/erpnext/utilities/page/leaderboard/leaderboard.py deleted file mode 100644 index 87cf2a43be..0000000000 --- a/erpnext/utilities/page/leaderboard/leaderboard.py +++ /dev/null @@ -1,153 +0,0 @@ -# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors -# MIT License. See license.txt - -from __future__ import unicode_literals, print_function -import frappe -from frappe.utils import add_to_date - -@frappe.whitelist() -def get_leaderboard(doctype, timespan, company, field): - """return top 10 items for that doctype based on conditions""" - from_date = get_from_date(timespan) - records = [] - if doctype == "Customer": - records = get_all_customers(from_date, company, field) - elif doctype == "Item": - records = get_all_items(from_date, company, field) - elif doctype == "Supplier": - records = get_all_suppliers(from_date, company, field) - elif doctype == "Sales Partner": - records = get_all_sales_partner(from_date, company, field) - elif doctype == "Sales Person": - records = get_all_sales_person(from_date, company) - - return records - -def get_all_customers(from_date, company, field): - if field == "outstanding_amount": - return frappe.db.sql(""" - select customer as name, sum(outstanding_amount) as value - FROM `tabSales Invoice` - where docstatus = 1 and posting_date >= %s and company = %s - group by customer - order by value DESC - limit 20 - """, (from_date, company), as_dict=1) - else: - if field == "total_sales_amount": - select_field = "sum(so_item.base_net_amount)" - elif field == "total_qty_sold": - select_field = "sum(so_item.stock_qty)" - - return frappe.db.sql(""" - select so.customer as name, {0} as value - FROM `tabSales Order` as so JOIN `tabSales Order Item` as so_item - ON so.name = so_item.parent - where so.docstatus = 1 and so.transaction_date >= %s and so.company = %s - group by so.customer - order by value DESC - limit 20 - """.format(select_field), (from_date, company), as_dict=1) - -def get_all_items(from_date, company, field): - if field in ("available_stock_qty", "available_stock_value"): - return frappe.db.sql(""" - select item_code as name, {0} as value - from tabBin - group by item_code - order by value desc - limit 20 - """.format("sum(actual_qty)" if field=="available_stock_qty" else "sum(stock_value)"), as_dict=1) - else: - if field == "total_sales_amount": - select_field = "sum(order_item.base_net_amount)" - select_doctype = "Sales Order" - elif field == "total_purchase_amount": - select_field = "sum(order_item.base_net_amount)" - select_doctype = "Purchase Order" - elif field == "total_qty_sold": - select_field = "sum(order_item.stock_qty)" - select_doctype = "Sales Order" - elif field == "total_qty_purchased": - select_field = "sum(order_item.stock_qty)" - select_doctype = "Purchase Order" - - return frappe.db.sql(""" - select order_item.item_code as name, {0} as value - from `tab{1}` sales_order join `tab{1} Item` as order_item - on sales_order.name = order_item.parent - where sales_order.docstatus = 1 - and sales_order.company = %s and sales_order.transaction_date >= %s - group by order_item.item_code - order by value desc - limit 20 - """.format(select_field, select_doctype), (company, from_date), as_dict=1) - -def get_all_suppliers(from_date, company, field): - if field == "outstanding_amount": - return frappe.db.sql(""" - select supplier as name, sum(outstanding_amount) as value - FROM `tabPurchase Invoice` - where docstatus = 1 and posting_date >= %s and company = %s - group by supplier - order by value DESC - limit 20""", (from_date, company), as_dict=1) - else: - if field == "total_purchase_amount": - select_field = "sum(purchase_order_item.base_net_amount)" - elif field == "total_qty_purchased": - select_field = "sum(purchase_order_item.stock_qty)" - - return frappe.db.sql(""" - select purchase_order.supplier as name, {0} as value - FROM `tabPurchase Order` as purchase_order LEFT JOIN `tabPurchase Order Item` - as purchase_order_item ON purchase_order.name = purchase_order_item.parent - where purchase_order.docstatus = 1 and purchase_order.modified >= %s - and purchase_order.company = %s - group by purchase_order.supplier - order by value DESC - limit 20""".format(select_field), (from_date, company), as_dict=1) - -def get_all_sales_partner(from_date, company, field): - if field == "total_sales_amount": - select_field = "sum(base_net_total)" - elif field == "total_commission": - select_field = "sum(total_commission)" - - return frappe.db.sql(""" - select sales_partner as name, {0} as value - from `tabSales Order` - where ifnull(sales_partner, '') != '' and docstatus = 1 - and transaction_date >= %s and company = %s - group by sales_partner - order by value DESC - limit 20 - """.format(select_field), (from_date, company), as_dict=1) - -def get_all_sales_person(from_date, company): - return frappe.db.sql(""" - select sales_team.sales_person as name, sum(sales_order.base_net_total) as value - from `tabSales Order` as sales_order join `tabSales Team` as sales_team - on sales_order.name = sales_team.parent and sales_team.parenttype = 'Sales Order' - where sales_order.docstatus = 1 - and sales_order.transaction_date >= %s - and sales_order.company = %s - group by sales_team.sales_person - order by value DESC - limit 20 - """, (from_date, company), as_dict=1) - -def get_from_date(seleted_timespan): - """return string for ex:this week as date:string""" - days = months = years = 0 - if "month" == seleted_timespan.lower(): - months = -1 - elif "quarter" == seleted_timespan.lower(): - months = -3 - elif "year" == seleted_timespan.lower(): - years = -1 - else: - days = -7 - - return add_to_date(None, years=years, months=months, days=days, - as_string=True, as_datetime=True) \ No newline at end of file From 3f1444e4107dce4f3d615fc6086261e31f153b6c Mon Sep 17 00:00:00 2001 From: prssanna Date: Tue, 24 Sep 2019 13:04:53 +0530 Subject: [PATCH 02/18] fix: get leaderboards using hooks --- erpnext/hooks.py | 2 + erpnext/startup/leaderboard.py | 128 +++++++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+) create mode 100644 erpnext/startup/leaderboard.py diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 7e33a14d51..b94c29dafc 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -42,6 +42,8 @@ notification_config = "erpnext.startup.notifications.get_notification_config" get_help_messages = "erpnext.utilities.activation.get_help_messages" get_user_progress_slides = "erpnext.utilities.user_progress.get_user_progress_slides" update_and_get_user_progress = "erpnext.utilities.user_progress_utils.update_default_domain_actions_and_get_state" +leaderboards = "erpnext.startup.leaderboard.get_leaderboards" + on_session_creation = "erpnext.shopping_cart.utils.set_cart_count" on_logout = "erpnext.shopping_cart.utils.clear_cart_count" diff --git a/erpnext/startup/leaderboard.py b/erpnext/startup/leaderboard.py new file mode 100644 index 0000000000..a5549b8748 --- /dev/null +++ b/erpnext/startup/leaderboard.py @@ -0,0 +1,128 @@ + +from __future__ import unicode_literals, print_function +import frappe + +def get_leaderboards(): + leaderboards = { + 'Customer': 'erpnext.startup.leaderboard.get_all_customers', + 'Item': 'erpnext.startup.leaderboard.get_all_items', + 'Supplier': 'erpnext.startup.leaderboard.get_all_suppliers', + 'Sales Partner': 'erpnext.startup.leaderboard.get_all_sales_partner', + 'Sales Person': 'erpnext.startup.leaderboard.get_all_sales_person', + } + + return leaderboards + +def get_all_customers(from_date, company, field): + if field == "outstanding_amount": + return frappe.db.sql(""" + select customer as name, sum(outstanding_amount) as value + FROM `tabSales Invoice` + where docstatus = 1 and posting_date >= %s and company = %s + group by customer + order by value DESC + limit 20 + """, (from_date, company), as_dict=1) + else: + if field == "total_sales_amount": + select_field = "sum(so_item.base_net_amount)" + elif field == "total_qty_sold": + select_field = "sum(so_item.stock_qty)" + + return frappe.db.sql(""" + select so.customer as name, {0} as value + FROM `tabSales Order` as so JOIN `tabSales Order Item` as so_item + ON so.name = so_item.parent + where so.docstatus = 1 and so.transaction_date >= %s and so.company = %s + group by so.customer + order by value DESC + limit 20 + """.format(select_field), (from_date, company), as_dict=1) + +def get_all_items(from_date, company, field): + if field in ("available_stock_qty", "available_stock_value"): + return frappe.db.sql(""" + select item_code as name, {0} as value + from tabBin + group by item_code + order by value desc + limit 20 + """.format("sum(actual_qty)" if field=="available_stock_qty" else "sum(stock_value)"), as_dict=1) + else: + if field == "total_sales_amount": + select_field = "sum(order_item.base_net_amount)" + select_doctype = "Sales Order" + elif field == "total_purchase_amount": + select_field = "sum(order_item.base_net_amount)" + select_doctype = "Purchase Order" + elif field == "total_qty_sold": + select_field = "sum(order_item.stock_qty)" + select_doctype = "Sales Order" + elif field == "total_qty_purchased": + select_field = "sum(order_item.stock_qty)" + select_doctype = "Purchase Order" + + return frappe.db.sql(""" + select order_item.item_code as name, {0} as value + from `tab{1}` sales_order join `tab{1} Item` as order_item + on sales_order.name = order_item.parent + where sales_order.docstatus = 1 + and sales_order.company = %s and sales_order.transaction_date >= %s + group by order_item.item_code + order by value desc + limit 20 + """.format(select_field, select_doctype), (company, from_date), as_dict=1) + +def get_all_suppliers(from_date, company, field): + if field == "outstanding_amount": + return frappe.db.sql(""" + select supplier as name, sum(outstanding_amount) as value + FROM `tabPurchase Invoice` + where docstatus = 1 and posting_date >= %s and company = %s + group by supplier + order by value DESC + limit 20""", (from_date, company), as_dict=1) + else: + if field == "total_purchase_amount": + select_field = "sum(purchase_order_item.base_net_amount)" + elif field == "total_qty_purchased": + select_field = "sum(purchase_order_item.stock_qty)" + + return frappe.db.sql(""" + select purchase_order.supplier as name, {0} as value + FROM `tabPurchase Order` as purchase_order LEFT JOIN `tabPurchase Order Item` + as purchase_order_item ON purchase_order.name = purchase_order_item.parent + where purchase_order.docstatus = 1 and purchase_order.modified >= %s + and purchase_order.company = %s + group by purchase_order.supplier + order by value DESC + limit 20""".format(select_field), (from_date, company), as_dict=1) + +def get_all_sales_partner(from_date, company, field): + if field == "total_sales_amount": + select_field = "sum(base_net_total)" + elif field == "total_commission": + select_field = "sum(total_commission)" + + return frappe.db.sql(""" + select sales_partner as name, {0} as value + from `tabSales Order` + where ifnull(sales_partner, '') != '' and docstatus = 1 + and transaction_date >= %s and company = %s + group by sales_partner + order by value DESC + limit 20 + """.format(select_field), (from_date, company), as_dict=1) + +def get_all_sales_person(from_date, company, field = None): + return frappe.db.sql(""" + select sales_team.sales_person as name, sum(sales_order.base_net_total) as value + from `tabSales Order` as sales_order join `tabSales Team` as sales_team + on sales_order.name = sales_team.parent and sales_team.parenttype = 'Sales Order' + where sales_order.docstatus = 1 + and sales_order.transaction_date >= %s + and sales_order.company = %s + group by sales_team.sales_person + order by value DESC + limit 20 + """, (from_date, company), as_dict=1) From d095acdad5b17923b3bf807327d815e8b7f8ca08 Mon Sep 17 00:00:00 2001 From: prssanna Date: Thu, 26 Sep 2019 13:41:24 +0530 Subject: [PATCH 03/18] fix: use orm for queries --- erpnext/startup/leaderboard.py | 103 ++++++++++++++++++++------------- 1 file changed, 62 insertions(+), 41 deletions(-) diff --git a/erpnext/startup/leaderboard.py b/erpnext/startup/leaderboard.py index a5549b8748..711d0098ed 100644 --- a/erpnext/startup/leaderboard.py +++ b/erpnext/startup/leaderboard.py @@ -4,25 +4,43 @@ import frappe def get_leaderboards(): leaderboards = { - 'Customer': 'erpnext.startup.leaderboard.get_all_customers', - 'Item': 'erpnext.startup.leaderboard.get_all_items', - 'Supplier': 'erpnext.startup.leaderboard.get_all_suppliers', - 'Sales Partner': 'erpnext.startup.leaderboard.get_all_sales_partner', - 'Sales Person': 'erpnext.startup.leaderboard.get_all_sales_person', + "Customer": { + "fields": ['total_sales_amount', 'total_qty_sold', 'outstanding_amount'], + "method": "erpnext.startup.leaderboard.get_all_customers", + }, + "Item": { + "fields": ["total_sales_amount", "total_qty_sold", "total_purchase_amount", + "total_qty_purchased", "available_stock_qty", "available_stock_value"], + "method": "erpnext.startup.leaderboard.get_all_items", + }, + "Supplier": { + "fields": ["total_purchase_amount", "total_qty_purchased", "outstanding_amount"], + "method": "erpnext.startup.leaderboard.get_all_suppliers", + }, + "Sales Partner": { + "fields": ["total_sales_amount", "total_commission"], + "method": "erpnext.startup.leaderboard.get_all_sales_partner", + }, + "Sales Person": { + "fields": ["total_sales_amount"], + "method": "erpnext.startup.leaderboard.get_all_sales_person", + } } return leaderboards -def get_all_customers(from_date, company, field): +def get_all_customers(from_date, company, field, limit = None): if field == "outstanding_amount": - return frappe.db.sql(""" - select customer as name, sum(outstanding_amount) as value - FROM `tabSales Invoice` - where docstatus = 1 and posting_date >= %s and company = %s - group by customer - order by value DESC - limit 20 - """, (from_date, company), as_dict=1) + filters = [['docstatus', '=', '1'], ['company', '=', company]] + if from_date: + filters.append(['posting_date', '>=', from_date]) + return frappe.db.get_all('Sales Invoice', + fields = ['customer as name', 'sum(outstanding_amount) as value'], + filters = filters, + group_by = 'customer', + order_by = 'value desc', + limit = limit + ) else: if field == "total_sales_amount": select_field = "sum(so_item.base_net_amount)" @@ -36,18 +54,18 @@ def get_all_customers(from_date, company, field): where so.docstatus = 1 and so.transaction_date >= %s and so.company = %s group by so.customer order by value DESC - limit 20 - """.format(select_field), (from_date, company), as_dict=1) + limit %s + """.format(select_field), (from_date, company, limit), as_dict=1) -def get_all_items(from_date, company, field): +def get_all_items(from_date, company, field, limit = None): if field in ("available_stock_qty", "available_stock_value"): - return frappe.db.sql(""" - select item_code as name, {0} as value - from tabBin - group by item_code - order by value desc - limit 20 - """.format("sum(actual_qty)" if field=="available_stock_qty" else "sum(stock_value)"), as_dict=1) + select_field = "sum(actual_qty)" if field=="available_stock_qty" else "sum(stock_value)" + return frappe.db.get_all('Bin', + fields = ['item_code as name', '{0} as value'.format(select_field)], + group_by = 'item_code', + order_by = 'value desc', + limit = limit + ) else: if field == "total_sales_amount": select_field = "sum(order_item.base_net_amount)" @@ -70,18 +88,21 @@ def get_all_items(from_date, company, field): and sales_order.company = %s and sales_order.transaction_date >= %s group by order_item.item_code order by value desc - limit 20 - """.format(select_field, select_doctype), (company, from_date), as_dict=1) + limit %s + """.format(select_field, select_doctype), (company, from_date, limit), as_dict=1) -def get_all_suppliers(from_date, company, field): +def get_all_suppliers(from_date, company, field, limit = None): if field == "outstanding_amount": - return frappe.db.sql(""" - select supplier as name, sum(outstanding_amount) as value - FROM `tabPurchase Invoice` - where docstatus = 1 and posting_date >= %s and company = %s - group by supplier - order by value DESC - limit 20""", (from_date, company), as_dict=1) + filters = [['docstatus', '=', '1'], ['company', '=', company]] + if from_date: + filters.append(['posting_date', '>=', from_date]) + return frappe.db.get_all('Purchase Invoice', + fields = ['supplier as name', 'sum(outstanding_amount) as value'], + filters = filters, + group_by = 'supplier', + order_by = 'value desc', + limit = limit + ) else: if field == "total_purchase_amount": select_field = "sum(purchase_order_item.base_net_amount)" @@ -96,9 +117,9 @@ def get_all_suppliers(from_date, company, field): and purchase_order.company = %s group by purchase_order.supplier order by value DESC - limit 20""".format(select_field), (from_date, company), as_dict=1) + limit %s""".format(select_field), (from_date, company, limit), as_dict=1) -def get_all_sales_partner(from_date, company, field): +def get_all_sales_partner(from_date, company, field, limit = None): if field == "total_sales_amount": select_field = "sum(base_net_total)" elif field == "total_commission": @@ -111,10 +132,10 @@ def get_all_sales_partner(from_date, company, field): and transaction_date >= %s and company = %s group by sales_partner order by value DESC - limit 20 - """.format(select_field), (from_date, company), as_dict=1) + limit %s + """.format(select_field), (from_date, company, limit), as_dict=1) -def get_all_sales_person(from_date, company, field = None): +def get_all_sales_person(from_date, company, field = None, limit = None): return frappe.db.sql(""" select sales_team.sales_person as name, sum(sales_order.base_net_total) as value from `tabSales Order` as sales_order join `tabSales Team` as sales_team @@ -124,5 +145,5 @@ def get_all_sales_person(from_date, company, field = None): and sales_order.company = %s group by sales_team.sales_person order by value DESC - limit 20 - """, (from_date, company), as_dict=1) + limit %s + """, (from_date, company, limit), as_dict=1) From 8f7ed71e9eeea046feef714f0c88dab3ba13a431 Mon Sep 17 00:00:00 2001 From: prssanna Date: Fri, 27 Sep 2019 15:09:40 +0530 Subject: [PATCH 04/18] fix: add df to leaderboard config --- erpnext/startup/leaderboard.py | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/erpnext/startup/leaderboard.py b/erpnext/startup/leaderboard.py index 711d0098ed..b3e4b99cbe 100644 --- a/erpnext/startup/leaderboard.py +++ b/erpnext/startup/leaderboard.py @@ -5,24 +5,43 @@ import frappe def get_leaderboards(): leaderboards = { "Customer": { - "fields": ['total_sales_amount', 'total_qty_sold', 'outstanding_amount'], + "fields": [ + {'fieldname': 'total_sales_amount', 'fieldtype': 'Currency'}, + 'total_qty_sold', + {'fieldname': 'outstanding_amount', 'fieldtype': 'Currency'} + ], "method": "erpnext.startup.leaderboard.get_all_customers", }, "Item": { - "fields": ["total_sales_amount", "total_qty_sold", "total_purchase_amount", - "total_qty_purchased", "available_stock_qty", "available_stock_value"], + "fields": [ + {'fieldname': 'total_sales_amount', 'fieldtype': 'Currency'}, + 'total_qty_sold' + {'fieldname': 'total_purchase_amount', 'fieldtype': 'Currency'}, + 'total_qty_purchased', + 'available_stock_qty', + {'fieldname': 'available_stock_value', 'fieldtype': 'Currency'} + ], "method": "erpnext.startup.leaderboard.get_all_items", }, "Supplier": { - "fields": ["total_purchase_amount", "total_qty_purchased", "outstanding_amount"], + "fields": [ + {'fieldname': 'total_purchase_amount', 'fieldtype': 'Currency'}, + 'total_qty_purchased', + {'fieldname': 'outstanding_amount', 'fieldtype': 'Currency'} + ], "method": "erpnext.startup.leaderboard.get_all_suppliers", }, "Sales Partner": { - "fields": ["total_sales_amount", "total_commission"], + "fields": [ + {'fieldname': 'total_sales_amount', 'fieldtype': 'Currency'}, + {'fieldname': 'total_commission', 'fieldtype': 'Currency'} + ], "method": "erpnext.startup.leaderboard.get_all_sales_partner", }, "Sales Person": { - "fields": ["total_sales_amount"], + "fields": [ + {'fieldname': 'total_sales_amount', 'fieldtype': 'Currency'} + ], "method": "erpnext.startup.leaderboard.get_all_sales_person", } } From 119c976ad143110fd0fa65916de03b14d21481fd Mon Sep 17 00:00:00 2001 From: prssanna Date: Fri, 27 Sep 2019 16:28:08 +0530 Subject: [PATCH 05/18] fix: missing comma --- erpnext/startup/leaderboard.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/startup/leaderboard.py b/erpnext/startup/leaderboard.py index b3e4b99cbe..6d9b77ed24 100644 --- a/erpnext/startup/leaderboard.py +++ b/erpnext/startup/leaderboard.py @@ -15,7 +15,7 @@ def get_leaderboards(): "Item": { "fields": [ {'fieldname': 'total_sales_amount', 'fieldtype': 'Currency'}, - 'total_qty_sold' + 'total_qty_sold', {'fieldname': 'total_purchase_amount', 'fieldtype': 'Currency'}, 'total_qty_purchased', 'available_stock_qty', From b8749224040d96f1f6e8ed0d1a6e10bc2789b81c Mon Sep 17 00:00:00 2001 From: prssanna Date: Mon, 30 Sep 2019 11:12:10 +0530 Subject: [PATCH 06/18] fix: whitelist leaderboard functions --- erpnext/startup/leaderboard.py | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/erpnext/startup/leaderboard.py b/erpnext/startup/leaderboard.py index 6d9b77ed24..00b761bea6 100644 --- a/erpnext/startup/leaderboard.py +++ b/erpnext/startup/leaderboard.py @@ -48,6 +48,7 @@ def get_leaderboards(): return leaderboards +@frappe.whitelist() def get_all_customers(from_date, company, field, limit = None): if field == "outstanding_amount": filters = [['docstatus', '=', '1'], ['company', '=', company]] @@ -73,9 +74,10 @@ def get_all_customers(from_date, company, field, limit = None): where so.docstatus = 1 and so.transaction_date >= %s and so.company = %s group by so.customer order by value DESC - limit %s - """.format(select_field), (from_date, company, limit), as_dict=1) + limit {1} + """.format(select_field, limit), (from_date, company), as_dict=1) +@frappe.whitelist() def get_all_items(from_date, company, field, limit = None): if field in ("available_stock_qty", "available_stock_value"): select_field = "sum(actual_qty)" if field=="available_stock_qty" else "sum(stock_value)" @@ -107,9 +109,10 @@ def get_all_items(from_date, company, field, limit = None): and sales_order.company = %s and sales_order.transaction_date >= %s group by order_item.item_code order by value desc - limit %s - """.format(select_field, select_doctype), (company, from_date, limit), as_dict=1) + limit {2} + """.format(select_field, select_doctype, limit), (company, from_date), as_dict=1) +@frappe.whitelist() def get_all_suppliers(from_date, company, field, limit = None): if field == "outstanding_amount": filters = [['docstatus', '=', '1'], ['company', '=', company]] @@ -136,8 +139,9 @@ def get_all_suppliers(from_date, company, field, limit = None): and purchase_order.company = %s group by purchase_order.supplier order by value DESC - limit %s""".format(select_field), (from_date, company, limit), as_dict=1) + limit {1}""".format(select_field, limit), (from_date, company), as_dict=1) +@frappe.whitelist() def get_all_sales_partner(from_date, company, field, limit = None): if field == "total_sales_amount": select_field = "sum(base_net_total)" @@ -151,9 +155,10 @@ def get_all_sales_partner(from_date, company, field, limit = None): and transaction_date >= %s and company = %s group by sales_partner order by value DESC - limit %s - """.format(select_field), (from_date, company, limit), as_dict=1) + limit {1} + """.format(select_field, limit), (from_date, company), as_dict=1) +@frappe.whitelist() def get_all_sales_person(from_date, company, field = None, limit = None): return frappe.db.sql(""" select sales_team.sales_person as name, sum(sales_order.base_net_total) as value @@ -164,5 +169,5 @@ def get_all_sales_person(from_date, company, field = None, limit = None): and sales_order.company = %s group by sales_team.sales_person order by value DESC - limit %s - """, (from_date, company, limit), as_dict=1) + limit {0} + """.format(limit), (from_date, company), as_dict=1) From d23c9987ed21fbbaea5a533016d8129ac0036ee2 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Mon, 30 Sep 2019 13:09:12 +0530 Subject: [PATCH 07/18] style: Fix Codacy --- erpnext/startup/leaderboard.py | 42 +++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/erpnext/startup/leaderboard.py b/erpnext/startup/leaderboard.py index 00b761bea6..90ecd46259 100644 --- a/erpnext/startup/leaderboard.py +++ b/erpnext/startup/leaderboard.py @@ -1,6 +1,7 @@ from __future__ import unicode_literals, print_function import frappe +from frappe.utils import cint def get_leaderboards(): leaderboards = { @@ -74,8 +75,8 @@ def get_all_customers(from_date, company, field, limit = None): where so.docstatus = 1 and so.transaction_date >= %s and so.company = %s group by so.customer order by value DESC - limit {1} - """.format(select_field, limit), (from_date, company), as_dict=1) + limit %s + """.format(select_field), (from_date, company, cint(limit)), as_dict=1) #nosec @frappe.whitelist() def get_all_items(from_date, company, field, limit = None): @@ -109,8 +110,8 @@ def get_all_items(from_date, company, field, limit = None): and sales_order.company = %s and sales_order.transaction_date >= %s group by order_item.item_code order by value desc - limit {2} - """.format(select_field, select_doctype, limit), (company, from_date), as_dict=1) + limit %s + """.format(select_field, select_doctype), (company, from_date, cint(limit)), as_dict=1) #nosec @frappe.whitelist() def get_all_suppliers(from_date, company, field, limit = None): @@ -139,27 +140,30 @@ def get_all_suppliers(from_date, company, field, limit = None): and purchase_order.company = %s group by purchase_order.supplier order by value DESC - limit {1}""".format(select_field, limit), (from_date, company), as_dict=1) + limit %s""".format(select_field), (from_date, company, cint(limit)), as_dict=1) #nosec @frappe.whitelist() def get_all_sales_partner(from_date, company, field, limit = None): if field == "total_sales_amount": - select_field = "sum(base_net_total)" + select_field = "sum(`base_net_total`)" elif field == "total_commission": - select_field = "sum(total_commission)" + select_field = "sum(`total_commission`)" - return frappe.db.sql(""" - select sales_partner as name, {0} as value - from `tabSales Order` - where ifnull(sales_partner, '') != '' and docstatus = 1 - and transaction_date >= %s and company = %s - group by sales_partner - order by value DESC - limit {1} - """.format(select_field, limit), (from_date, company), as_dict=1) + filters = { + 'sales_partner': ['!=', ''], + 'docstatus': 1, + 'company': company + } + if from_date: + filters['transaction_date'] = ['>=', from_date] + + return frappe.get_list('Sales Order', fields=[ + '`sales_partner` as name', + '{} as value'.format(select_field), + ], filters=filters, group_by='sales_partner', order_by='value DESC', limit=limit) @frappe.whitelist() -def get_all_sales_person(from_date, company, field = None, limit = None): +def get_all_sales_person(from_date, company, field = None, limit = 0): return frappe.db.sql(""" select sales_team.sales_person as name, sum(sales_order.base_net_total) as value from `tabSales Order` as sales_order join `tabSales Team` as sales_team @@ -169,5 +173,5 @@ def get_all_sales_person(from_date, company, field = None, limit = None): and sales_order.company = %s group by sales_team.sales_person order by value DESC - limit {0} - """.format(limit), (from_date, company), as_dict=1) + limit %s + """, (from_date, company, cint(limit)), as_dict=1) From 46831c4c20be2cc66fe30943a0055e8657ea3e67 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Mon, 30 Sep 2019 14:34:56 +0530 Subject: [PATCH 08/18] fix: show mobile no --- erpnext/public/js/templates/contact_list.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/public/js/templates/contact_list.html b/erpnext/public/js/templates/contact_list.html index 50fbfd9f12..7e6969163b 100644 --- a/erpnext/public/js/templates/contact_list.html +++ b/erpnext/public/js/templates/contact_list.html @@ -19,6 +19,9 @@ {% if(contact_list[i].phone) { %} {%= __("Phone") %}: {%= contact_list[i].phone %} ({%= __("Primary") %})
    {% endif %} + {% if(contact_list[i].mobile_no) { %} + {%= __("Mobile No") %}: {%= contact_list[i].mobile_no %} ({%= __("Primary") %})
    + {% endif %} {% if(contact_list[i].phone_nos) { %} {% for(var j=0, k=contact_list[i].phone_nos.length; j From 147af15268d514ef23a2a1e4811e99ad29a902c4 Mon Sep 17 00:00:00 2001 From: Marica Date: Mon, 30 Sep 2019 15:11:15 +0530 Subject: [PATCH 09/18] fix: Added 'Manual' % Complete Method in Project (#19175) Added additional '% Complete Method' in Project so that Project can be set to 'Completed' irrespective of presence of Tasks --- erpnext/projects/doctype/project/project.json | 2 +- erpnext/projects/doctype/project/project.py | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/erpnext/projects/doctype/project/project.json b/erpnext/projects/doctype/project/project.json index 205f895849..7d47db371d 100644 --- a/erpnext/projects/doctype/project/project.json +++ b/erpnext/projects/doctype/project/project.json @@ -108,7 +108,7 @@ "fieldname": "percent_complete_method", "fieldtype": "Select", "label": "% Complete Method", - "options": "Task Completion\nTask Progress\nTask Weight" + "options": "Manual\nTask Completion\nTask Progress\nTask Weight" }, { "bold": 1, diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py index 6176cf89b4..783bcf3c38 100644 --- a/erpnext/projects/doctype/project/project.py +++ b/erpnext/projects/doctype/project/project.py @@ -87,6 +87,11 @@ class Project(Document): frappe.db.set_value("Sales Order", self.sales_order, "project", self.name) def update_percent_complete(self): + if self.percent_complete_method == "Manual": + if self.status == "Completed": + self.percent_complete = 100 + return + total = frappe.db.count('Task', dict(project=self.name)) if not total: From ed1cc18ab529c218429e88daef94aaa8df4595af Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Mon, 30 Sep 2019 15:15:52 +0530 Subject: [PATCH 10/18] fix: stock ledger report not showing data if the UOM filter has selected (#19179) --- .../stock/report/stock_ledger/stock_ledger.py | 2 +- erpnext/stock/utils.py | 53 +++++++++++-------- 2 files changed, 32 insertions(+), 23 deletions(-) diff --git a/erpnext/stock/report/stock_ledger/stock_ledger.py b/erpnext/stock/report/stock_ledger/stock_ledger.py index d386230687..5bdbca23d9 100644 --- a/erpnext/stock/report/stock_ledger/stock_ledger.py +++ b/erpnext/stock/report/stock_ledger/stock_ledger.py @@ -107,7 +107,7 @@ def get_item_details(items, sl_entries, include_uom): if include_uom: cf_field = ", ucd.conversion_factor" cf_join = "left join `tabUOM Conversion Detail` ucd on ucd.parent=item.name and ucd.uom='%s'" \ - % frappe.db.escape(include_uom) + % (include_uom) res = frappe.db.sql(""" select diff --git a/erpnext/stock/utils.py b/erpnext/stock/utils.py index 4c663e393f..2ac0bae6da 100644 --- a/erpnext/stock/utils.py +++ b/erpnext/stock/utils.py @@ -253,31 +253,40 @@ def update_included_uom_in_report(columns, result, include_uom, conversion_facto return convertible_cols = {} - for col_idx in reversed(range(0, len(columns))): - col = columns[col_idx] - if isinstance(col, dict) and col.get("convertible") in ['rate', 'qty']: - convertible_cols[col_idx] = col['convertible'] - columns.insert(col_idx+1, col.copy()) - columns[col_idx+1]['fieldname'] += "_alt" - if convertible_cols[col_idx] == 'rate': - columns[col_idx+1]['label'] += " (per {})".format(include_uom) - else: - columns[col_idx+1]['label'] += " ({})".format(include_uom) + + is_dict_obj = False + if isinstance(result[0], dict): + is_dict_obj = True + + convertible_columns = {} + for idx, d in enumerate(columns): + key = d.get("fieldname") if is_dict_obj else idx + if d.get("convertible"): + convertible_columns.setdefault(key, d.get("convertible")) + + # Add new column to show qty/rate as per the selected UOM + columns.insert(idx+1, { + 'label': "{0} (per {1})".format(d.get("label"), include_uom), + 'fieldname': "{0}_{1}".format(d.get("fieldname"), frappe.scrub(include_uom)), + 'fieldtype': 'Currency' if d.get("convertible") == 'rate' else 'Float' + }) for row_idx, row in enumerate(result): - new_row = [] - for col_idx, d in enumerate(row): - new_row.append(d) - if col_idx in convertible_cols: - if conversion_factors[row_idx]: - if convertible_cols[col_idx] == 'rate': - new_row.append(flt(d) * conversion_factors[row_idx]) - else: - new_row.append(flt(d) / conversion_factors[row_idx]) - else: - new_row.append(None) + data = row.items() if is_dict_obj else enumerate(row) + for key, value in data: + if not key in convertible_columns or not conversion_factors[row_idx]: + continue - result[row_idx] = new_row + if convertible_columns.get(key) == 'rate': + new_value = flt(value) * conversion_factors[row_idx] + else: + new_value = flt(value) / conversion_factors[row_idx] + + if not is_dict_obj: + row.insert(key+1, new_value) + else: + new_key = "{0}_{1}".format(key, frappe.scrub(include_uom)) + row[new_key] = new_value def get_available_serial_nos(item_code, warehouse): return frappe.get_all("Serial No", filters = {'item_code': item_code, From b54f0fb388dfbb71fe845c91fb9ee7c7363faeda Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Mon, 30 Sep 2019 15:19:56 +0530 Subject: [PATCH 11/18] fix: Party column empty in accounts receivable/ payable summary (#19205) --- .../accounts_receivable_summary.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py index 350e081957..b90a7a9501 100644 --- a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py +++ b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals import frappe -from frappe import _ +from frappe import _, scrub from frappe.utils import flt, cint from erpnext.accounts.party import get_partywise_advanced_payment_amount from erpnext.accounts.report.accounts_receivable.accounts_receivable import ReceivablePayableReport @@ -40,7 +40,7 @@ class AccountsReceivableSummary(ReceivablePayableReport): row.party = party if self.party_naming_by == "Naming Series": - row.party_name = frappe.get_cached_value(self.party_type, party, [self.party_type + "_name"]) + row.party_name = frappe.get_cached_value(self.party_type, party, scrub(self.party_type) + "_name") row.update(party_dict) From 8d889ef80e18ae6533d2686bae61d6226aaab2ca Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Mon, 30 Sep 2019 15:22:12 +0530 Subject: [PATCH 12/18] fix: update the pending qty in production plan on completion of work order (#19180) --- erpnext/manufacturing/doctype/production_plan/production_plan.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py index b51420ffdb..04359e3f5d 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py @@ -195,6 +195,7 @@ class ProductionPlan(Document): for data in self.po_items: if data.name == production_plan_item: data.produced_qty = produced_qty + data.pending_qty = data.planned_qty - data.produced_qty data.db_update() self.calculate_total_produced_qty() From de15cc1387d167e41db5258364144c81a255a1c1 Mon Sep 17 00:00:00 2001 From: Marica Date: Mon, 30 Sep 2019 15:36:33 +0530 Subject: [PATCH 13/18] fix: Work order dialog box 'Select Quantity' on clicking 'Finish' (#19136) The dialog box fetched 0 as Quantity to Manufacture and Max Quantity on finishing a Work Order --- .../manufacturing/doctype/work_order/work_order.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/erpnext/manufacturing/doctype/work_order/work_order.js b/erpnext/manufacturing/doctype/work_order/work_order.js index ce7b4f9425..96e44c881b 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.js +++ b/erpnext/manufacturing/doctype/work_order/work_order.js @@ -545,11 +545,14 @@ erpnext.work_order = { get_max_transferable_qty: (frm, purpose) => { let max = 0; - if (frm.doc.skip_transfer) return max; - if (purpose === 'Manufacture') { - max = flt(frm.doc.material_transferred_for_manufacturing) - flt(frm.doc.produced_qty); + if (frm.doc.skip_transfer) { + max = flt(frm.doc.qty) - flt(frm.doc.produced_qty); } else { - max = flt(frm.doc.qty) - flt(frm.doc.material_transferred_for_manufacturing); + if (purpose === 'Manufacture') { + max = flt(frm.doc.material_transferred_for_manufacturing) - flt(frm.doc.produced_qty); + } else { + max = flt(frm.doc.qty) - flt(frm.doc.material_transferred_for_manufacturing); + } } return flt(max, precision('qty')); }, From 905573700be41b5fa8b08c5a7939f969db29e9f8 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Mon, 30 Sep 2019 16:10:47 +0530 Subject: [PATCH 14/18] feat(report): fixed asset register (#19164) * feat(report): fixed asset register * fix: fetch supplier and check for asset status * fix: fetch vendor name from purchase invoice * style(fixed-asset-register): use conventional column name * Update fixed_asset_register.py --- .../report/fixed_asset_register/__init__.py | 0 .../fixed_asset_register.js | 30 +++ .../fixed_asset_register.json | 27 +++ .../fixed_asset_register.py | 172 ++++++++++++++++++ 4 files changed, 229 insertions(+) create mode 100644 erpnext/assets/report/fixed_asset_register/__init__.py create mode 100644 erpnext/assets/report/fixed_asset_register/fixed_asset_register.js create mode 100644 erpnext/assets/report/fixed_asset_register/fixed_asset_register.json create mode 100644 erpnext/assets/report/fixed_asset_register/fixed_asset_register.py diff --git a/erpnext/assets/report/fixed_asset_register/__init__.py b/erpnext/assets/report/fixed_asset_register/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/assets/report/fixed_asset_register/fixed_asset_register.js b/erpnext/assets/report/fixed_asset_register/fixed_asset_register.js new file mode 100644 index 0000000000..5e994b5c9c --- /dev/null +++ b/erpnext/assets/report/fixed_asset_register/fixed_asset_register.js @@ -0,0 +1,30 @@ +// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt +/* eslint-disable */ + +frappe.query_reports["Fixed Asset Register"] = { + "filters": [ + { + fieldname:"company", + label: __("Company"), + fieldtype: "Link", + options: "Company", + default: frappe.defaults.get_user_default("Company"), + reqd: 1 + }, + { + fieldname:"status", + label: __("Status"), + fieldtype: "Select", + options: "In Store\nDisposed", + default: 'In Store', + reqd: 1 + }, + { + fieldname:"finance_book", + label: __("Finance Book"), + fieldtype: "Link", + options: "Finance Book" + }, + ] +}; diff --git a/erpnext/assets/report/fixed_asset_register/fixed_asset_register.json b/erpnext/assets/report/fixed_asset_register/fixed_asset_register.json new file mode 100644 index 0000000000..ae2aa542f5 --- /dev/null +++ b/erpnext/assets/report/fixed_asset_register/fixed_asset_register.json @@ -0,0 +1,27 @@ +{ + "add_total_row": 0, + "creation": "2019-09-23 16:35:02.836134", + "disable_prepared_report": 0, + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "idx": 0, + "is_standard": "Yes", + "modified": "2019-09-23 16:35:02.836134", + "modified_by": "Administrator", + "module": "Assets", + "name": "Fixed Asset Register", + "owner": "Administrator", + "prepared_report": 0, + "ref_doctype": "Asset", + "report_name": "Fixed Asset Register", + "report_type": "Script Report", + "roles": [ + { + "role": "Accounts User" + }, + { + "role": "Quality Manager" + } + ] +} \ No newline at end of file diff --git a/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py b/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py new file mode 100644 index 0000000000..eac0e2a0bf --- /dev/null +++ b/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py @@ -0,0 +1,172 @@ +# 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): + filters = frappe._dict(filters or {}) + columns = get_columns(filters) + data = get_data(filters) + return columns, data + +def get_columns(filters): + return [ + { + "label": _("Asset Id"), + "fieldtype": "Link", + "fieldname": "asset_id", + "options": "Asset", + "width": 100 + }, + { + "label": _("Asset Name"), + "fieldtype": "Data", + "fieldname": "asset_name", + "width": 140 + }, + { + "label": _("Asset Category"), + "fieldtype": "Link", + "fieldname": "asset_category", + "options": "Asset Category", + "width": 100 + }, + { + "label": _("Status"), + "fieldtype": "Data", + "fieldname": "status", + "width": 90 + }, + { + "label": _("Cost Center"), + "fieldtype": "Link", + "fieldname": "cost_center", + "options": "Cost Center", + "width": 100 + }, + { + "label": _("Department"), + "fieldtype": "Link", + "fieldname": "department", + "options": "Department", + "width": 100 + }, + { + "label": _("Location"), + "fieldtype": "Link", + "fieldname": "location", + "options": "Location", + "width": 100 + }, + { + "label": _("Purchase Date"), + "fieldtype": "Date", + "fieldname": "purchase_date", + "width": 90 + }, + { + "label": _("Gross Purchase Amount"), + "fieldname": "gross_purchase_amount", + "options": "Currency", + "width": 90 + }, + { + "label": _("Vendor Name"), + "fieldtype": "Data", + "fieldname": "vendor_name", + "width": 100 + }, + { + "label": _("Available For Use Date"), + "fieldtype": "Date", + "fieldname": "available_for_use_date", + "width": 90 + }, + { + "label": _("Current Value"), + "fieldname": "current_value", + "options": "Currency", + "width": 90 + }, + ] + +def get_conditions(filters): + conditions = {'docstatus': 1} + status = filters.status + + if filters.company: + conditions["company"] = filters.company + + # In Store assets are those that are not sold or scrapped + operand = 'not in' + if status not in 'In Store': + operand = 'in' + + conditions['status'] = (operand, ['Sold', 'Scrapped']) + + return conditions + +def get_data(filters): + + data = [] + + conditions = get_conditions(filters) + current_value_map = get_finance_book_value_map(filters.finance_book) + pr_supplier_map = get_purchase_receipt_supplier_map() + pi_supplier_map = get_purchase_invoice_supplier_map() + + assets_record = frappe.db.get_all("Asset", + filters=conditions, + fields=["name", "asset_name", "department", "cost_center", "purchase_receipt", + "asset_category", "purchase_date", "gross_purchase_amount", "location", + "available_for_use_date", "status", "purchase_invoice"]) + + for asset in assets_record: + if current_value_map.get(asset.name) is not None: + row = { + "asset_id": asset.name, + "asset_name": asset.asset_name, + "status": asset.status, + "department": asset.department, + "cost_center": asset.cost_center, + "vendor_name": pr_supplier_map.get(asset.purchase_receipt) or pi_supplier_map.get(asset.purchase_invoice), + "gross_purchase_amount": asset.gross_purchase_amount, + "available_for_use_date": asset.available_for_use_date, + "location": asset.location, + "asset_category": asset.asset_category, + "purchase_date": asset.purchase_date, + "current_value": current_value_map.get(asset.name) + } + data.append(row) + + return data + +def get_finance_book_value_map(finance_book=''): + return frappe._dict(frappe.db.sql(''' Select + parent, value_after_depreciation + FROM `tabAsset Finance Book` + WHERE + parentfield='finance_books' + AND finance_book=%s''', (finance_book))) + +def get_purchase_receipt_supplier_map(): + return frappe._dict(frappe.db.sql(''' Select + pr.name, pr.supplier + FROM `tabPurchase Receipt` pr, `tabPurchase Receipt Item` pri + WHERE + pri.parent = pr.name + AND pri.is_fixed_asset=1 + AND pr.docstatus=1 + AND pr.is_return=0''')) + +def get_purchase_invoice_supplier_map(): + return frappe._dict(frappe.db.sql(''' Select + pi.name, pi.supplier + FROM `tabPurchase Invoice` pi, `tabPurchase Invoice Item` pii + WHERE + pii.parent = pi.name + AND pii.is_fixed_asset=1 + AND pi.docstatus=1 + AND pi.is_return=0''')) From 25e043766a3d30c94f2e7a82e1ba437bc6971d9d Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 30 Sep 2019 16:36:23 +0530 Subject: [PATCH 15/18] fix: Get leave approvers in Employee leave balance report (#19211) --- .../report/employee_leave_balance/employee_leave_balance.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py b/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py index 7717ba0e40..e967db87c4 100644 --- a/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py +++ b/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py @@ -60,7 +60,10 @@ def get_data(filters, leave_types): data = [] for employee in active_employees: - leave_approvers = department_approver_map.get(employee.department_name, []).append(employee.leave_approver) + leave_approvers = department_approver_map.get(employee.department_name, []) + if employee.leave_approver: + leave_approvers.append(employee.leave_approver) + if (len(leave_approvers) and user in leave_approvers) or (user in ["Administrator", employee.user_id]) or ("HR Manager" in frappe.get_roles(user)): row = [employee.name, employee.employee_name, employee.department] From d463c346feb2ee373e14d184843b331225a53563 Mon Sep 17 00:00:00 2001 From: Rohan Date: Mon, 30 Sep 2019 16:37:29 +0530 Subject: [PATCH 16/18] fix: set no-copy on some contract fields (#19208) --- erpnext/crm/doctype/contract/contract.json | 1249 ++++---------------- 1 file changed, 258 insertions(+), 991 deletions(-) diff --git a/erpnext/crm/doctype/contract/contract.json b/erpnext/crm/doctype/contract/contract.json index d48cc3762c..e04ad30ea7 100755 --- a/erpnext/crm/doctype/contract/contract.json +++ b/erpnext/crm/doctype/contract/contract.json @@ -1,1034 +1,301 @@ { - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 1, - "allow_rename": 1, - "autoname": "", - "beta": 0, - "creation": "2018-04-12 06:32:04.582486", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", + "allow_import": 1, + "allow_rename": 1, + "creation": "2018-04-12 06:32:04.582486", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "party_type", + "is_signed", + "cb_party", + "party_name", + "party_user", + "status", + "fulfilment_status", + "sb_terms", + "start_date", + "cb_date", + "end_date", + "sb_signee", + "signee", + "signed_on", + "cb_user", + "ip_address", + "sb_contract", + "contract_template", + "contract_terms", + "sb_fulfilment", + "requires_fulfilment", + "fulfilment_deadline", + "fulfilment_terms", + "sb_references", + "document_type", + "cb_links", + "document_name", + "amended_from" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "Customer", - "fieldname": "party_type", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Party Type", - "length": 0, - "no_copy": 0, - "options": "Customer\nSupplier\nEmployee", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "Customer", + "fieldname": "party_type", + "fieldtype": "Select", + "label": "Party Type", + "options": "Customer\nSupplier\nEmployee", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "is_signed", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Signed", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "allow_on_submit": 1, + "default": "0", + "fieldname": "is_signed", + "fieldtype": "Check", + "label": "Signed", + "no_copy": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "cb_party", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "cb_party", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "party_name", - "fieldtype": "Dynamic Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 1, - "label": "Party Name", - "length": 0, - "no_copy": 0, - "options": "party_type", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "party_name", + "fieldtype": "Dynamic Link", + "in_standard_filter": 1, + "label": "Party Name", + "options": "party_type", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fieldname": "party_user", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Party User", - "length": 0, - "no_copy": 0, - "options": "User", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "party_user", + "fieldtype": "Link", + "label": "Party User", + "options": "User" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "status", - "fieldtype": "Select", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 1, - "label": "Status", - "length": 0, - "no_copy": 0, - "options": "Unsigned\nActive\nInactive", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "allow_on_submit": 1, + "fieldname": "status", + "fieldtype": "Select", + "hidden": 1, + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Status", + "no_copy": 1, + "options": "Unsigned\nActive\nInactive" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "fulfilment_status", - "fieldtype": "Select", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 1, - "label": "Fulfilment Status", - "length": 0, - "no_copy": 0, - "options": "N/A\nUnfulfilled\nPartially Fulfilled\nFulfilled\nLapsed", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "allow_on_submit": 1, + "fieldname": "fulfilment_status", + "fieldtype": "Select", + "hidden": 1, + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Fulfilment Status", + "no_copy": 1, + "options": "N/A\nUnfulfilled\nPartially Fulfilled\nFulfilled\nLapsed" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "sb_terms", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Contract Period", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "sb_terms", + "fieldtype": "Section Break", + "label": "Contract Period" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "start_date", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Start Date", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "start_date", + "fieldtype": "Date", + "label": "Start Date" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "cb_date", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "cb_date", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "end_date", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "End Date", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "end_date", + "fieldtype": "Date", + "label": "End Date" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "collapsible_depends_on": "", - "columns": 0, - "depends_on": "eval:doc.is_signed==1", - "fieldname": "sb_signee", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Signee Details", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "depends_on": "eval:doc.is_signed==1", + "fieldname": "sb_signee", + "fieldtype": "Section Break", + "label": "Signee Details" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fieldname": "signee", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 1, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Signee", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "allow_on_submit": 1, + "fieldname": "signee", + "fieldtype": "Data", + "in_global_search": 1, + "label": "Signee", + "no_copy": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fieldname": "signed_on", - "fieldtype": "Datetime", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Signed On", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "allow_on_submit": 1, + "fieldname": "signed_on", + "fieldtype": "Datetime", + "in_list_view": 1, + "label": "Signed On", + "no_copy": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "cb_user", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "cb_user", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fieldname": "ip_address", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "IP Address", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "allow_on_submit": 1, + "fieldname": "ip_address", + "fieldtype": "Data", + "label": "IP Address", + "no_copy": 1, + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "collapsible_depends_on": "eval:doc.docstatus==0", - "columns": 0, - "fieldname": "sb_contract", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Contract Details", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "collapsible": 1, + "collapsible_depends_on": "eval:doc.docstatus==0", + "fieldname": "sb_contract", + "fieldtype": "Section Break", + "label": "Contract Details" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "contract_template", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Contract Template", - "length": 0, - "no_copy": 0, - "options": "Contract Template", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "contract_template", + "fieldtype": "Link", + "label": "Contract Template", + "options": "Contract Template" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "contract_terms", - "fieldtype": "Text Editor", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Contract Terms", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "contract_terms", + "fieldtype": "Text Editor", + "in_list_view": 1, + "label": "Contract Terms", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "sb_fulfilment", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Fulfilment Details", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "sb_fulfilment", + "fieldtype": "Section Break", + "label": "Fulfilment Details" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "requires_fulfilment", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Requires Fulfilment", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "0", + "fieldname": "requires_fulfilment", + "fieldtype": "Check", + "label": "Requires Fulfilment" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.requires_fulfilment==1", - "fieldname": "fulfilment_deadline", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Fulfilment Deadline", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "depends_on": "eval:doc.requires_fulfilment==1", + "fieldname": "fulfilment_deadline", + "fieldtype": "Date", + "label": "Fulfilment Deadline" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.requires_fulfilment==1", - "fieldname": "fulfilment_terms", - "fieldtype": "Table", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Fulfilment Terms", - "length": 0, - "no_copy": 0, - "options": "Contract Fulfilment Checklist", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "allow_on_submit": 1, + "depends_on": "eval:doc.requires_fulfilment==1", + "fieldname": "fulfilment_terms", + "fieldtype": "Table", + "label": "Fulfilment Terms", + "options": "Contract Fulfilment Checklist" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "columns": 0, - "fieldname": "sb_references", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "References", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "collapsible": 1, + "fieldname": "sb_references", + "fieldtype": "Section Break", + "label": "References" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "", - "depends_on": "", - "fieldname": "document_type", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Document Type", - "length": 0, - "no_copy": 0, - "options": "\nQuotation\nProject\nSales Order\nPurchase Order\nSales Invoice\nPurchase Invoice", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "document_type", + "fieldtype": "Select", + "label": "Document Type", + "options": "\nQuotation\nProject\nSales Order\nPurchase Order\nSales Invoice\nPurchase Invoice" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "cb_links", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "cb_links", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fieldname": "document_name", - "fieldtype": "Dynamic Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 1, - "in_list_view": 1, - "in_standard_filter": 1, - "label": "Document Name", - "length": 0, - "no_copy": 0, - "options": "document_type", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "document_name", + "fieldtype": "Dynamic Link", + "in_global_search": 1, + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Document Name", + "options": "document_type" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "amended_from", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Amended From", - "length": 0, - "no_copy": 1, - "options": "Contract", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "fieldname": "amended_from", + "fieldtype": "Link", + "label": "Amended From", + "no_copy": 1, + "options": "Contract", + "print_hide": 1, + "read_only": 1 } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 1, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2018-06-14 12:47:10.142988", - "modified_by": "Administrator", - "module": "CRM", - "name": "Contract", - "name_case": "", - "owner": "Administrator", + ], + "is_submittable": 1, + "modified": "2019-09-30 00:56:41.559681", + "modified_by": "Administrator", + "module": "CRM", + "name": "Contract", + "owner": "Administrator", "permissions": [ { - "amend": 1, - "cancel": 1, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Sales Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 1, + "amend": 1, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Sales Manager", + "share": 1, + "submit": 1, "write": 1 - }, + }, { - "amend": 1, - "cancel": 1, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Purchase Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 1, + "amend": 1, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Purchase Manager", + "share": 1, + "submit": 1, "write": 1 - }, + }, { - "amend": 1, - "cancel": 1, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "HR Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 1, + "amend": 1, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "HR Manager", + "share": 1, + "submit": 1, "write": 1 - }, + }, { - "amend": 1, - "cancel": 1, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 1, + "amend": 1, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "submit": 1, "write": 1 } - ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 1, - "sort_field": "modified", - "sort_order": "DESC", - "title_field": "", - "track_changes": 1, + ], + "show_name_in_global_search": 1, + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1, "track_seen": 1 } \ No newline at end of file From 20194c4cc577f34e01a0f959568f1f45b89eac91 Mon Sep 17 00:00:00 2001 From: DeeMysterio Date: Mon, 30 Sep 2019 16:59:15 +0530 Subject: [PATCH 17/18] rename return/invoice to Purchase return/invoice (#19212) --- erpnext/stock/doctype/purchase_receipt/purchase_receipt.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js index 2e8bc64038..aef53ed74b 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js @@ -115,12 +115,12 @@ erpnext.stock.PurchaseReceiptController = erpnext.buying.BuyingController.extend cur_frm.add_custom_button(__("Close"), this.close_purchase_receipt, __("Status")) } - cur_frm.add_custom_button(__('Return'), this.make_purchase_return, __('Create')); + cur_frm.add_custom_button(__('Purchase Return'), this.make_purchase_return, __('Create')); cur_frm.add_custom_button(__('Make Stock Entry'), cur_frm.cscript['Make Stock Entry'], __('Create')); if(flt(this.frm.doc.per_billed) < 100) { - cur_frm.add_custom_button(__('Invoice'), this.make_purchase_invoice, __('Create')); + cur_frm.add_custom_button(__('Purchase Invoice'), this.make_purchase_invoice, __('Create')); } cur_frm.add_custom_button(__('Retention Stock Entry'), this.make_retention_stock_entry, __('Create')); From 9d26c69c4a86c527b10a8333f75dc17628d85ce6 Mon Sep 17 00:00:00 2001 From: Chinmay Pai Date: Mon, 30 Sep 2019 16:59:42 +0530 Subject: [PATCH 18/18] fix(amazon-mws): python3 compatibility changes (#19209) Signed-off-by: Chinmay D. Pai --- .../doctype/amazon_mws_settings/amazon_methods.py | 12 +++++------- .../doctype/amazon_mws_settings/amazon_mws_api.py | 6 +++--- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_methods.py b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_methods.py index b9be9c0b9c..2f39dc596b 100644 --- a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_methods.py +++ b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_methods.py @@ -4,10 +4,7 @@ from __future__ import unicode_literals import frappe, time, dateutil, math, csv -try: - from StringIO import StringIO -except ImportError: - from io import StringIO +from six import StringIO import erpnext.erpnext_integrations.doctype.amazon_mws_settings.amazon_mws_api as mws from frappe import _ @@ -26,7 +23,7 @@ def get_products_details(): listings_response = reports.get_report(report_id=report_id) #Get ASIN Codes - string_io = StringIO(listings_response.original) + string_io = StringIO(frappe.safe_decode(listings_response.original)) csv_rows = list(csv.reader(string_io, delimiter=str('\t'))) asin_list = list(set([row[1] for row in csv_rows[1:]])) #break into chunks of 10 @@ -294,7 +291,8 @@ def create_sales_order(order_json,after_date): so.submit() except Exception as e: - frappe.log_error(message=e, title="Create Sales Order") + import traceback + frappe.log_error(message=traceback.format_exc(), title="Create Sales Order") def create_customer(order_json): order_customer_name = "" @@ -451,7 +449,7 @@ def get_charges_and_fees(market_place_order_id): shipment_item_list = return_as_list(shipment_event.ShipmentEvent.ShipmentItemList.ShipmentItem) for shipment_item in shipment_item_list: - charges, fees = [] + charges, fees = [], [] if 'ItemChargeList' in shipment_item.keys(): charges = return_as_list(shipment_item.ItemChargeList.ChargeComponent) diff --git a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_api.py b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_api.py index 68c2b9c324..9925dc4a08 100755 --- a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_api.py +++ b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_api.py @@ -65,7 +65,8 @@ def calc_md5(string): """ md = hashlib.md5() md.update(string) - return base64.encodestring(md.digest()).strip('\n') + return base64.encodestring(md.digest()).strip('\n') if six.PY2 \ + else base64.encodebytes(md.digest()).decode().strip() def remove_empty(d): """ @@ -87,8 +88,7 @@ class DictWrapper(object): self.original = xml self._rootkey = rootkey self._mydict = xml_utils.xml2dict().fromstring(remove_namespace(xml)) - self._response_dict = self._mydict.get(self._mydict.keys()[0], - self._mydict) + self._response_dict = self._mydict.get(list(self._mydict)[0], self._mydict) @property def parsed(self):