[merge master
]
diff --git a/accounts/doctype/journal_voucher_detail/journal_voucher_detail.txt b/accounts/doctype/journal_voucher_detail/journal_voucher_detail.txt
index ac30346..68019cb 100644
--- a/accounts/doctype/journal_voucher_detail/journal_voucher_detail.txt
+++ b/accounts/doctype/journal_voucher_detail/journal_voucher_detail.txt
@@ -2,7 +2,7 @@
{
"creation": "2013-02-22 01:27:39",
"docstatus": 0,
- "modified": "2013-03-07 07:03:23",
+ "modified": "2013-04-17 14:05:18",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -58,6 +58,7 @@
"options": "Company:company:default_currency"
},
{
+ "default": ":Company",
"doctype": "DocField",
"fieldname": "cost_center",
"fieldtype": "Link",
diff --git a/accounts/doctype/purchase_invoice_item/purchase_invoice_item.txt b/accounts/doctype/purchase_invoice_item/purchase_invoice_item.txt
index 5e9daf7..e33ab7c 100755
--- a/accounts/doctype/purchase_invoice_item/purchase_invoice_item.txt
+++ b/accounts/doctype/purchase_invoice_item/purchase_invoice_item.txt
@@ -1,8 +1,8 @@
[
{
- "creation": "2013-03-07 11:42:55",
+ "creation": "2013-04-10 08:35:38",
"docstatus": 0,
- "modified": "2013-03-29 13:44:37",
+ "modified": "2013-04-17 14:05:20",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -170,6 +170,7 @@
"width": "120px"
},
{
+ "default": ":Company",
"doctype": "DocField",
"fieldname": "cost_center",
"fieldtype": "Link",
diff --git a/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.txt b/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.txt
index b593b81..5767307 100644
--- a/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.txt
+++ b/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.txt
@@ -1,8 +1,8 @@
[
{
- "creation": "2013-03-08 15:36:47",
+ "creation": "2013-03-26 06:51:12",
"docstatus": 0,
- "modified": "2013-03-22 16:45:28",
+ "modified": "2013-04-17 14:05:19",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -58,6 +58,7 @@
"reqd": 1
},
{
+ "default": ":Company",
"doctype": "DocField",
"fieldname": "cost_center",
"fieldtype": "Link",
diff --git a/accounts/doctype/sales_invoice_item/sales_invoice_item.txt b/accounts/doctype/sales_invoice_item/sales_invoice_item.txt
index 98962b5..2a6384d 100644
--- a/accounts/doctype/sales_invoice_item/sales_invoice_item.txt
+++ b/accounts/doctype/sales_invoice_item/sales_invoice_item.txt
@@ -1,8 +1,8 @@
[
{
- "creation": "2013-03-29 18:21:58",
+ "creation": "2013-04-10 08:35:44",
"docstatus": 0,
- "modified": "2013-03-29 19:32:32",
+ "modified": "2013-04-17 14:05:20",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -219,6 +219,7 @@
"width": "120px"
},
{
+ "default": ":Company",
"doctype": "DocField",
"fieldname": "cost_center",
"fieldtype": "Link",
diff --git a/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.txt b/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.txt
index 3b32524..161eb00 100644
--- a/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.txt
+++ b/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.txt
@@ -2,7 +2,7 @@
{
"creation": "2013-02-22 01:27:41",
"docstatus": 0,
- "modified": "2013-03-07 07:03:31",
+ "modified": "2013-04-17 14:05:18",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -48,6 +48,7 @@
"search_index": 1
},
{
+ "default": ":Company",
"doctype": "DocField",
"fieldname": "cost_center_other_charges",
"fieldtype": "Link",
diff --git a/accounts/page/general_ledger/general_ledger.js b/accounts/page/general_ledger/general_ledger.js
index 4a39d74..21be3a0 100644
--- a/accounts/page/general_ledger/general_ledger.js
+++ b/accounts/page/general_ledger/general_ledger.js
@@ -307,10 +307,10 @@
make_account_by_name: function() {
this.account_by_name = this.make_name_map(wn.report_dump.data["Account"]);
- this.make_voucher_acconuts_map();
+ this.make_voucher_accounts_map();
},
- make_voucher_acconuts_map: function() {
+ make_voucher_accounts_map: function() {
this.voucher_accounts = {};
var data = wn.report_dump.data["GL Entry"];
for(var i=0, j=data.length; i<j; i++) {
diff --git a/home/page/latest_updates/latest_updates.js b/home/page/latest_updates/latest_updates.js
index 6f8a05b..80571c1 100644
--- a/home/page/latest_updates/latest_updates.js
+++ b/home/page/latest_updates/latest_updates.js
@@ -1,4 +1,5 @@
erpnext.updates = [
+ ["12th April", ["Employee: List of Leave Approvers who can approve the Employee's Leave Applications"]],
["10th April", ["Redesigned File Uploads and added File Manager in Setup"]],
["27th March", ["Rename multiple items together. Go to Setup > Rename Tool"]],
["26th March", ["Added project to Stock Ledger and Balance",
diff --git a/hr/doctype/employee/employee.js b/hr/doctype/employee/employee.js
index 239b3b7..5a2dbab 100644
--- a/hr/doctype/employee/employee.js
+++ b/hr/doctype/employee/employee.js
@@ -14,62 +14,95 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
-cur_frm.cscript.onload = function(doc) {
- // bc
- var india_specific = ["esic_card_no", "gratuity_lic_id", "pan_number", "pf_number"]
- if(wn.control_panel.country!="India") {
- hide_field(india_specific);
- }
-}
-
-cur_frm.cscript.refresh = function(doc) {
- if(!doc.__islocal) {
- hide_field("naming_series");
- cur_frm.add_custom_button('Make Salary Structure',
- cur_frm.cscript['Make Salary Structure']);
- }
-}
-
-cur_frm.cscript.date_of_birth = function(doc, dt, dn) {
- get_server_fields('get_retirement_date','','',doc,dt,dn,1);
-}
-
-cur_frm.cscript.salutation = function(doc,dt,dn) {
- if(doc.salutation){
- if(doc.salutation=='Mr')
- doc.gender='Male';
- else if(doc.salutation=='Ms')
- doc.gender='Female';
- refresh_field('gender');
- }
-}
-
-cur_frm.cscript['Make Salary Structure']=function(){
- $c_obj(make_doclist (cur_frm.doc.doctype, cur_frm.doc.name), 'check_sal_structure',
- cur_frm.doc.name, function(r, rt) {
- if(r.message)
- msgprint("You have already created Active salary structure.\n \
- If you want to create new one, please ensure that no active salary structure \
- exist.\nTo inactive salary structure select 'Is Active' as 'No'.");
- else
- cur_frm.cscript.make_salary_structure(cur_frm.doc);
+wn.provide("erpnext.hr");
+erpnext.hr.EmployeeController = wn.ui.form.Controller.extend({
+ setup: function() {
+ this.setup_leave_approver_select();
+ this.frm.fields_dict.user_id.get_query = erpnext.utils.profile_query;
+ this.frm.fields_dict.reports_to.get_query = erpnext.utils.employee_query;
+ },
+
+ onload: function() {
+ this.frm.toggle_display(["esic_card_no", "gratuity_lic_id", "pan_number", "pf_number"],
+ wn.control_panel.country==="India");
+ },
+
+ refresh: function() {
+ var me = this;
+ erpnext.hide_naming_series();
+ if(!this.frm.doc.__islocal) {
+ cur_frm.add_custom_button('View Active Salary Structure', function() {
+ me.view_active_salary_structure(this); });
+
+ cur_frm.add_custom_button('Make Salary Structure', function() {
+ me.make_salary_structure(this); });
+
}
- );
-}
-
-cur_frm.cscript.make_salary_structure = function(doc, dt, dn, det){
- var st = wn.model.make_new_doc_and_get_name('Salary Structure');
- st = locals['Salary Structure'][st];
- st.employee = doc.name;
- st.employee_name = doc.employee_name;
- st.branch=doc.branch;
- st.designation=doc.designation;
- st.department=doc.department;
- st.fiscal_year = doc.fiscal_year
- st.grade=doc.grade;
- loaddoc('Salary Structure', st.name);
-}
-
-cur_frm.fields_dict.user_id.get_query = erpnext.utils.profile_query;
-
-cur_frm.fields_dict.reports_to.get_query = erpnext.utils.employee_query;
\ No newline at end of file
+ },
+
+ setup_leave_approver_select: function() {
+ var me = this;
+ this.frm.call({
+ method:"hr.utils.get_leave_approver_list",
+ callback: function(r) {
+ me.frm.fields_dict.employee_leave_approvers.grid.get_field("leave_approver").df.options =
+ $.map(r.message, function(profile) {
+ return {value: profile, label: wn.user_info(profile).fullname};
+ });
+ }
+ });
+ },
+
+ date_of_birth: function() {
+ cur_frm.call({
+ method: "get_retirement_date",
+ args: {date_of_birth: this.frm.doc.date_of_birth}
+ });
+ },
+
+ salutation: function() {
+ if(this.frm.doc.salutation) {
+ this.frm.set_value("gender", {
+ "Mr": "Male",
+ "Ms": "Female"
+ }[this.frm.doc.salutation]);
+ }
+ },
+
+ make_salary_structure: function(btn) {
+ var me = this;
+ this.validate_salary_structure(btn, function(r) {
+ if(r.message) {
+ msgprint(wn._("Employee") + ' "' + me.frm.doc.name + '": '
+ + wn._("An active Salary Structure already exists. \
+ If you want to create new one, please ensure that no active Salary Structure \
+ exists for this Employee. Go to the active Salary Structure and set \
+ \"Is Active\" = \"No\""));
+ } else if(!r.exc) {
+ wn.model.map({
+ source: wn.model.get_doclist(me.frm.doc.doctype, me.frm.doc.name),
+ target: "Salary Structure"
+ });
+ }
+ });
+ },
+
+ validate_salary_structure: function(btn, callback) {
+ var me = this;
+ this.frm.call({
+ btn: btn,
+ method: "webnotes.client.get_value",
+ args: {
+ doctype: "Salary Structure",
+ fieldname: "name",
+ filters: {
+ employee: me.frm.doc.name,
+ is_active: "Yes",
+ docstatus: ["!=", 2]
+ },
+ },
+ callback: callback
+ });
+ },
+});
+cur_frm.cscript = new erpnext.hr.EmployeeController({frm: cur_frm});
\ No newline at end of file
diff --git a/hr/doctype/employee/employee.py b/hr/doctype/employee/employee.py
index 4100e2e..bef3274 100644
--- a/hr/doctype/employee/employee.py
+++ b/hr/doctype/employee/employee.py
@@ -27,7 +27,7 @@
def __init__(self,doc,doclist=[]):
self.doc = doc
self.doclist = doclist
-
+
def autoname(self):
ret = sql("select value from `tabSingles` where doctype = 'Global Defaults' and field = 'emp_created_by'")
if not ret:
@@ -49,30 +49,31 @@
self.validate_email()
self.validate_name()
self.validate_status()
-
- def get_retirement_date(self):
- import datetime
- ret = {}
- if self.doc.date_of_birth:
- dt = getdate(self.doc.date_of_birth) + datetime.timedelta(21915)
- ret = {'date_of_retirement': dt.strftime('%Y-%m-%d')}
- return ret
-
- def check_sal_structure(self, nm):
- ret_sal_struct=sql("select name from `tabSalary Structure` where employee='%s' and is_active = 'Yes' and docstatus!= 2"%nm)
- return ret_sal_struct and ret_sal_struct[0][0] or ''
-
+ self.validate_employee_leave_approver()
+
def on_update(self):
if self.doc.user_id:
self.update_user_default()
self.update_profile()
-
+
def update_user_default(self):
webnotes.conn.set_default("employee", self.doc.name, self.doc.user_id)
webnotes.conn.set_default("employee_name", self.doc.employee_name, self.doc.user_id)
webnotes.conn.set_default("company", self.doc.company, self.doc.user_id)
- if self.doc.reports_to:
- webnotes.conn.set_default("leave_approver", webnotes.conn.get_value("Employee", self.doc.reports_to, "user_id"), self.doc.user_id)
+ self.set_default_leave_approver()
+
+ def set_default_leave_approver(self):
+ employee_leave_approvers = self.doclist.get({"parentfield": "employee_leave_approvers"})
+
+ if len(employee_leave_approvers):
+ webnotes.conn.set_default("leave_approver", employee_leave_approvers[0].leave_approver,
+ self.doc.user_id)
+
+ elif self.doc.reports_to:
+ from webnotes.profile import Profile
+ reports_to_user = webnotes.conn.get_value("Employee", self.doc.reports_to, "user_id")
+ if "Leave Approver" in Profile(reports_to_user).get_roles():
+ webnotes.conn.set_default("leave_approver", reports_to_user, self.doc.user_id)
def update_profile(self):
# add employee role if missing
@@ -118,7 +119,6 @@
profile_wrapper.save()
def validate_date(self):
- import datetime
if self.doc.date_of_birth and self.doc.date_of_joining and getdate(self.doc.date_of_birth) >= getdate(self.doc.date_of_joining):
msgprint('Date of Joining must be greater than Date of Birth')
raise Exception
@@ -169,3 +169,21 @@
if self.doc.status == 'Left' and not self.doc.relieving_date:
msgprint("Please enter relieving date.")
raise Exception
+
+ def validate_employee_leave_approver(self):
+ from webnotes.profile import Profile
+ from hr.doctype.leave_application.leave_application import InvalidLeaveApproverError
+
+ for l in self.doclist.get({"parentfield": "employee_leave_approvers"}):
+ if "Leave Approver" not in Profile(l.leave_approver).get_roles():
+ msgprint(_("Invalid Leave Approver") + ": \"" + l.leave_approver + "\"",
+ raise_exception=InvalidLeaveApproverError)
+
+@webnotes.whitelist()
+def get_retirement_date(date_of_birth=None):
+ import datetime
+ ret = {}
+ if date_of_birth:
+ dt = getdate(date_of_birth) + datetime.timedelta(21915)
+ ret = {'date_of_retirement': dt.strftime('%Y-%m-%d')}
+ return ret
diff --git a/hr/doctype/employee/employee.txt b/hr/doctype/employee/employee.txt
index 1744f62..705eaa7 100644
--- a/hr/doctype/employee/employee.txt
+++ b/hr/doctype/employee/employee.txt
@@ -1,8 +1,8 @@
[
{
- "creation": "2013-03-07 14:48:31",
+ "creation": "2013-03-07 09:04:18",
"docstatus": 0,
- "modified": "2013-02-08 13:07:25",
+ "modified": "2013-04-12 07:16:42",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -321,15 +321,6 @@
"reqd": 0
},
{
- "doctype": "DocField",
- "fieldname": "reports_to",
- "fieldtype": "Link",
- "label": "Reports to",
- "oldfieldname": "reports_to",
- "oldfieldtype": "Link",
- "options": "Employee"
- },
- {
"description": "Provide email id registered in company",
"doctype": "DocField",
"fieldname": "company_email",
@@ -342,6 +333,14 @@
},
{
"doctype": "DocField",
+ "fieldname": "notice_number_of_days",
+ "fieldtype": "Int",
+ "label": "Notice - Number of Days",
+ "oldfieldname": "notice_number_of_days",
+ "oldfieldtype": "Int"
+ },
+ {
+ "doctype": "DocField",
"fieldname": "salary_information",
"fieldtype": "Column Break",
"label": "Salary Information",
@@ -405,6 +404,29 @@
},
{
"doctype": "DocField",
+ "fieldname": "organization_profile",
+ "fieldtype": "Section Break",
+ "label": "Organization Profile"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "reports_to",
+ "fieldtype": "Link",
+ "label": "Reports to",
+ "oldfieldname": "reports_to",
+ "oldfieldtype": "Link",
+ "options": "Employee"
+ },
+ {
+ "description": "The first Leave Approver in the list will be set as the default Leave Approver",
+ "doctype": "DocField",
+ "fieldname": "employee_leave_approvers",
+ "fieldtype": "Table",
+ "label": "Leave Approvers",
+ "options": "Employee Leave Approver"
+ },
+ {
+ "doctype": "DocField",
"fieldname": "contact_details",
"fieldtype": "Section Break",
"label": "Contact Details"
@@ -429,14 +451,6 @@
},
{
"doctype": "DocField",
- "fieldname": "notice_number_of_days",
- "fieldtype": "Int",
- "label": "Notice - Number of Days",
- "oldfieldname": "notice_number_of_days",
- "oldfieldtype": "Int"
- },
- {
- "doctype": "DocField",
"fieldname": "emergency_contact_details",
"fieldtype": "HTML",
"label": "Emergency Contact Details",
diff --git a/hr/doctype/employee_leave_approver/__init__.py b/hr/doctype/employee_leave_approver/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/hr/doctype/employee_leave_approver/__init__.py
diff --git a/hr/doctype/employee_leave_approver/employee_leave_approver.py b/hr/doctype/employee_leave_approver/employee_leave_approver.py
new file mode 100644
index 0000000..928aa9f
--- /dev/null
+++ b/hr/doctype/employee_leave_approver/employee_leave_approver.py
@@ -0,0 +1,8 @@
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import webnotes
+
+class DocType:
+ def __init__(self, d, dl):
+ self.doc, self.doclist = d, dl
\ No newline at end of file
diff --git a/hr/doctype/employee_leave_approver/employee_leave_approver.txt b/hr/doctype/employee_leave_approver/employee_leave_approver.txt
new file mode 100644
index 0000000..31e3e09
--- /dev/null
+++ b/hr/doctype/employee_leave_approver/employee_leave_approver.txt
@@ -0,0 +1,39 @@
+[
+ {
+ "creation": "2013-04-12 06:56:15",
+ "docstatus": 0,
+ "modified": "2013-04-12 07:53:33",
+ "modified_by": "Administrator",
+ "owner": "Administrator"
+ },
+ {
+ "allow_import": 0,
+ "autoname": "LAPPR-/.#####",
+ "description": "Users who can approve a specific employee's leave applications",
+ "doctype": "DocType",
+ "istable": 1,
+ "module": "HR",
+ "name": "__common__"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "leave_approver",
+ "fieldtype": "Select",
+ "label": "Leave Approver",
+ "name": "__common__",
+ "parent": "Employee Leave Approver",
+ "parentfield": "fields",
+ "parenttype": "DocType",
+ "permlevel": 0,
+ "print_hide": 1,
+ "reqd": 1,
+ "width": "200"
+ },
+ {
+ "doctype": "DocType",
+ "name": "Employee Leave Approver"
+ },
+ {
+ "doctype": "DocField"
+ }
+]
\ No newline at end of file
diff --git a/hr/doctype/expense_claim/expense_claim.js b/hr/doctype/expense_claim/expense_claim.js
index 72fe15c..5b136d0 100644
--- a/hr/doctype/expense_claim/expense_claim.js
+++ b/hr/doctype/expense_claim/expense_claim.js
@@ -29,7 +29,7 @@
}
cur_frm.call({
- method:"get_approver_list",
+ method:"hr.utils.get_expense_approver_list",
callback: function(r) {
cur_frm.set_df_property("exp_approver", "options", r.message);
}
diff --git a/hr/doctype/expense_claim/expense_claim.py b/hr/doctype/expense_claim/expense_claim.py
index 0aa9ed8..0564d1d 100644
--- a/hr/doctype/expense_claim/expense_claim.py
+++ b/hr/doctype/expense_claim/expense_claim.py
@@ -52,12 +52,3 @@
if not getlist(self.doclist, 'expense_voucher_details'):
msgprint("Please add expense voucher details")
raise Exception
-
-@webnotes.whitelist()
-def get_approver_list():
- roles = [r[0] for r in webnotes.conn.sql("""select distinct parent from `tabUserRole`
- where role='Expense Approver'""")]
- if not roles:
- webnotes.msgprint("No Expense Approvers. Please assign 'Expense Approver' \
- Role to atleast one user.")
- return roles
diff --git a/hr/doctype/leave_application/leave_application.js b/hr/doctype/leave_application/leave_application.js
index 0252818..7f8948a 100755
--- a/hr/doctype/leave_application/leave_application.js
+++ b/hr/doctype/leave_application/leave_application.js
@@ -26,7 +26,7 @@
}
cur_frm.set_df_property("leave_approver", "options", "");
cur_frm.call({
- method:"get_approver_list",
+ method:"hr.utils.get_leave_approver_list",
callback: function(r) {
cur_frm.set_df_property("leave_approver", "options", $.map(r.message,
function(profile) {
diff --git a/hr/doctype/leave_application/leave_application.py b/hr/doctype/leave_application/leave_application.py
index d34abd8..b9f9e5b 100755
--- a/hr/doctype/leave_application/leave_application.py
+++ b/hr/doctype/leave_application/leave_application.py
@@ -18,11 +18,13 @@
import webnotes
from webnotes import _
-from webnotes.utils import cint, cstr, date_diff, flt, formatdate, getdate, get_url_to_form
+from webnotes.utils import cint, cstr, date_diff, flt, formatdate, getdate, get_url_to_form, \
+ comma_or, get_fullname
from webnotes import msgprint
-class LeaveDayBlockedError(Exception): pass
-class OverlapError(Exception): pass
+class LeaveDayBlockedError(webnotes.ValidationError): pass
+class OverlapError(webnotes.ValidationError): pass
+class InvalidLeaveApproverError(webnotes.ValidationError): pass
from webnotes.model.controller import DocListController
class DocType(DocListController):
@@ -39,6 +41,7 @@
self.validate_max_days()
self.show_block_day_warning()
self.validate_block_days()
+ self.validate_leave_approver()
def on_update(self):
if (not self.previous_doc and self.doc.leave_approver) or (self.previous_doc and \
@@ -156,6 +159,21 @@
msgprint("Sorry ! You cannot apply for %s for more than %s days" % (self.doc.leave_type, max_days))
raise Exception
+ def validate_leave_approver(self):
+ employee = webnotes.bean("Employee", self.doc.employee)
+ leave_approvers = [l.leave_approver for l in
+ employee.doclist.get({"parentfield": "employee_leave_approvers"})]
+
+ if len(leave_approvers) and self.doc.leave_approver not in leave_approvers:
+ msgprint(("[" + _("For Employee") + ' "' + self.doc.employee + '"] '
+ + _("Leave Approver can be one of") + ": "
+ + comma_or(leave_approvers)), raise_exception=InvalidLeaveApproverError)
+
+ elif self.doc.leave_approver and not webnotes.conn.sql("""select name from `tabUserRole`
+ where parent=%s and role='Leave Approver'""", self.doc.leave_approver):
+ msgprint(get_fullname(self.doc.leave_approver) + ": " \
+ + _("does not have role 'Leave Approver'"), raise_exception=InvalidLeaveApproverError)
+
def notify_employee(self, status):
employee = webnotes.doc("Employee", self.doc.employee)
if not employee.user_id:
@@ -221,15 +239,6 @@
ret = {'leave_balance': leave_all - leave_app}
return ret
-@webnotes.whitelist()
-def get_approver_list():
- roles = [r[0] for r in webnotes.conn.sql("""select distinct parent from `tabUserRole`
- where role='Leave Approver'""")]
- if not roles:
- webnotes.msgprint("No Leave Approvers. Please assign 'Leave Approver' Role to atleast one user.")
-
- return roles
-
def is_lwp(leave_type):
lwp = webnotes.conn.sql("select is_lwp from `tabLeave Type` where name = %s", leave_type)
return lwp and cint(lwp[0][0]) or 0
diff --git a/hr/doctype/leave_application/test_leave_application.py b/hr/doctype/leave_application/test_leave_application.py
index 672e668..338225c 100644
--- a/hr/doctype/leave_application/test_leave_application.py
+++ b/hr/doctype/leave_application/test_leave_application.py
@@ -4,6 +4,23 @@
from hr.doctype.leave_application.leave_application import LeaveDayBlockedError, OverlapError
class TestLeaveApplication(unittest.TestCase):
+ def _clear_roles(self):
+ webnotes.conn.sql("""delete from `tabUserRole` where parent in
+ ("test@example.com", "test1@example.com", "test2@example.com")""")
+
+ def _clear_applications(self):
+ webnotes.conn.sql("""delete from `tabLeave Application`""")
+
+ def _add_employee_leave_approver(self, employee, leave_approver):
+ webnotes.session.user = "Administrator"
+ employee = webnotes.bean("Employee", employee)
+ employee.doclist.append({
+ "doctype": "Employee Leave Approver",
+ "parentfield": "employee_leave_approvers",
+ "leave_approver": leave_approver
+ })
+ employee.save()
+
def get_application(self, doclist):
application = webnotes.bean(copy=doclist)
application.doc.from_date = "2013-01-01"
@@ -11,8 +28,14 @@
return application
def test_block_list(self):
- import webnotes
- webnotes.conn.set_value("Department", "_Test Department", "leave_block_list", "_Test Leave Block List")
+ webnotes.session.user = "Administrator"
+ self._clear_roles()
+
+ from webnotes.profile import add_role
+ add_role("test1@example.com", "HR User")
+
+ webnotes.conn.set_value("Department", "_Test Department",
+ "leave_block_list", "_Test Leave Block List")
application = self.get_application(test_records[1])
application.insert()
@@ -20,9 +43,6 @@
self.assertRaises(LeaveDayBlockedError, application.submit)
webnotes.session.user = "test1@example.com"
-
- from webnotes.profile import add_role
- add_role("test1@example.com", "HR User")
# clear other applications
webnotes.conn.sql("delete from `tabLeave Application`")
@@ -31,11 +51,31 @@
self.assertTrue(application.insert())
def test_overlap(self):
+ webnotes.session.user = "Administrator"
+ self._clear_roles()
+ self._clear_applications()
+
+ from webnotes.profile import add_role
+ add_role("test@example.com", "Employee")
+ add_role("test2@example.com", "Leave Approver")
+
+ webnotes.session.user = "test@example.com"
application = self.get_application(test_records[1])
+ application.doc.leave_approver = "test2@example.com"
+ application.insert()
+
+ application = self.get_application(test_records[1])
+ application.doc.leave_approver = "test2@example.com"
self.assertRaises(OverlapError, application.insert)
def test_global_block_list(self):
-
+ webnotes.session.user = "Administrator"
+ self._clear_roles()
+
+ from webnotes.profile import add_role
+ add_role("test1@example.com", "Employee")
+ add_role("test@example.com", "Leave Approver")
+
application = self.get_application(test_records[3])
application.doc.leave_approver = "test@example.com"
@@ -44,19 +84,120 @@
webnotes.conn.set_value("Employee", "_T-Employee-0002", "department",
"_Test Department")
- webnotes.session.user = "test2@example.com"
- from webnotes.profile import add_role
- add_role("test2@example.com", "Employee")
-
+ webnotes.session.user = "test1@example.com"
application.insert()
webnotes.session.user = "test@example.com"
- from webnotes.profile import add_role
- add_role("test@example.com", "Leave Approver")
-
application.doc.status = "Approved"
self.assertRaises(LeaveDayBlockedError, application.submit)
+ webnotes.conn.set_value("Leave Block List", "_Test Leave Block List",
+ "applies_to_all_departments", 0)
+
+ def test_leave_approval(self):
+ webnotes.session.user = "Administrator"
+ self._clear_roles()
+
+ from webnotes.profile import add_role
+ add_role("test@example.com", "Employee")
+ add_role("test1@example.com", "Leave Approver")
+ add_role("test2@example.com", "Leave Approver")
+
+ self._test_leave_approval_basic_case_1()
+ self._test_leave_approval_basic_case_2()
+ self._test_leave_approval_invalid_leave_approver_insert()
+ self._test_leave_approval_invalid_leave_approver_submit()
+ self._test_leave_approval_valid_leave_approver_insert()
+
+ def _test_leave_approval_basic_case_1(self):
+ self._clear_applications()
+
+ # create leave application as Employee
+ webnotes.session.user = "test@example.com"
+ application = self.get_application(test_records[1])
+ application.doc.leave_approver = "test1@example.com"
+ application.insert()
+
+ # submit leave application by Leave Approver
+ webnotes.session.user = "test1@example.com"
+ application.doc.status = "Approved"
+ application.submit()
+ self.assertEqual(webnotes.conn.get_value("Leave Application", application.doc.name,
+ "docstatus"), 1)
+
+ def _test_leave_approval_basic_case_2(self):
+ self._clear_applications()
+
+ # create leave application by any leave approver,
+ # when no leave approver specified in employee's leave approvers list
+ application = self.get_application(test_records[1])
+ application.doc.leave_approver = "test1@example.com"
+ application.insert()
+ application.doc.status = "Approved"
+ application.submit()
+ self.assertEqual(webnotes.conn.get_value("Leave Application", application.doc.name,
+ "docstatus"), 1)
+
+ def _test_leave_approval_invalid_leave_approver_insert(self):
+ from hr.doctype.leave_application.leave_application import InvalidLeaveApproverError
+
+ self._clear_applications()
+
+ # add a different leave approver in the employee's list
+ # should raise exception if not a valid leave approver
+ self._add_employee_leave_approver("_T-Employee-0001", "test2@example.com")
+
+ # TODO - add test2@example.com leave approver in employee's leave approvers list
+ application = self.get_application(test_records[1])
+ webnotes.session.user = "test@example.com"
+
+ application.doc.leave_approver = "test1@example.com"
+ self.assertRaises(InvalidLeaveApproverError, application.insert)
+
+ webnotes.conn.sql("""delete from `tabEmployee Leave Approver` where parent=%s""",
+ "_T-Employee-0001")
+
+ def _test_leave_approval_invalid_leave_approver_submit(self):
+ self._clear_applications()
+ self._add_employee_leave_approver("_T-Employee-0001", "test2@example.com")
+
+ # create leave application as employee
+ # but submit as invalid leave approver - should raise exception
+ webnotes.session.user = "test@example.com"
+ application = self.get_application(test_records[1])
+ application.doc.leave_approver = "test2@example.com"
+ application.insert()
+ webnotes.session.user = "test1@example.com"
+ application.doc.status = "Approved"
+
+ from webnotes.model.bean import BeanPermissionError
+ self.assertRaises(BeanPermissionError, application.submit)
+
+ webnotes.conn.sql("""delete from `tabEmployee Leave Approver` where parent=%s""",
+ "_T-Employee-0001")
+
+ def _test_leave_approval_valid_leave_approver_insert(self):
+ self._clear_applications()
+ self._add_employee_leave_approver("_T-Employee-0001", "test2@example.com")
+
+ original_department = webnotes.conn.get_value("Employee", "_T-Employee-0001", "department")
+ webnotes.conn.set_value("Employee", "_T-Employee-0001", "department", None)
+
+ # change to valid leave approver and try to create and submit leave application
+ webnotes.session.user = "test2@example.com"
+ application = self.get_application(test_records[1])
+ application.doc.leave_approver = "test2@example.com"
+ application.insert()
+ application.doc.status = "Approved"
+ application.submit()
+ self.assertEqual(webnotes.conn.get_value("Leave Application", application.doc.name,
+ "docstatus"), 1)
+
+ webnotes.conn.sql("""delete from `tabEmployee Leave Approver` where parent=%s""",
+ "_T-Employee-0001")
+
+ webnotes.conn.set_value("Employee", "_T-Employee-0001", "department", original_department)
+
test_dependencies = ["Leave Block List"]
test_records = [
diff --git a/hr/utils.py b/hr/utils.py
new file mode 100644
index 0000000..0d23a16
--- /dev/null
+++ b/hr/utils.py
@@ -0,0 +1,38 @@
+# ERPNext - web based ERP (http://erpnext.com)
+# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import unicode_literals
+import webnotes
+from webnotes import _
+
+@webnotes.whitelist()
+def get_leave_approver_list():
+ roles = [r[0] for r in webnotes.conn.sql("""select distinct parent from `tabUserRole`
+ where role='Leave Approver'""")]
+ if not roles:
+ webnotes.msgprint(_("No Leave Approvers. Please assign 'Leave Approver' Role to atleast one user."))
+
+ return roles
+
+
+@webnotes.whitelist()
+def get_expense_approver_list():
+ roles = [r[0] for r in webnotes.conn.sql("""select distinct parent from `tabUserRole`
+ where role='Expense Approver'""")]
+ if not roles:
+ webnotes.msgprint("No Expense Approvers. Please assign 'Expense Approver' \
+ Role to atleast one user.")
+ return roles
diff --git a/patches/patch_list.py b/patches/patch_list.py
index 985aba8..698b062 100644
--- a/patches/patch_list.py
+++ b/patches/patch_list.py
@@ -231,7 +231,6 @@
"patches.march_2013.p12_set_item_tax_rate_in_json",
"patches.march_2013.p07_update_valuation_rate",
"patches.march_2013.p08_create_aii_accounts",
- # "patches.march_2013.p03_update_buying_amount",
"patches.april_2013.p01_update_serial_no_valuation_rate",
"patches.april_2013.p02_add_country_and_currency",
"patches.april_2013.p03_fixes_for_lead_in_quotation",
@@ -244,4 +243,5 @@
"patches.april_2013.p05_update_file_data",
"patches.april_2013.p06_update_file_size",
"patches.april_2013.p05_fixes_in_reverse_modules",
+ "execute:webnotes.delete_doc('DocType Mapper', 'Delivery Note-Packing Slip')"
]
\ No newline at end of file
diff --git a/public/js/startup.js b/public/js/startup.js
index 0a6580b..76f2c26 100644
--- a/public/js/startup.js
+++ b/public/js/startup.js
@@ -136,10 +136,7 @@
erpnext.hide_naming_series = function() {
if(cur_frm.fields_dict.naming_series) {
- hide_field('naming_series');
- if(cur_frm.doc.__islocal) {
- unhide_field('naming_series');
- }
+ cur_frm.toggle_display("naming_series", cur_frm.doc.__islocal?true:false);
}
}
diff --git a/selling/doctype/sales_common/sales_common.py b/selling/doctype/sales_common/sales_common.py
index b9f9af6..7b1528b 100644
--- a/selling/doctype/sales_common/sales_common.py
+++ b/selling/doctype/sales_common/sales_common.py
@@ -125,8 +125,7 @@
def get_item_details(self, args, obj):
import json
if not obj.doc.price_list_name:
- msgprint("Please Select Price List before selecting Items")
- raise Exception
+ msgprint("Please Select Price List before selecting Items", raise_exception=True)
item = webnotes.conn.sql("""select description, item_name, brand, item_group, stock_uom,
default_warehouse, default_income_account, default_sales_cost_center,
purchase_account, description_html, barcode from `tabItem`
diff --git a/selling/search_criteria/sales_personwise_transaction_summary/sales_personwise_transaction_summary.js b/selling/search_criteria/sales_personwise_transaction_summary/sales_personwise_transaction_summary.js
index 335df7a..79dd9d5 100755
--- a/selling/search_criteria/sales_personwise_transaction_summary/sales_personwise_transaction_summary.js
+++ b/selling/search_criteria/sales_personwise_transaction_summary/sales_personwise_transaction_summary.js
@@ -39,10 +39,7 @@
sp = this.get_filter('Sales Person', 'Sales Person').get_value();
date_fld = 'transaction_date';
- if(based_on == 'Sales Invoice') {
- based_on = 'Sales Invoice';
- date_fld = 'posting_date';
- }
+ if(based_on == 'Sales Invoice' || based_on == "Delivery Note") date_fld = 'posting_date';
sp_cond = '';
if (from_date) sp_cond += ' AND t1.' + date_fld + '>= "' + from_date + '"';
diff --git a/setup/doctype/company/company.py b/setup/doctype/company/company.py
index bee1333..78be538 100644
--- a/setup/doctype/company/company.py
+++ b/setup/doctype/company/company.py
@@ -153,7 +153,7 @@
for d in acc_list_common:
self.add_acc(d)
- country = sql("select value from tabSingles where field = 'country' and doctype = 'Control Panel'")
+ country = webnotes.conn.sql("select value from tabSingles where field = 'country' and doctype = 'Control Panel'")
country = country and cstr(country[0][0]) or ''
# load taxes (only for India)
@@ -245,6 +245,9 @@
for cc in cc_list:
add_cc(cc)
+ webnotes.conn.set_value("Company", self.doc.name, "cost_center",
+ "Default CC Ledger - " + self.doc.abbr)
+
def on_update(self):
self.set_letter_head()
@@ -265,26 +268,31 @@
"""
Trash accounts and cost centers for this company if no gl entry exists
"""
- rec = sql("SELECT name from `tabGL Entry` where ifnull(is_cancelled, 'No') = 'No' and company = %s", self.doc.name)
+ rec = webnotes.conn.sql("SELECT name from `tabGL Entry` where ifnull(is_cancelled, 'No') = 'No' and company = %s", self.doc.name)
if not rec:
# delete gl entry
- sql("delete from `tabGL Entry` where company = %s", self.doc.name)
+ webnotes.conn.sql("delete from `tabGL Entry` where company = %s", self.doc.name)
#delete tabAccount
- sql("delete from `tabAccount` where company = %s order by lft desc, rgt desc", self.doc.name)
+ webnotes.conn.sql("delete from `tabAccount` where company = %s order by lft desc, rgt desc", self.doc.name)
#delete cost center child table - budget detail
- sql("delete bd.* from `tabBudget Detail` bd, `tabCost Center` cc where bd.parent = cc.name and cc.company_name = %s", self.doc.name)
+ webnotes.conn.sql("delete bd.* from `tabBudget Detail` bd, `tabCost Center` cc where bd.parent = cc.name and cc.company_name = %s", self.doc.name)
#delete cost center
- sql("delete from `tabCost Center` WHERE company_name = %s order by lft desc, rgt desc", self.doc.name)
+ webnotes.conn.sql("delete from `tabCost Center` WHERE company_name = %s order by lft desc, rgt desc", self.doc.name)
- webnotes.defaults.clear_default("company", value=self.doc.name)
+ webnotes.defaults.clear_default("company", value=self.doc.name)
- #update value as blank for tabSingles Global Defaults
- sql("update `tabSingles` set value = '' where doctype='Global Defaults' and field = 'default_company' and value = %s", self.doc.name)
-
+ webnotes.conn.sql("""update `tabSingles` set value=""
+ where doctype='Global Defaults' and field='default_company'
+ and value=%s""", self.doc.name)
+
def on_rename(self,newdn,olddn):
- sql("update `tabCompany` set company_name = '%s' where name = '%s'" %(newdn,olddn))
- sql("update `tabSingles` set value = %s where doctype='Global Defaults' and field = 'default_company' and value = %s", (newdn, olddn))
- if webnotes.defaults.get_global_default('company') == olddn:
- webnotes.defaults.set_global_default('company', newdn)
\ No newline at end of file
+ webnotes.conn.sql("""update `tabCompany` set company_name=%s
+ where name=%s""", (newdn, olddn))
+
+ webnotes.conn.sql("""update `tabSingles` set value=%s
+ where doctype='Global Defaults' and field='default_company'
+ and value=%s""", (newdn, olddn))
+
+ webnotes.defaults.clear_default("company", value=olddn)
\ No newline at end of file
diff --git a/setup/doctype/company/company.txt b/setup/doctype/company/company.txt
index a49a7e0..c4176d8 100644
--- a/setup/doctype/company/company.txt
+++ b/setup/doctype/company/company.txt
@@ -1,8 +1,8 @@
[
{
- "creation": "2013-03-26 11:03:08",
+ "creation": "2013-04-10 08:35:39",
"docstatus": 0,
- "modified": "2013-03-28 16:04:27",
+ "modified": "2013-04-17 14:07:46",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -142,6 +142,15 @@
"read_only": 0
},
{
+ "depends_on": "eval:!doc.__islocal",
+ "doctype": "DocField",
+ "fieldname": "cost_center",
+ "fieldtype": "Link",
+ "label": "Cost Center",
+ "no_copy": 1,
+ "options": "Cost Center"
+ },
+ {
"doctype": "DocField",
"fieldname": "column_break0",
"fieldtype": "Column Break",
diff --git a/setup/doctype/email_digest/email_digest.py b/setup/doctype/email_digest/email_digest.py
index 0b0b21a..881e35a 100644
--- a/setup/doctype/email_digest/email_digest.py
+++ b/setup/doctype/email_digest/email_digest.py
@@ -94,8 +94,7 @@
msg_for_this_receipient = self.get_msg_html(self.get_user_specific_content(user_id) + \
common_msg)
from webnotes.utils.email_lib import sendmail
- sendmail(recipients=user_id, subject=(self.doc.frequency + " Digest"),
- sender="ERPNext Notifications <notifications+email_digest@erpnext.com>",
+ sendmail(recipients=user_id, subject="[ERPNext] " + (self.doc.frequency + " Digest"),
msg=msg_for_this_receipient)
def get_digest_msg(self):
diff --git a/startup/boot.py b/startup/boot.py
index 4774a90..9ed20ff 100644
--- a/startup/boot.py
+++ b/startup/boot.py
@@ -36,7 +36,8 @@
for key in ['max_users', 'expires_on', 'max_space', 'status', 'developer_mode']:
if hasattr(conf, key): bootinfo[key] = getattr(conf, key)
- bootinfo['docs'] += webnotes.conn.sql("select name, default_currency from `tabCompany`",
+ bootinfo['docs'] += webnotes.conn.sql("""select name, default_currency, cost_center,
+ cost_center as 'cost_center_other_charges' from `tabCompany`""",
as_dict=1, update={"doctype":":Company"})
def get_letter_heads():
diff --git a/stock/DocType Mapper/Delivery Note-Packing Slip/Delivery Note-Packing Slip.txt b/stock/DocType Mapper/Delivery Note-Packing Slip/Delivery Note-Packing Slip.txt
index 79b17c2..fc88bba 100644
--- a/stock/DocType Mapper/Delivery Note-Packing Slip/Delivery Note-Packing Slip.txt
+++ b/stock/DocType Mapper/Delivery Note-Packing Slip/Delivery Note-Packing Slip.txt
@@ -2,7 +2,7 @@
{
"creation": "2012-02-02 11:50:33",
"docstatus": 0,
- "modified": "2013-04-05 16:08:22",
+ "modified": "2013-04-16 12:26:28",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -61,6 +61,13 @@
"to_field": "dn_detail"
},
{
+ "doctype": "Field Mapper Detail",
+ "from_field": "eval: flt(obj.qty) - flt(obj.packed_qty)",
+ "map": "Yes",
+ "match_id": 1,
+ "to_field": "qty"
+ },
+ {
"doctype": "Table Mapper Detail",
"from_table": "Delivery Note",
"match_id": 0,
diff --git a/stock/doctype/delivery_note/delivery_note.js b/stock/doctype/delivery_note/delivery_note.js
index f47040d..8d09cbd 100644
--- a/stock/doctype/delivery_note/delivery_note.js
+++ b/stock/doctype/delivery_note/delivery_note.js
@@ -158,7 +158,6 @@
}
-// ****************************** DELIVERY TYPE ************************************
cur_frm.cscript.delivery_type = function(doc, cdt, cdn) {
if (doc.delivery_type = 'Sample') cfn_set_fields(doc, cdt, cdn);
}
@@ -185,7 +184,6 @@
return 'SELECT DISTINCT `tabSupplier`.`name` FROM `tabSupplier` WHERE `tabSupplier`.supplier_type = "transporter" AND `tabSupplier`.docstatus != 2 AND `tabSupplier`.%(key)s LIKE "%s" ORDER BY `tabSupplier`.`name` LIMIT 50';
}
-//-----------------------------------Make Sales Invoice----------------------------------------------
cur_frm.cscript['Make Sales Invoice'] = function() {
var doc = cur_frm.doc
n = wn.model.make_new_doc_and_get_name('Sales Invoice');
@@ -201,7 +199,6 @@
);
}
-//-----------------------------------Make Installation Note----------------------------------------------
cur_frm.cscript['Make Installation Note'] = function() {
var doc = cur_frm.doc;
if(doc.per_installed < 99.99){
@@ -221,31 +218,19 @@
msgprint("Item installation is already completed")
}
-//-----------------------------------Make Sales Invoice----------------------------------------------
cur_frm.cscript['Make Packing Slip'] = function() {
- var doc = cur_frm.doc
n = wn.model.make_new_doc_and_get_name('Packing Slip');
- $c('dt_map', args={
- 'docs':wn.model.compress([locals['Packing Slip'][n]]),
- 'from_doctype':doc.doctype,
- 'to_doctype':'Packing Slip',
- 'from_docname':doc.name,
- 'from_to_list':"[['Delivery Note','Packing Slip'],['Delivery Note Item','Packing Slip Item']]"
- }, function(r,rt) {
- loaddoc('Packing Slip', n);
- }
- );
+ ps = locals["Packing Slip"][n];
+ ps.delivery_note = cur_frm.doc.name;
+ loaddoc('Packing Slip', n);
}
//get query select Territory
-//=======================================================================================================================
cur_frm.fields_dict['territory'].get_query = function(doc,cdt,cdn) {
return 'SELECT `tabTerritory`.`name`,`tabTerritory`.`parent_territory` FROM `tabTerritory` WHERE `tabTerritory`.`is_group` = "No" AND `tabTerritory`.`docstatus`!= 2 AND `tabTerritory`.%(key)s LIKE "%s" ORDER BY `tabTerritory`.`name` ASC LIMIT 50';
}
-//------------------------for printing without amount----------
-
var set_print_hide= function(doc, cdt, cdn){
var dn_fields = wn.meta.docfield_map['Delivery Note'];
var dn_item_fields = wn.meta.docfield_map['Delivery Note Item'];
diff --git a/stock/doctype/delivery_note/delivery_note.py b/stock/doctype/delivery_note/delivery_note.py
index 0019698..15e24ef 100644
--- a/stock/doctype/delivery_note/delivery_note.py
+++ b/stock/doctype/delivery_note/delivery_note.py
@@ -20,7 +20,7 @@
from webnotes.utils import cstr, flt, getdate, cint
from webnotes.model.bean import getlist
from webnotes.model.code import get_obj
-from webnotes import msgprint
+from webnotes import msgprint, _
import webnotes.defaults
@@ -333,17 +333,15 @@
"""
Cancel submitted packing slips related to this delivery note
"""
- res = webnotes.conn.sql("""\
- SELECT name, count(*) FROM `tabPacking Slip`
- WHERE delivery_note = %s AND docstatus = 1
- """, self.doc.name)
+ res = webnotes.conn.sql("""SELECT name FROM `tabPacking Slip` WHERE delivery_note = %s
+ AND docstatus = 1""", self.doc.name)
- if res and res[0][1]>0:
+ if res:
from webnotes.model.bean import Bean
for r in res:
ps = Bean(dt='Packing Slip', dn=r[0])
ps.cancel()
- webnotes.msgprint("%s Packing Slip(s) Cancelled" % res[0][1])
+ webnotes.msgprint(_("Packing Slip(s) Cancelled"))
def update_stock_ledger(self, update_stock):
@@ -421,4 +419,4 @@
if gl_entries:
from accounts.general_ledger import make_gl_entries
- make_gl_entries(gl_entries)
+ make_gl_entries(gl_entries)
\ No newline at end of file
diff --git a/stock/doctype/delivery_note_item/delivery_note_item.txt b/stock/doctype/delivery_note_item/delivery_note_item.txt
index fb3dd41..1073f0c 100644
--- a/stock/doctype/delivery_note_item/delivery_note_item.txt
+++ b/stock/doctype/delivery_note_item/delivery_note_item.txt
@@ -1,8 +1,8 @@
[
{
- "creation": "2013-03-26 11:03:09",
+ "creation": "2013-04-01 10:49:21",
"docstatus": 0,
- "modified": "2013-03-28 15:42:41",
+ "modified": "2013-04-17 17:20:58",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -257,6 +257,7 @@
"width": "120px"
},
{
+ "default": ":Company",
"doctype": "DocField",
"fieldname": "cost_center",
"fieldtype": "Link",
@@ -333,17 +334,6 @@
"width": "150px"
},
{
- "allow_on_submit": 1,
- "default": "0",
- "doctype": "DocField",
- "fieldname": "packed_qty",
- "fieldtype": "Float",
- "label": "Packed Quantity",
- "no_copy": 1,
- "print_hide": 1,
- "read_only": 1
- },
- {
"doctype": "DocField",
"fieldname": "prevdoc_doctype",
"fieldtype": "Data",
diff --git a/stock/doctype/item/item.py b/stock/doctype/item/item.py
index 2b2dbfe..a16296d 100644
--- a/stock/doctype/item/item.py
+++ b/stock/doctype/item/item.py
@@ -22,12 +22,10 @@
from webnotes.model.bean import getlist
from webnotes import msgprint, _
-sql = webnotes.conn.sql
-
from webnotes.model.controller import DocListController
class DocType(DocListController):
def get_tax_rate(self, tax_type):
- rate = sql("select tax_rate from tabAccount where name = %s", tax_type)
+ rate = webnotes.conn.sql("select tax_rate from tabAccount where name = %s", tax_type)
ret = {
'tax_rate' : rate and flt(rate[0][0]) or 0
}
@@ -39,7 +37,8 @@
# webpage updates
self.update_website()
- bin = sql("select stock_uom from `tabBin` where item_code = '%s' " % self.doc.item_code)
+ bin = webnotes.conn.sql("select stock_uom from `tabBin` where item_code = %s",
+ self.doc.item_code)
if bin and cstr(bin[0][0]) and cstr(bin[0][0]) != cstr(self.doc.stock_uom):
msgprint("Please Update Stock UOM with the help of Stock UOM Replace Utility.")
raise Exception
@@ -107,8 +106,8 @@
# On delete 1. Delete BIN (if none of the corrosponding transactions present, it gets deleted. if present, rolled back due to exception)
def on_trash(self):
- sql("""delete from tabBin where item_code=%s""", self.doc.item_code)
- sql("""delete from `tabStock Ledger Entry`
+ webnotes.conn.sql("""delete from tabBin where item_code=%s""", self.doc.item_code)
+ webnotes.conn.sql("""delete from `tabStock Ledger Entry`
where item_code=%s and is_cancelled='Yes' """, self.doc.item_code)
if self.doc.page_name:
@@ -149,7 +148,7 @@
def check_for_active_boms(self, field_label):
if field_label in ['Is Active', 'Is Purchase Item']:
- bom_mat = sql("select distinct t1.parent from `tabBOM Item` t1, `tabBOM` t2 where t1.item_code ='%s' and (t1.bom_no = '' or t1.bom_no is NULL) and t2.name = t1.parent and t2.is_active = 1 and t2.docstatus = 1 and t1.docstatus =1 " % self.doc.name )
+ bom_mat = webnotes.conn.sql("select distinct t1.parent from `tabBOM Item` t1, `tabBOM` t2 where t1.item_code =%s and (t1.bom_no = '' or t1.bom_no is NULL) and t2.name = t1.parent and t2.is_active = 1 and t2.docstatus = 1 and t1.docstatus =1 ", self.doc.name)
if bom_mat and bom_mat[0][0]:
msgprint("%s should be 'Yes'. As Item %s is present in one or many Active BOMs." % (cstr(field_label), cstr(self.doc.name)))
raise Exception
@@ -157,25 +156,27 @@
and self.doc.is_sub_contracted_item != 'Yes')
or (field_label == 'Is Sub Contracted Item'
and self.doc.is_manufactured_item != 'Yes')):
- bom = sql("select name from `tabBOM` where item = '%s' and is_active = 1" % cstr(self.doc.name))
+ bom = webnotes.conn.sql("select name from `tabBOM` where item = %s and is_active = 1",
+ (self.doc.name,))
if bom and bom[0][0]:
msgprint("%s should be 'Yes'. As Item %s is present in one or many Active BOMs." % (cstr(field_label), cstr(self.doc.name)))
raise Exception
def validate_barcode(self):
if self.doc.barcode:
- duplicate = sql("select name from tabItem where barcode = %s and name != %s", (self.doc.barcode, self.doc.name))
+ duplicate = webnotes.conn.sql("select name from tabItem where barcode = %s and name != %s", (self.doc.barcode, self.doc.name))
if duplicate:
msgprint("Barcode: %s already used in item: %s" % (self.doc.barcode, cstr(duplicate[0][0])), raise_exception = 1)
def validate(self):
- fl = {'is_manufactured_item' :'Allow Bill of Materials',
+ if not cint(self.doc.fields.get("__islocal")):
+ fl = {'is_manufactured_item' :'Allow Bill of Materials',
'is_sub_contracted_item':'Is Sub Contracted Item',
'is_purchase_item' :'Is Purchase Item',
'is_pro_applicable' :'Allow Production Order'}
- for d in fl:
- if cstr(self.doc.fields.get(d)) != 'Yes':
- self.check_for_active_boms(fl[d])
+ for d in fl:
+ if cstr(self.doc.fields.get(d)) != 'Yes':
+ self.check_for_active_boms(fl[d])
self.check_ref_rate_detail()
self.fill_customer_code()
self.check_item_tax()
@@ -197,7 +198,7 @@
def check_non_asset_warehouse(self):
if self.doc.is_asset_item == "Yes":
- existing_qty = sql("select t1.warehouse, t1.actual_qty from tabBin t1, tabWarehouse t2 where t1.item_code=%s and (t2.warehouse_type!='Fixed Asset' or t2.warehouse_type is null) and t1.warehouse=t2.name and t1.actual_qty > 0", self.doc.name)
+ existing_qty = webnotes.conn.sql("select t1.warehouse, t1.actual_qty from tabBin t1, tabWarehouse t2 where t1.item_code=%s and (t2.warehouse_type!='Fixed Asset' or t2.warehouse_type is null) and t1.warehouse=t2.name and t1.actual_qty > 0", self.doc.name)
for e in existing_qty:
msgprint("%s Units exist in Warehouse %s, which is not an Asset Warehouse." % (e[1],e[0]))
if existing_qty:
@@ -206,7 +207,7 @@
raise Exception
def get_file_details(self, arg = ''):
- file = sql("select file_group, description from tabFile where name = %s", eval(arg)['file_name'], as_dict = 1)
+ file = webnotes.conn.sql("select file_group, description from tabFile where name = %s", eval(arg)['file_name'], as_dict = 1)
ret = {
'file_group' : file and file[0]['file_group'] or '',
@@ -216,11 +217,11 @@
def check_if_sle_exists(self):
- sle = sql("select name from `tabStock Ledger Entry` where item_code = %s and ifnull(is_cancelled, 'No') = 'No'", self.doc.name)
+ sle = webnotes.conn.sql("select name from `tabStock Ledger Entry` where item_code = %s and ifnull(is_cancelled, 'No') = 'No'", self.doc.name)
return sle and 'exists' or 'not exists'
def on_rename(self,newdn,olddn):
- sql("update tabItem set item_code = %s where name = %s", (newdn, olddn))
+ webnotes.conn.sql("update tabItem set item_code = %s where name = %s", (newdn, olddn))
if self.doc.page_name:
from webnotes.webutils import clear_cache
clear_cache(self.doc.page_name)
@@ -242,7 +243,7 @@
if vals and ((self.doc.is_stock_item == "No" and vals.is_stock_item == "Yes") or
vals.has_serial_no != self.doc.has_serial_no or
vals.valuation_method != self.doc.valuation_method):
- if self.check_if_sle_exists():
+ if self.check_if_sle_exists() == "exists":
webnotes.msgprint(_("As there are existing stock transactions for this \
item, you can not change the values of 'Has Serial No', \
'Is Stock Item' and 'Valuation Method'"), raise_exception=1)
diff --git a/stock/doctype/packing_slip/packing_slip.js b/stock/doctype/packing_slip/packing_slip.js
index 5ece164..18a2486 100644
--- a/stock/doctype/packing_slip/packing_slip.js
+++ b/stock/doctype/packing_slip/packing_slip.js
@@ -23,52 +23,36 @@
function(doc, cdt, cdn) {
var query = 'SELECT name, item_name, description FROM `tabItem` WHERE name IN ( \
SELECT item_code FROM `tabDelivery Note Item` dnd \
- WHERE parent="' + doc.delivery_note + '" AND IFNULL(qty, 0) > IFNULL(packed_qty, 0)) AND %(key)s LIKE "%s" LIMIT 50';
+ WHERE parent="' + doc.delivery_note + '" AND IFNULL(qty, 0) > IFNULL(packed_qty, 0)) \
+ AND %(key)s LIKE "%s" LIMIT 50';
return query;
}
-
-// Fetch item details
-cur_frm.add_fetch("item_code", "item_name", "item_name");
-cur_frm.add_fetch("item_code", "stock_uom", "stock_uom");
-cur_frm.add_fetch("item_code", "net_weight", "net_weight");
-cur_frm.add_fetch("item_code", "weight_uom", "weight_uom");
-
cur_frm.cscript.onload_post_render = function(doc, cdt, cdn) {
if(doc.delivery_note && doc.__islocal) {
- var ps_detail = getchildren('Packing Slip Item', doc.name, 'item_details');
- if(!(flt(ps_detail.net_weight) && cstr(ps_detail.weight_uom))) {
- cur_frm.cscript.update_item_details(doc);
- }
+ cur_frm.cscript.get_items(doc, cdt, cdn);
}
}
-cur_frm.cscript.refresh = function(doc, dt, dn) {
- if(!doc.amended_from) {
- hide_field('misc_details');
- } else {
- unhide_field('misc_details');
- }
-}
-
-
-cur_frm.cscript.update_item_details = function(doc) {
- $c_obj(make_doclist(doc.doctype, doc.name), 'update_item_details', '', function(r, rt) {
- if(r.exc) {
- msgprint(r.exc);
- } else {
- refresh_many(['item_details', 'naming_series', 'from_case_no', 'to_case_no'])
+cur_frm.cscript.get_items = function(doc, cdt, cdn) {
+ this.frm.call({
+ doc: this.frm.doc,
+ method: "get_items",
+ callback: function(r) {
+ if(!r.exc) cur_frm.refresh();
}
});
}
+cur_frm.cscript.refresh = function(doc, dt, dn) {
+ cur_frm.toggle_display("misc_details", doc.amended_from);
+}
cur_frm.cscript.validate = function(doc, cdt, cdn) {
cur_frm.cscript.validate_case_nos(doc);
cur_frm.cscript.validate_calculate_item_details(doc);
}
-
// To Case No. cannot be less than From Case No.
cur_frm.cscript.validate_case_nos = function(doc) {
doc = locals[doc.doctype][doc.name];
@@ -99,7 +83,7 @@
cur_frm.cscript.validate_duplicate_items = function(doc, ps_detail) {
for(var i=0; i<ps_detail.length; i++) {
for(var j=0; j<ps_detail.length; j++) {
- if(i!=j && ps_detail[i].dn_detail && ps_detail[i].dn_detail==ps_detail[j].dn_detail) {
+ if(i!=j && ps_detail[i].item_code && ps_detail[i].item_code==ps_detail[j].item_code) {
msgprint("You have entered duplicate items. Please rectify and try again.");
validated = false;
return;
diff --git a/stock/doctype/packing_slip/packing_slip.py b/stock/doctype/packing_slip/packing_slip.py
index 161c9bd..1375108 100644
--- a/stock/doctype/packing_slip/packing_slip.py
+++ b/stock/doctype/packing_slip/packing_slip.py
@@ -16,13 +16,14 @@
from __future__ import unicode_literals
import webnotes
-from webnotes.utils import flt, cint, now
+from webnotes.utils import flt, cint
+from webnotes import msgprint, _
+from webnotes.model.doc import addchild
class DocType:
def __init__(self, d, dl):
self.doc, self.doclist = d, dl
-
def validate(self):
"""
* Validate existence of submitted Delivery Note
@@ -32,48 +33,48 @@
It is necessary to validate case nos before checking quantity
"""
self.validate_delivery_note()
+ self.validate_items_mandatory()
self.validate_case_nos()
self.validate_qty()
-
def validate_delivery_note(self):
"""
- Validates if delivery note has status as submitted
+ Validates if delivery note has status as draft
"""
- res = webnotes.conn.sql("""SELECT docstatus FROM `tabDelivery Note`
- WHERE name=%(delivery_note)s""", self.doc.fields)
-
- if not(res and res[0][0]==0):
- webnotes.msgprint("""Invalid Delivery Note. Delivery Note should exist
- and should be in draft state. Please rectify and try again.""", raise_exception=1)
-
+ if cint(webnotes.conn.get_value("Delivery Note", self.doc.delivery_note, "docstatus")) != 0:
+ msgprint(_("""Invalid Delivery Note. Delivery Note should exist and should be in
+ draft state. Please rectify and try again."""), raise_exception=1)
+
+ def validate_items_mandatory(self):
+ rows = [d.item_code for d in self.doclist.get({"parentfield": "item_details"})]
+ if not rows:
+ webnotes.msgprint(_("No Items to Pack"), raise_exception=1)
def validate_case_nos(self):
"""
- Validate if case nos overlap
- If they do, recommend next case no.
+ Validate if case nos overlap. If they do, recommend next case no.
"""
if not cint(self.doc.from_case_no):
- webnotes.msgprint("Please specify a valid 'From Case No.'", raise_exception=1)
+ webnotes.msgprint(_("Please specify a valid 'From Case No.'"), raise_exception=1)
elif not self.doc.to_case_no:
self.doc.to_case_no = self.doc.from_case_no
elif self.doc.from_case_no > self.doc.to_case_no:
- webnotes.msgprint("'To Case No.' cannot be less than 'From Case No.'",
+ webnotes.msgprint(_("'To Case No.' cannot be less than 'From Case No.'"),
raise_exception=1)
res = webnotes.conn.sql("""SELECT name FROM `tabPacking Slip`
WHERE delivery_note = %(delivery_note)s AND docstatus = 1 AND
(from_case_no BETWEEN %(from_case_no)s AND %(to_case_no)s
- OR to_case_no BETWEEN %(from_case_no)s AND %(to_case_no)s)
+ OR to_case_no BETWEEN %(from_case_no)s AND %(to_case_no)s
+ OR %(from_case_no)s BETWEEN from_case_no AND to_case_no)
""", self.doc.fields)
if res:
- webnotes.msgprint("""Case No(s). already in use. Please rectify and try again.
- Recommended <b>From Case No. = %s</b>""" % self.get_recommended_case_no(),
+ webnotes.msgprint(_("""Case No(s) already in use. Please rectify and try again.
+ Recommended <b>From Case No. = %s</b>""") % self.get_recommended_case_no(),
raise_exception=1)
-
def validate_qty(self):
"""
Check packed qty across packing slips and delivery note
@@ -82,8 +83,9 @@
dn_details, ps_item_qty, no_of_cases = self.get_details_for_packing()
for item in dn_details:
- new_packed_qty = (flt(ps_item_qty[item['item_code']]) * no_of_cases) + flt(item['packed_qty'])
- if new_packed_qty > flt(item['qty']):
+ new_packed_qty = (flt(ps_item_qty[item['item_code']]) * no_of_cases) + \
+ flt(item['packed_qty'])
+ if new_packed_qty > flt(item['qty']) and no_of_cases:
self.recommend_new_qty(item, ps_item_qty, no_of_cases)
@@ -95,26 +97,25 @@
* No. of Cases of this packing slip
"""
- items = [d.item_code for d in self.doclist.get({"parentfield": "item_details"})]
+ rows = [d.item_code for d in self.doclist.get({"parentfield": "item_details"})]
- if not items: webnotes.msgprint("No Items to Pack",
- raise_exception=1)
+ condition = ""
+ if rows:
+ condition = " and item_code in (%s)" % (", ".join(["%s"]*len(rows)))
# gets item code, qty per item code, latest packed qty per item code and stock uom
res = webnotes.conn.sql("""select item_code, ifnull(sum(qty), 0) as qty,
(select sum(ifnull(psi.qty, 0) * (abs(ps.to_case_no - ps.from_case_no) + 1))
from `tabPacking Slip` ps, `tabPacking Slip Item` psi
where ps.name = psi.parent and ps.docstatus = 1
- and ps.delivery_note = dni.parent and psi.item_code=dni.item_code)
- as packed_qty,
- stock_uom
+ and ps.delivery_note = dni.parent and psi.item_code=dni.item_code) as packed_qty,
+ stock_uom, item_name
from `tabDelivery Note Item` dni
- where parent=%s and item_code in (%s)
- group by item_code""" % ("%s", ", ".join(["%s"]*len(items))),
- tuple([self.doc.delivery_note] + items), as_dict=1)
-
- ps_item_qty = dict([[d.item_code, d.qty] for d in self.doclist])
+ where parent=%s %s
+ group by item_code""" % ("%s", condition),
+ tuple([self.doc.delivery_note] + rows), as_dict=1)
+ ps_item_qty = dict([[d.item_code, d.qty] for d in self.doclist])
no_of_cases = cint(self.doc.to_case_no) - cint(self.doc.from_case_no) + 1
return res, ps_item_qty, no_of_cases
@@ -134,45 +135,6 @@
<b>Recommended quantity for %(item_code)s = %(recommended_qty)s
%(stock_uom)s</b>""" % item, raise_exception=1)
-
- def on_submit(self):
- """
- * Update packed qty for all items
- """
- self.update_packed_qty(event='submit')
-
-
- def on_cancel(self):
- """
- * Update packed qty for all items
- """
- self.update_packed_qty(event='cancel')
-
-
- def update_packed_qty(self, event=''):
- """
- Updates packed qty for all items
- """
- if event not in ['submit', 'cancel']:
- raise Exception('update_packed_quantity can only be called on submit or cancel')
-
- # Get Delivery Note Items, Item Quantity Dict and No. of Cases for this Packing slip
- dn_details, ps_item_qty, no_of_cases = self.get_details_for_packing()
-
- for item in dn_details:
- new_packed_qty = flt(item['packed_qty'])
- if (new_packed_qty < 0) or (new_packed_qty > flt(item['qty'])):
- webnotes.msgprint("""Invalid new packed quantity for item %s.
- Please try again or contact support@erpnext.com""" %
- item['item_code'], raise_exception=1)
-
- webnotes.conn.sql("""UPDATE `tabDelivery Note Item`
- SET packed_qty = %s WHERE parent = %s AND item_code = %s""",
- (new_packed_qty, self.doc.delivery_note, item['item_code']))
-
- webnotes.conn.set_value("Delivery Note", self.doc.delivery_note, "modified", now())
-
-
def update_item_details(self):
"""
Fill empty columns in Packing Slip Item
@@ -181,28 +143,12 @@
self.doc.from_case_no = self.get_recommended_case_no()
for d in self.doclist.get({"parentfield": "item_details"}):
- self.set_item_details(d)
-
-
- def set_item_details(self, row):
- res = webnotes.conn.sql("""SELECT item_name, SUM(IFNULL(qty, 0)) as total_qty,
- IFNULL(packed_qty, 0) as packed_qty, stock_uom
- FROM `tabDelivery Note Item`
- WHERE parent=%s AND item_code=%s GROUP BY item_code""",
- (self.doc.delivery_note, row.item_code), as_dict=1)
-
- if res and len(res)>0:
- qty = res[0]['total_qty'] - res[0]['packed_qty']
- if not row.qty:
- row.qty = qty >= 0 and qty or 0
-
- res = webnotes.conn.sql("""SELECT net_weight, weight_uom FROM `tabItem`
- WHERE name=%s""", row.item_code, as_dict=1)
+ res = webnotes.conn.get_value("Item", d.item_code,
+ ["net_weight", "weight_uom"], as_dict=True)
- if res and len(res)>0:
- row.net_weight = res[0]["net_weight"]
- row.weight_uom = res[0]["weight_uom"]
-
+ if res and len(res)>0:
+ d.net_weight = res["net_weight"]
+ d.weight_uom = res["weight_uom"]
def get_recommended_case_no(self):
"""
@@ -211,5 +157,18 @@
"""
recommended_case_no = webnotes.conn.sql("""SELECT MAX(to_case_no) FROM `tabPacking Slip`
WHERE delivery_note = %(delivery_note)s AND docstatus=1""", self.doc.fields)
-
- return cint(recommended_case_no[0][0]) + 1
\ No newline at end of file
+
+ return cint(recommended_case_no[0][0]) + 1
+
+ def get_items(self):
+ self.doclist = self.doc.clear_table(self.doclist, "item_details", 1)
+
+ dn_details = self.get_details_for_packing()[0]
+ for item in dn_details:
+ if flt(item.qty) > flt(item.packed_qty):
+ ch = addchild(self.doc, 'item_details', 'Packing Slip Item', self.doclist)
+ ch.item_code = item.item_code
+ ch.item_name = item.item_name
+ ch.stock_uom = item.stock_uom
+ ch.qty = flt(item.qty) - flt(item.packed_qty)
+ self.update_item_details()
\ No newline at end of file
diff --git a/stock/doctype/packing_slip/packing_slip.txt b/stock/doctype/packing_slip/packing_slip.txt
index 32ac16b..f13b971 100644
--- a/stock/doctype/packing_slip/packing_slip.txt
+++ b/stock/doctype/packing_slip/packing_slip.txt
@@ -1,8 +1,8 @@
[
{
- "creation": "2013-03-07 18:50:31",
+ "creation": "2013-04-11 15:32:24",
"docstatus": 0,
- "modified": "2013-04-05 15:40:59",
+ "modified": "2013-04-16 17:33:38",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -132,6 +132,12 @@
},
{
"doctype": "DocField",
+ "fieldname": "get_items",
+ "fieldtype": "Button",
+ "label": "Get Items"
+ },
+ {
+ "doctype": "DocField",
"fieldname": "item_details",
"fieldtype": "Table",
"label": "Items",
diff --git a/stock/doctype/stock_ledger/stock_ledger.py b/stock/doctype/stock_ledger/stock_ledger.py
index 469c94b..3c83de3 100644
--- a/stock/doctype/stock_ledger/stock_ledger.py
+++ b/stock/doctype/stock_ledger/stock_ledger.py
@@ -84,7 +84,6 @@
item_details = webnotes.conn.sql("""select item_group, warranty_period
from `tabItem` where name = '%s' and (ifnull(end_of_life,'')='' or
end_of_life = '0000-00-00' or end_of_life > now()) """ %(d.item_code), as_dict=1)
- webnotes.errprint([d.item_code, d.valuation_rate])
s.purchase_document_type = obj.doc.doctype
s.purchase_document_no = obj.doc.name
diff --git a/website/doctype/website_settings/website_settings.txt b/website/doctype/website_settings/website_settings.txt
index 4b66e09..7eaa50e 100644
--- a/website/doctype/website_settings/website_settings.txt
+++ b/website/doctype/website_settings/website_settings.txt
@@ -1,8 +1,7 @@
[
- {
- "creation": "2013-03-25 16:01:34",
+ "creation": "2013-03-26 06:51:18",
"docstatus": 0,
- "modified": "2013-04-12 10:30:18",
+ "modified": "2013-04-17 11:51:24",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -231,13 +230,6 @@
"create": 1,
"doctype": "DocPerm",
"permlevel": 0,
- "role": "System Manager",
- "write": 1
- },
- {
- "create": 1,
- "doctype": "DocPerm",
- "permlevel": 0,
"role": "Website Manager",
"write": 1
},
diff --git a/website/helpers/sitemap.py b/website/helpers/sitemap.py
index 201865a..c8b6fd0 100644
--- a/website/helpers/sitemap.py
+++ b/website/helpers/sitemap.py
@@ -14,25 +14,40 @@
import urllib, os
import webnotes
import webnotes.webutils
+ from webnotes.utils import nowdate
# settings
- max_doctypes = 10
max_items = 1000
+ count = 0
site_map = ''
- page_list = []
-
if domain:
- # list of all pages in web cache
- for doctype in webnotes.webutils.page_map:
- d = webnotes.webutils.page_map[doctype];
+ today = nowdate()
+
+ # generated pages
+ for doctype, opts in webnotes.webutils.get_generators().items():
pages = webnotes.conn.sql("""select page_name, `modified`
from `tab%s` where ifnull(%s,0)=1
- order by modified desc""" % (doctype, d.condition_field))
+ order by modified desc""" % (doctype, opts.get("condition_field")))
for p in pages:
+ if count >= max_items: break
page_url = os.path.join(domain, urllib.quote(p[0]))
modified = p[1].strftime('%Y-%m-%d')
site_map += link_xml % (page_url, modified)
+ count += 1
+
+ if count >= max_items: break
+
+ # standard pages
+ for page, opts in webnotes.get_config()["web"]["pages"].items():
+ if "no_cache" in opts:
+ continue
+
+ if count >= max_items: break
+ page_url = os.path.join(domain, urllib.quote(page))
+ modified = today
+ site_map += link_xml % (page_url, modified)
+ count += 1
- return frame_xml % site_map
+ return frame_xml % site_map