Merge pull request #5514 from cgpurbaugh/patch-1
Update tasks.md
diff --git a/erpnext/accounts/report/purchase_register/purchase_register.py b/erpnext/accounts/report/purchase_register/purchase_register.py
index 9a90f2f..4bba066 100644
--- a/erpnext/accounts/report/purchase_register/purchase_register.py
+++ b/erpnext/accounts/report/purchase_register/purchase_register.py
@@ -147,10 +147,11 @@
def get_invoice_tax_map(invoice_list, invoice_expense_map, expense_accounts):
tax_details = frappe.db.sql("""
- select parent, account_head, sum(base_tax_amount_after_discount_amount) as tax_amount
+ select parent, account_head, case add_deduct_tax when "Add" then sum(base_tax_amount_after_discount_amount)
+ else sum(base_tax_amount_after_discount_amount) * -1 end as tax_amount
from `tabPurchase Taxes and Charges`
where parent in (%s) and category in ('Total', 'Valuation and Total')
- group by parent, account_head
+ group by parent, account_head, add_deduct_tax
""" % ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1)
invoice_tax_map = {}
diff --git a/erpnext/buying/doctype/purchase_common/purchase_common.js b/erpnext/buying/doctype/purchase_common/purchase_common.js
index 6416a23..c684715 100644
--- a/erpnext/buying/doctype/purchase_common/purchase_common.js
+++ b/erpnext/buying/doctype/purchase_common/purchase_common.js
@@ -25,6 +25,26 @@
onload: function() {
this.setup_queries();
this._super();
+
+ if(this.frm.get_field('shipping_address')) {
+ this.frm.set_query("shipping_address", function(){
+ if(me.frm.doc.customer){
+ return{
+ filters:{
+ "customer": me.frm.doc.customer
+ }
+ }
+ }
+ else{
+ return{
+ filters:{
+ "is_your_company_address": 1,
+ "company": me.frm.doc.company
+ }
+ }
+ }
+ });
+ }
},
setup_queries: function() {
@@ -225,25 +245,6 @@
shipping_address: function(){
var me = this;
-
- this.frm.set_query("shipping_address", function(){
- if(me.frm.doc.customer){
- return{
- filters:{
- "customer": me.frm.doc.customer
- }
- }
- }
- else{
- return{
- filters:{
- "is_your_company_address": 1,
- "company": me.frm.doc.company
- }
- }
- }
- });
-
erpnext.utils.get_address_display(this.frm, "shipping_address",
"shipping_address_display", is_your_company_address=true)
},
diff --git a/erpnext/config/crm.py b/erpnext/config/crm.py
index 26e9e03..dfefb75 100644
--- a/erpnext/config/crm.py
+++ b/erpnext/config/crm.py
@@ -40,6 +40,12 @@
},
{
"type": "report",
+ "name": "Minutes to First Response for Opportunity",
+ "doctype": "Opportunity",
+ "is_query_report": True
+ },
+ {
+ "type": "report",
"is_query_report": True,
"name": "Lead Details",
"doctype": "Lead"
diff --git a/erpnext/crm/doctype/newsletter_list/newsletter_list.py b/erpnext/crm/doctype/newsletter_list/newsletter_list.py
index c3604f8..68c445f 100644
--- a/erpnext/crm/doctype/newsletter_list/newsletter_list.py
+++ b/erpnext/crm/doctype/newsletter_list/newsletter_list.py
@@ -89,3 +89,14 @@
frappe.msgprint(_("{0} subscribers added").format(count))
return frappe.get_doc("Newsletter List", name).update_total_subscribers()
+
+def restrict_newsletter_list(doc, method):
+ from frappe.limits import get_limits
+
+ newsletter_list_limit = get_limits().get('newsletter_recipients')
+ if not newsletter_list_limit:
+ return
+
+ nl = frappe.get_doc("Newsletter List", doc.newsletter_list)
+ if nl.get_total_subscribers() >= newsletter_list_limit:
+ frappe.throw(_("Please Upgrade to add more than {0} subscribers").format(newsletter_list_limit))
\ No newline at end of file
diff --git a/erpnext/crm/report/__init__.py b/erpnext/crm/report/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/crm/report/__init__.py
diff --git a/erpnext/crm/report/minutes_to_first_response_for_opportunity/__init__.py b/erpnext/crm/report/minutes_to_first_response_for_opportunity/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/crm/report/minutes_to_first_response_for_opportunity/__init__.py
diff --git a/erpnext/crm/report/minutes_to_first_response_for_opportunity/minutes_to_first_response_for_opportunity.js b/erpnext/crm/report/minutes_to_first_response_for_opportunity/minutes_to_first_response_for_opportunity.js
new file mode 100644
index 0000000..b1e4917
--- /dev/null
+++ b/erpnext/crm/report/minutes_to_first_response_for_opportunity/minutes_to_first_response_for_opportunity.js
@@ -0,0 +1,43 @@
+// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.query_reports["Minutes to First Response for Opportunity"] = {
+ "filters": [
+ {
+ "fieldname":"from_date",
+ "label": __("From Date"),
+ "fieldtype": "Date",
+ 'reqd': 1,
+ "default": frappe.datetime.add_days(frappe.datetime.nowdate(), -30)
+ },
+ {
+ "fieldname":"to_date",
+ "label": __("To Date"),
+ "fieldtype": "Date",
+ 'reqd': 1,
+ "default":frappe.datetime.nowdate()
+ },
+ ],
+ get_chart_data: function(columns, result) {
+ return {
+ data: {
+ x: 'Date',
+ columns: [
+ ['Date'].concat($.map(result, function(d) { return d[0]; })),
+ ['Mins to first response'].concat($.map(result, function(d) { return d[1]; }))
+ ]
+ // rows: [['Date', 'Mins to first response']].concat(result)
+ },
+ axis: {
+ x: {
+ type: 'timeseries',
+ tick: {
+ format: frappe.ui.py_date_format
+ }
+ }
+ },
+ chart_type: 'line',
+
+ }
+ }
+}
diff --git a/erpnext/crm/report/minutes_to_first_response_for_opportunity/minutes_to_first_response_for_opportunity.json b/erpnext/crm/report/minutes_to_first_response_for_opportunity/minutes_to_first_response_for_opportunity.json
new file mode 100644
index 0000000..a366b3e
--- /dev/null
+++ b/erpnext/crm/report/minutes_to_first_response_for_opportunity/minutes_to_first_response_for_opportunity.json
@@ -0,0 +1,18 @@
+{
+ "add_total_row": 0,
+ "apply_user_permissions": 0,
+ "creation": "2016-06-17 11:28:25.867258",
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "idx": 0,
+ "is_standard": "Yes",
+ "modified": "2016-06-17 11:28:25.867258",
+ "modified_by": "Administrator",
+ "module": "CRM",
+ "name": "Minutes to First Response for Opportunity",
+ "owner": "Administrator",
+ "ref_doctype": "Opportunity",
+ "report_name": "Minutes to First Response for Opportunity",
+ "report_type": "Script Report"
+}
\ No newline at end of file
diff --git a/erpnext/crm/report/minutes_to_first_response_for_opportunity/minutes_to_first_response_for_opportunity.py b/erpnext/crm/report/minutes_to_first_response_for_opportunity/minutes_to_first_response_for_opportunity.py
new file mode 100644
index 0000000..54e3a60
--- /dev/null
+++ b/erpnext/crm/report/minutes_to_first_response_for_opportunity/minutes_to_first_response_for_opportunity.py
@@ -0,0 +1,28 @@
+# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+
+def execute(filters=None):
+ columns = [
+ {
+ 'fieldname': 'creation_date',
+ 'label': 'Date',
+ 'fieldtype': 'Date'
+ },
+ {
+ 'fieldname': 'mins',
+ 'fieldtype': 'Float',
+ 'label': 'Mins to First Response'
+ },
+ ]
+
+ data = frappe.db.sql('''select date(creation) as creation_date,
+ avg(mins_to_first_response) as mins
+ from tabOpportunity
+ where date(creation) between %s and %s
+ and mins_to_first_response > 0
+ group by creation_date order by creation_date desc''', (filters.from_date, filters.to_date))
+
+ return columns, data
diff --git a/erpnext/docs/user/manual/en/introduction/index.md b/erpnext/docs/user/manual/en/introduction/index.md
index 76e77b1..6471090 100644
--- a/erpnext/docs/user/manual/en/introduction/index.md
+++ b/erpnext/docs/user/manual/en/introduction/index.md
@@ -4,17 +4,12 @@
organization, you can skip this page.)
If you are running a small business that has a few employees, you understand
-that it's hard to manage the dynamic nature of doing businesses. You are
-already using a software like Accounting, and may be some more to manage your
-inventory and sales (or CRM).
-
-An ERP brings all of this together in one place.
-
-Small businesses are not so different from large ones. They contain most of
-the complexities of a large business along with many other constraints. Small
-businesses have to communicate with customers, do accounts, pay taxes, do
-payroll, manage timelines, deliver quality, answer questions, and keep
-everyone happy just like in large businesses.
+that it's hard to manage the dynamic nature of doing businesses. Small businesses
+are not so different from large ones. They contain most of the complexities of
+a large business along with many other constraints. Small businesses have to
+communicate with customers, do accounts, pay taxes, do payroll, manage timelines,
+deliver quality goods and services, answer questions, and keep everyone happy,
+just like in large businesses.
Large businesses have the advantage of using advanced data systems to manage
their process efficiently. Small businesses, on the other hand, typically
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 2bb2ca6..0c8de2a 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -136,6 +136,10 @@
"validate": "erpnext.shopping_cart.cart.set_customer_in_address"
},
+ "Newsletter List Subscriber": {
+ "validate": "erpnext.crm.doctype.newsletter_list.newsletter_list.restrict_newsletter_list"
+ },
+
# bubble transaction notification on master
('Opportunity', 'Quotation', 'Sales Order', 'Delivery Note', 'Sales Invoice',
'Supplier Quotation', 'Purchase Order', 'Purchase Receipt',
diff --git a/erpnext/manufacturing/doctype/production_order/production_order.js b/erpnext/manufacturing/doctype/production_order/production_order.js
index e4bf46f..ba7026e 100644
--- a/erpnext/manufacturing/doctype/production_order/production_order.js
+++ b/erpnext/manufacturing/doctype/production_order/production_order.js
@@ -220,7 +220,7 @@
flt(this.frm.doc.material_transferred_for_manufacturing) - flt(this.frm.doc.produced_qty) :
flt(this.frm.doc.qty) - flt(this.frm.doc.material_transferred_for_manufacturing);
- frappe.prompt({fieldtype:"Int", label: __("Qty for {0}", [purpose]), fieldname:"qty",
+ frappe.prompt({fieldtype:"Float", label: __("Qty for {0}", [purpose]), fieldname:"qty",
description: __("Max: {0}", [max]), 'default': max },
function(data) {
if(data.qty > max) {
diff --git a/erpnext/public/js/setup_wizard.js b/erpnext/public/js/setup_wizard.js
index d3ff8eb..511925c 100644
--- a/erpnext/public/js/setup_wizard.js
+++ b/erpnext/public/js/setup_wizard.js
@@ -20,7 +20,7 @@
description: __('Max 5 characters'), placeholder: __('e.g. "MC"'), reqd:1},
{fieldname:'company_tagline', label: __('What does it do?'), fieldtype:'Data',
placeholder:__('e.g. "Build tools for builders"'), reqd:1},
- {fieldname:'bank_account', label: __('Bank Account'), fieldtype:'Data',
+ {fieldname:'bank_account', label: __('Bank Name'), fieldtype:'Data',
placeholder: __('e.g. "XYZ National Bank"'), reqd:1 },
{fieldname:'domain', label: __('Domain'), fieldtype:'Select',
options: [
diff --git a/erpnext/support/report/minutes_to_first_response_for_issues/minutes_to_first_response_for_issues.js b/erpnext/support/report/minutes_to_first_response_for_issues/minutes_to_first_response_for_issues.js
index 9fd35d9..e84b13c 100644
--- a/erpnext/support/report/minutes_to_first_response_for_issues/minutes_to_first_response_for_issues.js
+++ b/erpnext/support/report/minutes_to_first_response_for_issues/minutes_to_first_response_for_issues.js
@@ -1,20 +1,20 @@
frappe.query_reports["Minutes to First Response for Issues"] = {
- "filters": [
- {
- "fieldname":"from_date",
- "label": __("From Date"),
- "fieldtype": "Date",
+ "filters": [
+ {
+ "fieldname":"from_date",
+ "label": __("From Date"),
+ "fieldtype": "Date",
'reqd': 1,
- "default": frappe.datetime.add_days(frappe.datetime.nowdate(), -30)
- },
- {
- "fieldname":"to_date",
- "label": __("To Date"),
- "fieldtype": "Date",
+ "default": frappe.datetime.add_days(frappe.datetime.nowdate(), -30)
+ },
+ {
+ "fieldname":"to_date",
+ "label": __("To Date"),
+ "fieldtype": "Date",
'reqd': 1,
- "default":frappe.datetime.nowdate()
- },
- ],
+ "default":frappe.datetime.nowdate()
+ },
+ ],
get_chart_data: function(columns, result) {
return {
data: {
@@ -25,14 +25,14 @@
]
// rows: [['Date', 'Mins to first response']].concat(result)
},
- axis: {
- x: {
- type: 'timeseries',
- tick: {
- format: '%Y-%m-%d'
- }
- }
- },
+ axis: {
+ x: {
+ type: 'timeseries',
+ tick: {
+ format: frappe.ui.py_date_format
+ }
+ }
+ },
chart_type: 'line',
}
diff --git a/erpnext/support/report/minutes_to_first_response_for_issues/minutes_to_first_response_for_issues.py b/erpnext/support/report/minutes_to_first_response_for_issues/minutes_to_first_response_for_issues.py
index e88e756..57c2d44 100644
--- a/erpnext/support/report/minutes_to_first_response_for_issues/minutes_to_first_response_for_issues.py
+++ b/erpnext/support/report/minutes_to_first_response_for_issues/minutes_to_first_response_for_issues.py
@@ -20,7 +20,9 @@
data = frappe.db.sql('''select date(creation) as creation_date,
avg(mins_to_first_response) as mins
- from tabIssue where date(creation) between %s and %s
+ from tabIssue
+ where date(creation) between %s and %s
+ and mins_to_first_response > 0
group by creation_date order by creation_date desc''', (filters.from_date, filters.to_date))
return columns, data