Merge branch 'master' of github.com:webnotes/erpnext
diff --git a/accounts/doctype/pos_setting/pos_setting.js b/accounts/doctype/pos_setting/pos_setting.js
index 18f555b..641b3ef 100755
--- a/accounts/doctype/pos_setting/pos_setting.js
+++ b/accounts/doctype/pos_setting/pos_setting.js
@@ -70,5 +70,5 @@
}
cur_frm.fields_dict.user.get_query = function(doc,cdt,cdn) {
- return{ query:"controllers.queries.profile_query"}
+ return{ query:"core.doctype.profile.profile.profile_query"}
}
diff --git a/accounts/doctype/sales_invoice/sales_invoice.js b/accounts/doctype/sales_invoice/sales_invoice.js
index 109d9f8..0c8fc37 100644
--- a/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/accounts/doctype/sales_invoice/sales_invoice.js
@@ -80,7 +80,6 @@
source_doctype: "Delivery Note",
get_query: function() {
var filters = {
- docstatus: 1,
company: cur_frm.doc.company
};
if(cur_frm.doc.customer) filters["customer"] = cur_frm.doc.customer;
diff --git a/controllers/queries.py b/controllers/queries.py
index 0e23d5c..02c992b 100644
--- a/controllers/queries.py
+++ b/controllers/queries.py
@@ -3,6 +3,7 @@
from __future__ import unicode_literals
import webnotes
+from webnotes.widgets.reportview import get_match_cond
def get_filters_cond(doctype, filters, conditions):
if filters:
@@ -22,34 +23,6 @@
cond = ''
return cond
-def get_match_cond(doctype, searchfield = 'name'):
- from webnotes.widgets.reportview import build_match_conditions
- cond = build_match_conditions(doctype)
-
- if cond:
- cond = ' and ' + cond
- else:
- cond = ''
- return cond
-
- # searches for enabled profiles
-def profile_query(doctype, txt, searchfield, start, page_len, filters):
- return webnotes.conn.sql("""select name, concat_ws(' ', first_name, middle_name, last_name)
- from `tabProfile`
- where ifnull(enabled, 0)=1
- and docstatus < 2
- and name not in ('Administrator', 'Guest')
- and (%(key)s like "%(txt)s"
- or concat_ws(' ', first_name, middle_name, last_name) like "%(txt)s")
- %(mcond)s
- order by
- case when name like "%(txt)s" then 0 else 1 end,
- case when concat_ws(' ', first_name, middle_name, last_name) like "%(txt)s"
- then 0 else 1 end,
- name asc
- limit %(start)s, %(page_len)s""" % {'key': searchfield, 'txt': "%%%s%%" % txt,
- 'mcond':get_match_cond(doctype, searchfield), 'start': start, 'page_len': page_len})
-
# searches for active employees
def employee_query(doctype, txt, searchfield, start, page_len, filters):
return webnotes.conn.sql("""select name, employee_name from `tabEmployee`
@@ -196,10 +169,12 @@
def get_delivery_notes_to_be_billed(doctype, txt, searchfield, start, page_len, filters):
return webnotes.conn.sql("""select `tabDelivery Note`.name, `tabDelivery Note`.customer_name
from `tabDelivery Note`
- where `tabDelivery Note`.`%(key)s` like %(txt)s %(fcond)s and
+ where `tabDelivery Note`.`%(key)s` like %(txt)s and
+ `tabDelivery Note`.docstatus = 1 %(fcond)s and
(ifnull((select sum(qty) from `tabDelivery Note Item` where
`tabDelivery Note Item`.parent=`tabDelivery Note`.name), 0) >
ifnull((select sum(qty) from `tabSales Invoice Item` where
+ `tabSales Invoice Item`.docstatus = 1 and
`tabSales Invoice Item`.delivery_note=`tabDelivery Note`.name), 0))
%(mcond)s order by `tabDelivery Note`.`%(key)s` asc
limit %(start)s, %(page_len)s""" % {
diff --git a/docs/dev/custom_script_examples/docs.dev.custom_script.calculate.md b/docs/dev/custom_script_examples/docs.dev.custom_script.calculate.md
new file mode 100644
index 0000000..6744e2b
--- /dev/null
+++ b/docs/dev/custom_script_examples/docs.dev.custom_script.calculate.md
@@ -0,0 +1,24 @@
+---
+{
+ "_label": "Calculate Incentive for Sales Team"
+}
+---
+Can be used in any Sales Transaction with **Sales Team** Table:
+
+
+ cur_frm.cscript.custom_validate = function(doc) {
+ // calculate incentives for each person on the deal
+ total_incentive = 0
+ $.each(wn.model.get("Sales Team", {parent:doc.name}), function(i, d) {
+
+ // calculate incentive
+ var incentive_percent = 2;
+ if(doc.grand_total > 400) incentive_percent = 4;
+
+ // actual incentive
+ d.incentives = flt(doc.grand_total) * incentive_percent / 100;
+ total_incentive += flt(d.incentives)
+ });
+
+ doc.total_incentive = total_incentive;
+ }
\ No newline at end of file
diff --git a/docs/dev/custom_script_examples/docs.dev.custom_script.fetch.md b/docs/dev/custom_script_examples/docs.dev.custom_script.fetch.md
new file mode 100644
index 0000000..d0414fb
--- /dev/null
+++ b/docs/dev/custom_script_examples/docs.dev.custom_script.fetch.md
@@ -0,0 +1,20 @@
+---
+{
+ "_label": "Custom Script: Fetch Values from Master"
+}
+---
+To pull a value of a link on selection, use the `add_fetch` method.
+
+ add_fetch(link_fieldname, source_fieldname, target_fieldname)
+
+### Example
+
+You create Custom Field **VAT ID** (`vat_id`) in **Customer** and **Sales Invoice** and want to make sure this value gets updated every time you select a Customer in a Sales Invoice.
+
+Then in the Sales Invoice Custom Script, add this line:
+
+ cur_frm.add_fetch('customer','vat_id','vat_id')
+
+
+---
+See: [How to create a custom script](!docs.dev.custom_script.html)
\ No newline at end of file
diff --git a/docs/dev/custom_script_examples/docs.dev.custom_script.item_code.md b/docs/dev/custom_script_examples/docs.dev.custom_script.item_code.md
new file mode 100644
index 0000000..22e75c9
--- /dev/null
+++ b/docs/dev/custom_script_examples/docs.dev.custom_script.item_code.md
@@ -0,0 +1,35 @@
+---
+{
+ "_label": "Generate Item Code based on Custom Logic"
+}
+---
+Add this in the Custom Script of **Item**, so that the new Item Code is generated just before the a new Item is saved.
+
+ cur_frm.cscript.custom_validate = function(doc) {
+ // clear item_code (name is from item_code)
+ doc.item_code = "";
+
+ // first 2 characters based on item_group
+ switch(doc.item_group) {
+ case "Test A":
+ doc.item_code = "TA";
+ break;
+ case "Test B":
+ doc.item_code = "TB";
+ break;
+ default:
+ doc.item_code = "XX";
+ }
+
+ // add next 2 characters based on brand
+ switch(doc.brand) {
+ case "Brand A":
+ doc.item_code += "BA";
+ break;
+ case "Brand B":
+ doc.item_code += "BB";
+ break;
+ default:
+ doc.item_code += "BX";
+ }
+ }
\ No newline at end of file
diff --git a/docs/dev/custom_script_examples/docs.dev.custom_script.read_only.md b/docs/dev/custom_script_examples/docs.dev.custom_script.read_only.md
new file mode 100644
index 0000000..9da3e85
--- /dev/null
+++ b/docs/dev/custom_script_examples/docs.dev.custom_script.read_only.md
@@ -0,0 +1,13 @@
+---
+{
+ "_label": "Make an Item read-only after Saving"
+}
+---
+Use the method `cur_frm.set_df_property` to update the field's display.
+
+In this script we also use the `__islocal` property of the doc to check if the document has been saved atleast once or is never saved. If `__islocal` is `1`, then the document has never been saved.
+
+ cur_frm.cscript.custom_refresh = function(doc) {
+ // use the __islocal value of doc, to check if the doc is saved or not
+ cur_frm.set_df_property("myfield", "read_only", doc.__islocal ? 0 : 1);
+ }
\ No newline at end of file
diff --git a/docs/dev/custom_script_examples/docs.dev.custom_script.validate.md b/docs/dev/custom_script_examples/docs.dev.custom_script.validate.md
new file mode 100644
index 0000000..a22851c
--- /dev/null
+++ b/docs/dev/custom_script_examples/docs.dev.custom_script.validate.md
@@ -0,0 +1,12 @@
+---
+{
+ "_label": "Date Validation: Do not allow past dates in a date field"
+}
+---
+
+ cur_frm.cscript.custom_validate = function(doc) {
+ if (doc.from_date < get_today()) {
+ msgprint("You can not select past date in From Date");
+ validated = false;
+ }
+ }
\ No newline at end of file
diff --git a/docs/dev/custom_script_examples/docs.dev.custom_script.validate1.md b/docs/dev/custom_script_examples/docs.dev.custom_script.validate1.md
new file mode 100644
index 0000000..b12c61f
--- /dev/null
+++ b/docs/dev/custom_script_examples/docs.dev.custom_script.validate1.md
@@ -0,0 +1,12 @@
+---
+{
+ "_label": "Restrict Purpose of Stock Entry"
+}
+---
+
+ cur_frm.cscript.custom_validate = function(doc) {
+ if(user=="user1@example.com" && doc.purpose!="Material Receipt") {
+ msgprint("You are only allowed Material Receipt");
+ validated = false;
+ }
+ }
\ No newline at end of file
diff --git a/docs/dev/custom_script_examples/docs.dev.custom_script.validate2.md b/docs/dev/custom_script_examples/docs.dev.custom_script.validate2.md
new file mode 100644
index 0000000..05d662e
--- /dev/null
+++ b/docs/dev/custom_script_examples/docs.dev.custom_script.validate2.md
@@ -0,0 +1,22 @@
+---
+{
+ "_label": "Restrict User Based on Child Record (Warehouse)"
+}
+---
+
+ // restrict certain warehouse to Material Manager
+ cur_frm.cscript.custom_validate = function(doc) {
+ if(user_roles.indexOf("Material Manager")==-1) {
+
+ var restricted_in_source = wn.model.get("Stock Entry Detail",
+ {parent:cur_frm.doc.name, s_warehouse:"Restricted"});
+
+ var restricted_in_target = wn.model.get("Stock Entry Detail",
+ {parent:cur_frm.doc.name, t_warehouse:"Restricted"})
+
+ if(restricted_in_source.length || restricted_in_target.length) {
+ msgprint("Only Material Manager can make entry in Restricted Warehouse");
+ validated = false;
+ }
+ }
+ }
\ No newline at end of file
diff --git a/docs/dev/custom_script_examples/docs.dev.custom_script.validate3.md b/docs/dev/custom_script_examples/docs.dev.custom_script.validate3.md
new file mode 100644
index 0000000..629f1c1
--- /dev/null
+++ b/docs/dev/custom_script_examples/docs.dev.custom_script.validate3.md
@@ -0,0 +1,17 @@
+---
+{
+ "_label": "Restrict Cancel Rights based on Certain Order Value"
+}
+---
+Add a handler to `custom_before_cancel` event:
+
+ cur_frm.cscript.custom_before_cancel = function(doc) {
+ if (user_roles.indexOf("Accounts User")!=-1 && user_roles.indexOf("Accounts Manager")==-1
+ && user_roles.indexOf("System Manager")==-1) {
+ if (flt(doc.grand_total) > 10000) {
+ msgprint("You can not cancel this transaction, because grand total \
+ is greater than 10000");
+ validated = false;
+ }
+ }
+ }
diff --git a/docs/dev/docs.dev.client_script.md b/docs/dev/docs.dev.client_script.md
deleted file mode 100644
index fc82f9d..0000000
--- a/docs/dev/docs.dev.client_script.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-{
- "_label": "Client Scripts: Custoimzing ERPNext"
-
-}
----
-
-
-
-
diff --git a/docs/dev/docs.dev.custom_script.md b/docs/dev/docs.dev.custom_script.md
new file mode 100644
index 0000000..ad50637
--- /dev/null
+++ b/docs/dev/docs.dev.custom_script.md
@@ -0,0 +1,31 @@
+---
+{
+ "_label": "Custom Script Examples",
+ "_toc": [
+ "docs.dev.custom_script.fetch",
+ "docs.dev.custom_script.validate",
+ "docs.dev.custom_script.validate1",
+ "docs.dev.custom_script.validate2",
+ "docs.dev.custom_script.validate3",
+ "docs.dev.custom_script.read_only",
+ "docs.dev.custom_script.calculate",
+ "docs.dev.custom_script.item_code"
+ ]
+}
+---
+### How to Create a Custom Script
+
+Create a Custom Script (you must have System Manager role for this):
+
+1. Got to: Setup > Custom Script > New Custom Script
+1. Select the DocType in which you want to add the Custom Script
+
+---
+### Notes
+
+1. Server Custom Scripts are only available for the Administrator.
+1. Client Custom Scripts are in Javascript and Server Custom Scripts are in Python.
+1. For testing, make sure to go to Tools > Clear Cache and refresh after updating a Custom Script.
+
+
+
diff --git a/docs/dev/docs.dev.md b/docs/dev/docs.dev.md
index 285f176..15afea8 100644
--- a/docs/dev/docs.dev.md
+++ b/docs/dev/docs.dev.md
@@ -6,7 +6,7 @@
"docs.dev.quickstart",
"docs.dev.framework",
"docs.dev.modules",
- "docs.dev.client_script",
+ "docs.dev.custom_script",
"docs.dev.api",
"docs.dev.translate",
"docs.dev.docs"
diff --git a/hr/doctype/employee/employee.js b/hr/doctype/employee/employee.js
index 9ee7c61..05aec3e 100644
--- a/hr/doctype/employee/employee.js
+++ b/hr/doctype/employee/employee.js
@@ -6,7 +6,7 @@
setup: function() {
this.setup_leave_approver_select();
this.frm.fields_dict.user_id.get_query = function(doc,cdt,cdn) {
- return { query:"controllers.queries.profile_query"} }
+ return { query:"core.doctype.profile.profile.profile_query"} }
this.frm.fields_dict.reports_to.get_query = function(doc,cdt,cdn) {
return{ query:"controllers.queries.employee_query"} }
},
diff --git a/public/js/queries.js b/public/js/queries.js
index fbd2947..d0346e0 100644
--- a/public/js/queries.js
+++ b/public/js/queries.js
@@ -5,7 +5,7 @@
wn.provide("erpnext.queries");
$.extend(erpnext.queries, {
profile: function() {
- return { query: "controllers.queries.profile_query" };
+ return { query: "core.doctype.profile.profile.profile_query" };
},
lead: function() {
diff --git a/selling/doctype/customer/customer.py b/selling/doctype/customer/customer.py
index cb19d4f..fb3c006 100644
--- a/selling/doctype/customer/customer.py
+++ b/selling/doctype/customer/customer.py
@@ -40,8 +40,7 @@
def validate_values(self):
if webnotes.defaults.get_global_default('cust_master_name') == 'Naming Series' and not self.doc.naming_series:
- msgprint("Series is Mandatory.")
- raise Exception
+ webnotes.throw("Series is Mandatory.", webnotes.MandatoryError)
def validate(self):
self.validate_values()
diff --git a/selling/doctype/lead/lead.js b/selling/doctype/lead/lead.js
index 9a86b22..a3ae783 100644
--- a/selling/doctype/lead/lead.js
+++ b/selling/doctype/lead/lead.js
@@ -14,12 +14,12 @@
onload: function() {
if(cur_frm.fields_dict.lead_owner.df.options.match(/^Profile/)) {
cur_frm.fields_dict.lead_owner.get_query = function(doc,cdt,cdn) {
- return { query:"controllers.queries.profile_query" } }
+ return { query:"core.doctype.profile.profile.profile_query" } }
}
if(cur_frm.fields_dict.contact_by.df.options.match(/^Profile/)) {
cur_frm.fields_dict.contact_by.get_query = function(doc,cdt,cdn) {
- return { query:"controllers.queries.profile_query" } }
+ return { query:"core.doctype.profile.profile.profile_query" } }
}
if(in_list(user_roles,'System Manager')) {
diff --git a/selling/doctype/quotation/quotation.py b/selling/doctype/quotation/quotation.py
index c1b529c..588d8d6 100644
--- a/selling/doctype/quotation/quotation.py
+++ b/selling/doctype/quotation/quotation.py
@@ -7,7 +7,7 @@
from webnotes.utils import cstr, getdate
from webnotes.model.bean import getlist
from webnotes.model.code import get_obj
-from webnotes import msgprint
+from webnotes import _, msgprint
sql = webnotes.conn.sql
@@ -278,3 +278,7 @@
return customer
else:
raise e
+ except webnotes.MandatoryError:
+ from webnotes.utils import get_url_to_form
+ webnotes.throw(_("Before proceeding, please create Customer from Lead") + \
+ (" - %s" % get_url_to_form("Lead", lead_name)))
diff --git a/selling/utils.py b/selling/utils.py
index 53ebbee..ca99512 100644
--- a/selling/utils.py
+++ b/selling/utils.py
@@ -161,7 +161,7 @@
FROM `tabItem Group` AS node, `tabItem Group` AS parent
WHERE parent.lft <= node.lft and parent.rgt >= node.rgt and node.name = %s
GROUP BY parent.name
- ORDER BY parent.lft desc""", item_group)]
+ ORDER BY parent.lft desc""", (item_group,))]
discount = 0
for d in parent_item_groups:
diff --git a/setup/doctype/authorization_rule/authorization_rule.js b/setup/doctype/authorization_rule/authorization_rule.js
index 02747a0..00f5260 100644
--- a/setup/doctype/authorization_rule/authorization_rule.js
+++ b/setup/doctype/authorization_rule/authorization_rule.js
@@ -69,10 +69,10 @@
cur_frm.fields_dict.system_user.get_query = function(doc,cdt,cdn) {
- return{ query:"controllers.queries.profile_query" } }
+ return{ query:"core.doctype.profile.profile.profile_query" } }
cur_frm.fields_dict.approving_user.get_query = function(doc,cdt,cdn) {
- return{ query:"controllers.queries.profile_query" } }
+ return{ query:"core.doctype.profile.profile.profile_query" } }
cur_frm.fields_dict['approving_role'].get_query = cur_frm.fields_dict['system_role'].get_query;
diff --git a/startup/boot.py b/startup/boot.py
index 79f0a7b..ce446e9 100644
--- a/startup/boot.py
+++ b/startup/boot.py
@@ -16,7 +16,9 @@
if webnotes.session['user']!='Guest':
bootinfo['letter_heads'] = get_letter_heads()
-
+
+ load_country_and_currency(bootinfo)
+
import webnotes.model.doctype
bootinfo['notification_settings'] = webnotes.doc("Notification Control",
"Notification Control").get_values()
@@ -36,7 +38,15 @@
bootinfo['docs'] += webnotes.conn.sql("""select name, default_currency, cost_center
from `tabCompany`""", as_dict=1, update={"doctype":":Company"})
-
+
+def load_country_and_currency(bootinfo):
+ if bootinfo.control_panel.country and \
+ webnotes.conn.exists("Country", bootinfo.control_panel.country):
+ bootinfo["docs"] += [webnotes.doc("Country", bootinfo.control_panel.country)]
+
+ bootinfo["docs"] += webnotes.conn.sql("""select * from tabCurrency
+ where ifnull(enabled,0)=1""", as_dict=1, update={"doctype":":Currency"})
+
def get_letter_heads():
"""load letter heads with startup"""
import webnotes
diff --git a/startup/event_handlers.py b/startup/event_handlers.py
index e807797..fa08962 100644
--- a/startup/event_handlers.py
+++ b/startup/event_handlers.py
@@ -64,6 +64,12 @@
webnotes.response['message'] = 'Account Expired'
raise webnotes.AuthenticationError
+def on_build():
+ from website.helpers.make_web_include_files import make
+ make()
+
+ from home.page.latest_updates import latest_updates
+ latest_updates.make()
def comment_added(doc):
"""add comment to feed"""