Merge branch 'master' of github.com:webnotes/erpnext
diff --git a/accounts/page/accounts_browser/accounts_browser.py b/accounts/page/accounts_browser/accounts_browser.py
index 76c64b7..8b24394 100644
--- a/accounts/page/accounts_browser/accounts_browser.py
+++ b/accounts/page/accounts_browser/accounts_browser.py
@@ -20,7 +20,7 @@
else:
return [r[0] for r in webnotes.conn.sql("""select name from tabCompany
where docstatus!=2""")]
-
+
@webnotes.whitelist()
def get_children():
args = webnotes.form_dict
diff --git a/accounts/search_criteria/creditors_ledger/creditors_ledger.txt b/accounts/search_criteria/creditors_ledger/creditors_ledger.txt
index 9a7565c..12134e1 100644
--- a/accounts/search_criteria/creditors_ledger/creditors_ledger.txt
+++ b/accounts/search_criteria/creditors_ledger/creditors_ledger.txt
@@ -1,31 +1,27 @@
-# Search Criteria, creditors_ledger
[
-
- # These values are common in all dictionaries
- {
- 'creation': '2012-04-03 12:49:51',
- 'docstatus': 0,
- 'modified': '2012-04-03 12:49:51',
- 'modified_by': u'Administrator',
- 'owner': u'nabin@webnotestech.com'
- },
-
- # These values are common for all Search Criteria
- {
- 'criteria_name': u"Creditor's Ledger",
- 'doc_type': u'GL Entry',
- 'doctype': 'Search Criteria',
- 'filters': u"{'GL Entry\x01Voucher Type':'','GL Entry\x01Is Cancelled':'','GL Entry\x01Is Opening':'','GL Entry\x01Fiscal Year':''}",
- 'module': u'Accounts',
- 'name': '__common__',
- 'page_len': 50,
- 'sort_order': u'DESC',
- 'standard': u'Yes'
- },
-
- # Search Criteria, creditors_ledger
- {
- 'doctype': 'Search Criteria',
- 'name': u'creditors_ledger'
- }
+ {
+ "owner": "nabin@erpnext.com",
+ "docstatus": 0,
+ "creation": "2012-05-14 18:05:41",
+ "modified_by": "nabin@erpnext.com",
+ "modified": "2012-12-06 11:36:09"
+ },
+ {
+ "custom_query": null,
+ "report_script": null,
+ "page_len": 50,
+ "module": "Accounts",
+ "standard": "Yes",
+ "sort_order": "DESC",
+ "filters": "{\"GL Entry\\u0001Voucher Type\":[],\"GL Entry\\u0001Is Cancelled\":[\"No\"],\"GL Entry\\u0001Is Opening\":[\"\"],\"GL Entry\\u0001Fiscal Year\":[\"\"]}",
+ "doc_type": "GL Entry",
+ "name": "__common__",
+ "doctype": "Search Criteria",
+ "sort_by": "`tabGL Entry`.`name`",
+ "criteria_name": "Creditor's Ledger"
+ },
+ {
+ "name": "creditors_ledger",
+ "doctype": "Search Criteria"
+ }
]
\ No newline at end of file
diff --git a/accounts/search_criteria/debtors_ledger/debtors_ledger.txt b/accounts/search_criteria/debtors_ledger/debtors_ledger.txt
index 0991097..a868003 100644
--- a/accounts/search_criteria/debtors_ledger/debtors_ledger.txt
+++ b/accounts/search_criteria/debtors_ledger/debtors_ledger.txt
@@ -1,31 +1,27 @@
-# Search Criteria, debtors_ledger
[
-
- # These values are common in all dictionaries
- {
- 'creation': '2012-04-03 12:49:51',
- 'docstatus': 0,
- 'modified': '2012-04-03 12:49:51',
- 'modified_by': u'Administrator',
- 'owner': u'nabin@webnotestech.com'
- },
-
- # These values are common for all Search Criteria
- {
- 'criteria_name': u"Debtor's Ledger",
- 'doc_type': u'GL Entry',
- 'doctype': 'Search Criteria',
- 'filters': u"{'GL Entry\x01Voucher Type':'','GL Entry\x01Is Cancelled':'No','GL Entry\x01Is Opening':'','GL Entry\x01Fiscal Year':''}",
- 'module': u'Accounts',
- 'name': '__common__',
- 'page_len': 50,
- 'sort_order': u'DESC',
- 'standard': u'Yes'
- },
-
- # Search Criteria, debtors_ledger
- {
- 'doctype': 'Search Criteria',
- 'name': u'debtors_ledger'
- }
+ {
+ "owner": "nabin@erpnext.com",
+ "docstatus": 0,
+ "creation": "2012-05-14 18:05:42",
+ "modified_by": "nabin@erpnext.com",
+ "modified": "2012-12-06 11:37:15"
+ },
+ {
+ "custom_query": null,
+ "report_script": null,
+ "page_len": 50,
+ "module": "Accounts",
+ "standard": "Yes",
+ "sort_order": "DESC",
+ "filters": "{\"GL Entry\\u0001Voucher Type\":[],\"GL Entry\\u0001Is Cancelled\":[\"No\"],\"GL Entry\\u0001Is Opening\":[],\"GL Entry\\u0001Fiscal Year\":[]}",
+ "doc_type": "GL Entry",
+ "name": "__common__",
+ "doctype": "Search Criteria",
+ "sort_by": "`tabGL Entry`.`name`",
+ "criteria_name": "Debtor's Ledger"
+ },
+ {
+ "name": "debtors_ledger",
+ "doctype": "Search Criteria"
+ }
]
\ No newline at end of file
diff --git a/buying/doctype/purchase_common/purchase_common.js b/buying/doctype/purchase_common/purchase_common.js
index 3b72236..b29ccb7 100644
--- a/buying/doctype/purchase_common/purchase_common.js
+++ b/buying/doctype/purchase_common/purchase_common.js
@@ -199,23 +199,35 @@
}
//==================== UOM ======================================================================
-cur_frm.cscript.uom = function(doc, cdt, cdn) {
+cur_frm.cscript.uom = function(doc, cdt, cdn, args) {
+ if(!args) args = {};
+
+ // args passed can contain conversion_factor
var d = locals[cdt][cdn];
- if (d.item_code && d.uom) {
- call_back = function(doc, cdt, cdn){
- cur_frm.cscript.calc_amount(doc, 2);
- }
- str_arg = {'item_code':d.item_code, 'uom':d.uom, 'stock_qty':flt(d.stock_qty), 'qty': flt(d.qty), 'conversion_rate':doc.conversion_rate, 'doc_name': doc.name}
- // Updates Conversion Factor, Qty and Purchase Rate
- get_server_fields('get_uom_details',JSON.stringify(str_arg), fname, doc,cdt,cdn,1, call_back);
- // don't make mistake of calling update_stock_qty() the get_uom_details returns stock_qty as per conversion factor properly
+ $.extend(args, {
+ item_code: d.item_code,
+ uom: d.uom,
+ stock_qty: flt(d.stock_qty),
+ });
+
+ if(d.item_code && d.uom) {
+ cur_frm.call({
+ method: "buying.doctype.purchase_common.purchase_common.get_uom_details",
+ args: { args: args },
+ child: d,
+ callback: function(r) {
+ cur_frm.cscript.calc_amount(doc, 2);
+ }
+ });
}
}
//==================== Conversion factor =========================================================
cur_frm.cscript.conversion_factor = function(doc, cdt, cdn) {
- cur_frm.cscript.uom(doc, cdt, cdn);
+ var item = locals[cdt][cdn];
+
+ cur_frm.cscript.uom(doc, cdt, cdn, { conversion_factor: item.conversion_factor });
}
//==================== stock qty ======================================================================
diff --git a/buying/doctype/purchase_common/purchase_common.py b/buying/doctype/purchase_common/purchase_common.py
index eb8ebef..9c1187d 100644
--- a/buying/doctype/purchase_common/purchase_common.py
+++ b/buying/doctype/purchase_common/purchase_common.py
@@ -182,39 +182,6 @@
ret = { 'projected_qty' : bin and flt(bin[0]['projected_qty']) or 0 }
return ret
- def get_uom_details(self, arg = ''):
- """fetches details on change of UOM"""
- import json
- arg, ret = json.loads(arg), {}
-
- uom = webnotes.conn.sql("""\
- select conversion_factor
- from `tabUOM Conversion Detail`
- where parent = %s and uom = %s""", (arg['item_code'],arg['uom']), as_dict = 1)
-
- if not uom: return ret
-
- last_purchase_details, last_purchase_date = self.get_last_purchase_details(arg['item_code'], arg['doc_name'])
-
- conversion_factor = flt(uom[0]['conversion_factor'])
- conversion_rate = flt(arg['conversion_rate'])
- purchase_ref_rate = last_purchase_details and \
- (last_purchase_details['purchase_ref_rate'] * conversion_factor) or 0
- purchase_rate = last_purchase_details and \
- (last_purchase_details['purchase_rate'] * conversion_factor) or 0
-
- ret = {
- 'conversion_factor': conversion_factor,
- 'qty': flt(arg['stock_qty']) / conversion_factor,
- 'purchase_ref_rate': purchase_ref_rate,
- 'purchase_rate': purchase_rate,
- 'import_ref_rate': purchase_ref_rate / conversion_rate,
- 'import_rate': purchase_rate / conversion_rate,
- }
-
- return ret
-
-
# --- Last Purchase Rate related methods ---
def update_last_purchase_rate(self, obj, is_submit):
@@ -683,3 +650,27 @@
if d.prevdoc_doctype and d.prevdoc_docname:
dt = sql("select transaction_date from `tab%s` where name = '%s'" % (d.prevdoc_doctype, d.prevdoc_docname))
d.prevdoc_date = dt and dt[0][0].strftime('%Y-%m-%d') or ''
+
+@webnotes.whitelist()
+def get_uom_details(args=None):
+ """fetches details on change of UOM"""
+ if not args:
+ return {}
+
+ if isinstance(args, basestring):
+ import json
+ args = json.loads(args)
+
+ uom = webnotes.conn.sql("""select conversion_factor
+ from `tabUOM Conversion Detail` where parent = %s and uom = %s""",
+ (args['item_code'], args['uom']), as_dict=1)
+
+ if not uom: return {}
+
+ conversion_factor = args.get("conversion_factor") or \
+ flt(uom[0]["conversion_factor"])
+
+ return {
+ "conversion_factor": conversion_factor,
+ "qty": flt(args["stock_qty"]) / conversion_factor,
+ }
\ No newline at end of file
diff --git a/buying/doctype/purchase_order/purchase_order.py b/buying/doctype/purchase_order/purchase_order.py
index 4497bcd..e52499c 100644
--- a/buying/doctype/purchase_order/purchase_order.py
+++ b/buying/doctype/purchase_order/purchase_order.py
@@ -69,10 +69,6 @@
- # Get UOM Details
- def get_uom_details(self, arg = ''):
- return get_obj('Purchase Common').get_uom_details(arg)
-
# get available qty at warehouse
def get_bin_details(self, arg = ''):
return get_obj(dt='Purchase Common').get_bin_details(arg)
diff --git a/buying/doctype/purchase_order/purchase_order_list.js b/buying/doctype/purchase_order/purchase_order_list.js
index 69f97f5..762c635 100644
--- a/buying/doctype/purchase_order/purchase_order_list.js
+++ b/buying/doctype/purchase_order/purchase_order_list.js
@@ -27,7 +27,7 @@
},
css: {'text-align':'right'}
},
- {width: '8%', content: 'per_received', type:'bar-graph', label:'Delivered'},
+ {width: '8%', content: 'per_received', type:'bar-graph', label:'Received'},
{width: '8%', content: 'per_billed', type:'bar-graph', label:'Billed'},
{width: '12%', content:'transaction_date',
css: {'text-align': 'right', 'color':'#777'},
diff --git a/buying/doctype/purchase_request/purchase_request.py b/buying/doctype/purchase_request/purchase_request.py
index 79c7400..7d0e08e 100644
--- a/buying/doctype/purchase_request/purchase_request.py
+++ b/buying/doctype/purchase_request/purchase_request.py
@@ -121,11 +121,6 @@
doc.fields[r] = ret[r]
- # Get UOM Details
- # ---------------------------------
- def get_uom_details(self, arg = ''):
- return get_obj(dt='Purchase Common').get_uom_details(arg)
-
# GET TERMS & CONDITIONS
#-----------------------------
def get_tc_details(self):
@@ -219,4 +214,4 @@
self.update_bin(is_submit = 0, is_stopped = (cstr(self.doc.status) == 'Stopped') and 1 or 0)
# Step 5:=> Set Status
- webnotes.conn.set(self.doc,'status','Cancelled')
+ webnotes.conn.set(self.doc,'status','Cancelled')
\ No newline at end of file
diff --git a/controllers/tax_controller.py b/controllers/tax_controller.py
index 7aa8e23..d70ba3e 100644
--- a/controllers/tax_controller.py
+++ b/controllers/tax_controller.py
@@ -140,7 +140,7 @@
self.doc.net_total = flt(self.doc.net_total, self.precision.main.net_total)
self.doc.fields[self.fmap.net_total_print] = \
flt(self.doc.fields.get(self.fmap.net_total_print),
- self.precision.main[self.fmap.net_total_print])
+ self.precision.main.get(self.fmap.net_total_print))
def calculate_taxes(self):
for item in self.item_doclist:
diff --git a/home/page/latest_updates/latest_updates.js b/home/page/latest_updates/latest_updates.js
index 09befee..d3bde12 100644
--- a/home/page/latest_updates/latest_updates.js
+++ b/home/page/latest_updates/latest_updates.js
@@ -1,5 +1,7 @@
erpnext.updates = [
["5th December 2012", [
+ "Leave Application: Now can set approver.",
+ "New Roles Added: Leave Approver and Expense Approver.",
"Production Order is now linked with sales order.",
"Production Planning Tool: The field 'Allow SA items as raw material' has been renamed to 'Use multi-level BOM', 'Include in plan' column from SO table has been deleted",
"Batch nos are now filtered with item and available qty",
diff --git a/hr/__init__.py b/hr/__init__.py
index 96bd47b..429c719 100644
--- a/hr/__init__.py
+++ b/hr/__init__.py
@@ -3,4 +3,6 @@
{"doctype":"Role", "role_name":"Employee", "name":"Employee"},
{"doctype":"Role", "role_name":"HR Manager", "name":"HR Manager"},
{"doctype":"Role", "role_name":"HR User", "name":"HR User"},
+ {"doctype":"Role", "role_name":"Leave Approver", "name":"Leave Approver"},
+ {"doctype":"Role", "role_name":"Expense Approver", "name":"Expense Approver"},
]
diff --git a/hr/doctype/expense_claim/expense_claim.js b/hr/doctype/expense_claim/expense_claim.js
index 466a8cf..8ba0978 100644
--- a/hr/doctype/expense_claim/expense_claim.js
+++ b/hr/doctype/expense_claim/expense_claim.js
@@ -15,79 +15,84 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
cur_frm.add_fetch('employee', 'company', 'company');
+cur_frm.add_fetch('employee','employee_name','employee_name');
cur_frm.cscript.onload = function(doc,cdt,cdn){
- //
- if(!doc.approval_status) set_multiple(cdt,cdn,{approval_status:'Draft'});
- if(doc.employee) cur_frm.cscript.employee(doc,cdt,cdn);
-
+ if(!doc.approval_status)
+ cur_frm.set_value("approval_status", "Draft")
+
if (doc.__islocal) {
- if(doc.amended_from) set_multiple(cdt,cdn,{approval_status:'Draft'});
- var val = getchildren('Expense Claim Detail', doc.name, 'expense_voucher_details', doc.doctype);
- for(var i = 0; i<val.length; i++){
- val[i].sanctioned_amount ='';
- }
- doc.total_sanctioned_amount = '';
- refresh_many(['sanctioned_amount', 'total_sanctioned_amount']);
+ cur_frm.set_value("posting_date", dateutil.get_today());
+ if(doc.amended_from)
+ cur_frm.set_value("approval_status", "Draft");
+ cur_frm.cscript.clear_sanctioned(doc);
}
+
+ cur_frm.call({
+ method:"get_approver_list",
+ callback: function(r) {
+ cur_frm.set_df_property("exp_approver", "options", r.message);
+ }
+ });
+}
+
+cur_frm.cscript.clear_sanctioned = function(doc) {
+ var val = getchildren('Expense Claim Detail', doc.name,
+ 'expense_voucher_details', doc.doctype);
+ for(var i = 0; i<val.length; i++){
+ val[i].sanctioned_amount ='';
+ }
+
+ doc.total_sanctioned_amount = '';
+ refresh_many(['sanctioned_amount', 'total_sanctioned_amount']);
}
cur_frm.cscript.refresh = function(doc,cdt,cdn){
- hide_field('calculate_total_amount');
- if(user == doc.exp_approver && doc.approval_status == 'Submitted'){
- unhide_field(['update_voucher', 'approve', 'reject', 'calculate_total_amount']);
- cur_frm.fields_dict['expense_voucher_details'].grid.set_column_disp('sanctioned_amount', true);
- set_field_permlevel('remark', 0);
+ cur_frm.set_intro("");
+ if(doc.__islocal && !in_list(user_roles, "HR User")) {
+ cur_frm.set_intro("Fill the form and save it")
} else {
- hide_field(['update_voucher', 'approve', 'reject']);
- cur_frm.fields_dict['expense_voucher_details'].grid.set_column_disp('sanctioned_amount', false);
- set_field_permlevel('remark', 1);
+ if(doc.approval_status=="Draft") {
+ if(user==doc.exp_approver) {
+ if(doc.approval_status=="Draft") {
+ cur_frm.set_intro("You are the Expense Approver for this record. Please Update the 'Status' and Save");
+ cur_frm.toggle_enable("approval_status", true);
+ }
+ } else {
+ cur_frm.set_intro("Expense Claim is pending approval. Only the Expense Approver can update status.");
+ cur_frm.toggle_enable("approval_status", false);
+ }
+ } else {
+ if(doc.approval_status=="Approved") {
+ cur_frm.set_intro("Expense Claim has been approved.");
+ } else if(doc.approval_status=="Rejected") {
+ cur_frm.set_intro("Expense Claim has been rejected.");
+ }
+ }
}
- if (doc.docstatus == 0) unhide_field('calculate_total_amount');
-}
+
+ if(doc.approval_status=="Approved" && doc.docstatus==0) {
+ cur_frm.savesubmit()
+ }}
cur_frm.cscript.validate = function(doc) {
- if(cint(doc.docstatus) == 0) {
- doc.approval_status = "Draft";
- }
cur_frm.cscript.calculate_total(doc);
}
-cur_frm.cscript.employee = function(doc,cdt,cdn){
- if(doc.employee){
- $c_obj(make_doclist(doc.doctype, doc.name),'set_approver','', function(r,rt){
- if(r.message){
- doc.employee_name = r.message['emp_nm'];
- wn.meta.get_docfield(doc.doctype, 'exp_approver' , doc.name).options = r.message['app_lst'];
- refresh_many(['exp_approver','employee_name']);
- }
- });
- }
-}
-
cur_frm.cscript.calculate_total = function(doc,cdt,cdn){
- if(doc.approval_status == 'Draft'){
- var val = getchildren('Expense Claim Detail', doc.name, 'expense_voucher_details', doc.doctype);
- var total_claim =0;
- for(var i = 0; i<val.length; i++){
- val[i].sanctioned_amount = val[i].claim_amount;
- total_claim = flt(total_claim)+flt(val[i].claim_amount);
- refresh_field('sactioned_amount', val[i].name, 'expense_voucher_details');
+ doc.total_claimed_amount = 0;
+ doc.total_sanctioned_amount = 0;
+ $.each(wn.model.get("Expense Claim Detail", {parent:doc.name}), function(i, d) {
+ doc.total_claimed_amount += d.claim_amount;
+ if(d.sanctioned_amount==null) {
+ d.sanctioned_amount = d.claim_amount;
}
- doc.total_claimed_amount = flt(total_claim);
- refresh_field('total_claimed_amount');
- }
- else if(doc.approval_status == 'Submitted'){
- var val = getchildren('Expense Claim Detail', doc.name, 'expense_voucher_details', doc.doctype);
- var total_sanctioned = 0;
- for(var i = 0; i<val.length; i++){
- total_sanctioned = flt(total_sanctioned)+flt(val[i].sanctioned_amount);
- refresh_field('sactioned_amount', val[i].name, 'expense_voucher_details');
-
- }
- doc.total_sanctioned_amount = flt(total_sanctioned);
- refresh_field('total_sanctioned_amount');
- }
+ doc.total_sanctioned_amount += d.sanctioned_amount;
+ });
+
+ refresh_field("total_claimed_amount");
+ refresh_field('total_sanctioned_amount');
+
}
cur_frm.cscript.calculate_total_amount = function(doc,cdt,cdn){
@@ -100,155 +105,8 @@
cur_frm.cscript.calculate_total(doc,cdt,cdn);
}
-cur_frm.cscript.approve = function(doc,cdt,cdn){
- cur_frm.cscript.calculate_total(doc,cdt,cdn);
-
- if(user == doc.exp_approver){
- var approve_voucher_dialog;
-
- set_approve_voucher_dialog = function() {
- approve_voucher_dialog = new Dialog(400, 200, 'Approve Voucher');
- approve_voucher_dialog.make_body([
- ['HTML', 'Message', '<div class = "comment">You wont be able to do any changes after approving this expense voucher. Are you sure, you want to approve it ?</div>'],
- ['HTML', 'Response', '<div class = "comment" id="approve_voucher_dialog_response"></div>'],
- ['HTML', 'Approve Voucher', '<div></div>']
- ]);
-
- var approve_voucher_btn1 = $a($i(approve_voucher_dialog.widgets['Approve Voucher']), 'button', 'button');
- approve_voucher_btn1.innerHTML = 'Yes';
- approve_voucher_btn1.onclick = function(){ approve_voucher_dialog.add(); }
-
- var approve_voucher_btn2 = $a($i(approve_voucher_dialog.widgets['Approve Voucher']), 'button', 'button');
- approve_voucher_btn2.innerHTML = 'No';
- $y(approve_voucher_btn2,{marginLeft:'4px'});
- approve_voucher_btn2.onclick = function(){ approve_voucher_dialog.hide();}
-
- approve_voucher_dialog.onshow = function() {
- $i('approve_voucher_dialog_response').innerHTML = '';
- }
-
- approve_voucher_dialog.add = function() {
- // sending...
- $i('approve_voucher_dialog_response').innerHTML = 'Processing...';
-
- $c_obj(make_doclist(this.doc.doctype, this.doc.name),'approve_voucher','', function(r,rt){
- if(r.message == 'Approved'){
- $i('approve_voucher_dialog_response').innerHTML = 'Approved';
- refresh_field('approval_status');
- hide_field(['update_voucher', 'approve', 'reject', 'calculate_total_amount']);
- approve_voucher_dialog.hide();
- var args = {
- type: 'Expense Claim Approved',
- doctype: 'Expense Claim',
- contact_name: doc.employee_name,
- send_to: doc.email_id
- }
- cur_frm.cscript.notify(doc, args);
- }
- else if(r.message == 'Incomplete'){
- $i('approve_voucher_dialog_response').innerHTML = 'Incomplete Voucher';
- }
- else if(r.message == 'No Amount'){
- $i('approve_voucher_dialog_response').innerHTML = 'Calculate total amount';
- }
- });
- }
- }
-
- if(!approve_voucher_dialog){
- set_approve_voucher_dialog();
- }
- approve_voucher_dialog.doc = doc;
- approve_voucher_dialog.cdt = cdt;
- approve_voucher_dialog.cdn = cdn;
- approve_voucher_dialog.show();
- refresh_field('expense_voucher_details');
- doc.__unsaved = 0;
- cur_frm.refresh_header();
- }else{
- msgprint("Expense Claim can be approved by Approver only");
- }
-}
-
-cur_frm.cscript.reject = function(doc,cdt,cdn){
- cur_frm.cscript.calculate_total(doc,cdt,cdn);
-
- if(user == doc.exp_approver){
- var reject_voucher_dialog;
-
- set_reject_voucher_dialog = function() {
- reject_voucher_dialog = new Dialog(400, 200, 'Reject Voucher');
- reject_voucher_dialog.make_body([
- ['HTML', 'Message', '<div class = "comment">You wont be able to do any changes after rejecting this expense voucher. Are you sure, you want to reject it ?</div>'],
- ['HTML', 'Response', '<div class = "comment" id="reject_voucher_dialog_response"></div>'],
- ['HTML', 'Reject Voucher', '<div></div>']
- ]);
-
- var reject_voucher_btn1 = $a($i(reject_voucher_dialog.widgets['Reject Voucher']), 'button', 'button');
- reject_voucher_btn1.innerHTML = 'Yes';
- reject_voucher_btn1.onclick = function(){ reject_voucher_dialog.add(); }
-
- var reject_voucher_btn2 = $a($i(reject_voucher_dialog.widgets['Reject Voucher']), 'button', 'button');
- reject_voucher_btn2.innerHTML = 'No';
- $y(reject_voucher_btn2,{marginLeft:'4px'});
- reject_voucher_btn2.onclick = function(){ reject_voucher_dialog.hide();}
-
- reject_voucher_dialog.onshow = function() {
- $i('reject_voucher_dialog_response').innerHTML = '';
- }
-
- reject_voucher_dialog.add = function() {
- // sending...
- $i('reject_voucher_dialog_response').innerHTML = 'Processing...';
-
- $c_obj(make_doclist(this.doc.doctype, this.doc.name),'reject_voucher','', function(r,rt){
- if(r.message == 'Rejected'){
- $i('reject_voucher_dialog_response').innerHTML = 'Rejected';
- refresh_field('approval_status');
- hide_field(['update_voucher', 'approve', 'reject', 'calculate_total_amount']);
- reject_voucher_dialog.hide();
- var args = {
- type: 'Expense Claim Rejected',
- doctype: 'Expense Claim',
- contact_name: doc.employee_name,
- send_to: doc.email_id
- }
- cur_frm.cscript.notify(doc, args);
- }
- });
- }
- }
-
- if(!reject_voucher_dialog){
- set_reject_voucher_dialog();
- }
- reject_voucher_dialog.doc = doc;
- reject_voucher_dialog.cdt = cdt;
- reject_voucher_dialog.cdn = cdn;
- reject_voucher_dialog.show();
- refresh_field('expense_voucher_details');
- doc.__unsaved = 0;
- cur_frm.refresh_header();
- }else{
- msgprint("Expense Claim can be rejected by Approver only");
- }
-}
-
-//update follow up
-//=================================================================================
-cur_frm.cscript.update_voucher = function(doc){
-
- $c_obj(make_doclist(doc.doctype, doc.name),'update_voucher','',function(r, rt){
- refresh_field('expense_voucher_details');
- doc.__unsaved = 0;
- cur_frm.refresh_header();
- });
-}
-
cur_frm.cscript.on_submit = function(doc, cdt, cdn) {
- if(cint(wn.boot.notification_settings.expense_claim)) {
+ if(cint(wn.boot.notification_settings && wn.boot.notification_settings.expense_claim)) {
cur_frm.email_doc(wn.boot.notification_settings.expense_claim_message);
}
-}
-
-cur_frm.fields_dict.employee.get_query = erpnext.utils.employee_query;
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/hr/doctype/expense_claim/expense_claim.py b/hr/doctype/expense_claim/expense_claim.py
index 0bfc318..b5fddda 100644
--- a/hr/doctype/expense_claim/expense_claim.py
+++ b/hr/doctype/expense_claim/expense_claim.py
@@ -17,86 +17,27 @@
from __future__ import unicode_literals
import webnotes
-from webnotes.utils import add_days, cstr
-from webnotes.model import db_exists
-from webnotes.model.wrapper import getlist, copy_doclist
-from webnotes.model.code import get_obj
+from webnotes.utils import add_days
+from webnotes.model.wrapper import getlist
from webnotes import form, msgprint
sql = webnotes.conn.sql
-
-
class DocType:
def __init__(self, doc, doclist=[]):
self.doc = doc
self.doclist = doclist
- def get_employee_name(self):
- emp_dtl = sql("select employee_name,company_email from `tabEmployee` where name=%s", self.doc.employee)
- emp_nm = emp_dtl and emp_dtl[0][0] or ''
- self.doc.employee_name = emp_nm
- self.doc.email_id = emp_dtl and emp_dtl[0][1] or ''
-
- return cstr(emp_nm)
-
- def get_approver_lst(self):
- approver_lst =[]
- approver_lst1 = get_obj('Authorization Control').get_approver_name(self.doc.doctype,0,self)
- if approver_lst1:
- approver_lst=approver_lst1
- else:
- approver_lst = [x[0] for x in sql("select distinct name from `tabProfile` where enabled=1 and name!='Administrator' and name!='Guest' and docstatus!=2")]
- return approver_lst
-
- def set_approver(self):
- ret={}
- approver_lst =[]
- emp_nm = self.get_employee_name()
- approver_lst = self.get_approver_lst()
- ret = {'app_lst':"\n" + "\n".join(approver_lst), 'emp_nm':cstr(emp_nm)}
- return ret
-
- def update_voucher(self):
- sql("delete from `tabExpense Claim Detail` where parent = '%s'"%self.doc.name)
- for d in getlist(self.doclist, 'expense_voucher_details'):
- if not d.expense_type or not d.claim_amount:
- msgprint("Please remove the extra blank row added")
- raise Exception
- d.save(1)
- if self.doc.total_sanctioned_amount:
- webnotes.conn.set(self.doc,'total_sanctioned_amount',self.doc.total_sanctioned_amount)
- if self.doc.remark:
- webnotes.conn.set(self.doc, 'remark', self.doc.remark)
-
- def approve_voucher(self):
- missing_count = 0
- for d in getlist(self.doclist, 'expense_voucher_details'):
- if not d.sanctioned_amount:
- missing_count += 1
- if missing_count == len(getlist(self.doclist, 'expense_voucher_details')):
- msgprint("Please add 'Sanctioned Amount' for atleast one expense")
- return cstr('Incomplete')
-
- if not self.doc.total_sanctioned_amount:
- msgprint("Please calculate total sanctioned amount using button 'Calculate Total Amount'")
- return cstr('No Amount')
- self.update_voucher()
-
- webnotes.conn.set(self.doc, 'approval_status', 'Approved')
- # on approval notification
- #get_obj('Notification Control').notify_contact('Expense Claim Approved', self.doc.doctype, self.doc.name, self.doc.email_id, self.doc.employee_name)
-
- return cstr('Approved')
-
- def reject_voucher(self):
-
- if self.doc.remark:
- webnotes.conn.set(self.doc, 'remark', self.doc.remark)
- webnotes.conn.set(self.doc, 'approval_status', 'Rejected')
-
- return cstr('Rejected')
-
+ def validate(self):
+ if self.doc.exp_approver == self.doc.owner:
+ webnotes.msgprint("""Self Approval is not allowed.""", raise_exception=1)
+ self.validate_fiscal_year()
+ self.validate_exp_details()
+
+ def on_submit(self):
+ if self.doc.approval_status=="Draft":
+ webnotes.msgprint("""Please set Approval Status to 'Approved' or 'Rejected' before submitting""",
+ raise_exception=1)
def validate_fiscal_year(self):
fy=sql("select year_start_date from `tabFiscal Year` where name='%s'"%self.doc.fiscal_year)
@@ -105,33 +46,16 @@
if str(self.doc.posting_date) < str(ysd) or str(self.doc.posting_date) > str(yed):
msgprint("Posting Date is not within the Fiscal Year selected")
raise Exception
-
- def validate(self):
- self.validate_fiscal_year()
-
- def on_update(self):
- webnotes.conn.set(self.doc, 'approval_status', 'Draft')
-
+
def validate_exp_details(self):
if not getlist(self.doclist, 'expense_voucher_details'):
msgprint("Please add expense voucher details")
raise Exception
- if not self.doc.total_claimed_amount:
- msgprint("Please calculate Total Claimed Amount")
- raise Exception
-
- if not self.doc.exp_approver:
- msgprint("Please select Expense Claim approver")
- raise Exception
-
- def on_submit(self):
- self.validate_exp_details()
- webnotes.conn.set(self.doc, 'approval_status', 'Submitted')
-
- def on_cancel(self):
- webnotes.conn.set(self.doc, 'approval_status', 'Cancelled')
-
- def get_formatted_message(self, args):
- """ get formatted message for auto notification"""
- return get_obj('Notification Control').get_formatted_message(args)
+@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/expense_claim/expense_claim.txt b/hr/doctype/expense_claim/expense_claim.txt
index 34ed31c..f42e2dd 100644
--- a/hr/doctype/expense_claim/expense_claim.txt
+++ b/hr/doctype/expense_claim/expense_claim.txt
@@ -1,390 +1,271 @@
-# DocType, Expense Claim
[
-
- # These values are common in all dictionaries
- {
- 'creation': '2012-03-27 14:35:56',
- 'docstatus': 0,
- 'modified': '2012-03-27 14:45:48',
- 'modified_by': u'Administrator',
- 'owner': u'harshada@webnotestech.com'
- },
-
- # These values are common for all DocType
- {
- '_last_update': u'1308808105',
- 'autoname': u'EXP.######',
- 'colour': u'White:FFF',
- 'default_print_format': u'Standard',
- 'doctype': 'DocType',
- 'is_submittable': 1,
- 'module': u'HR',
- 'name': '__common__',
- 'search_fields': u'approval_status,employee,employee_name',
- 'section_style': u'Simple',
- 'server_code_error': u' ',
- 'show_in_menu': 0,
- 'subject': u'From %(employee_name)s for %(total_claimed_amount)s (claimed)',
- 'tag_fields': u'approval_status',
- 'version': 135
- },
-
- # These values are common for all DocField
- {
- 'doctype': u'DocField',
- 'name': '__common__',
- 'parent': u'Expense Claim',
- 'parentfield': u'fields',
- 'parenttype': u'DocType'
- },
-
- # These values are common for all DocPerm
- {
- 'doctype': u'DocPerm',
- 'name': '__common__',
- 'parent': u'Expense Claim',
- 'parentfield': u'permissions',
- 'parenttype': u'DocType',
- 'read': 1
- },
-
- # DocType, Expense Claim
- {
- 'doctype': 'DocType',
- 'name': u'Expense Claim'
- },
-
- # DocPerm
- {
- 'doctype': u'DocPerm',
- 'permlevel': 1,
- 'role': u'All'
- },
-
- # DocPerm
- {
- 'amend': 1,
- 'cancel': 1,
- 'create': 1,
- 'doctype': u'DocPerm',
- 'match': u'owner',
- 'permlevel': 0,
- 'submit': 1,
- 'write': 1
- },
-
- # DocPerm
- {
- 'amend': 1,
- 'cancel': 1,
- 'create': 1,
- 'doctype': u'DocPerm',
- 'permlevel': 0,
- 'role': u'HR Manager',
- 'submit': 1,
- 'write': 1
- },
-
- # DocPerm
- {
- 'amend': 1,
- 'cancel': 1,
- 'create': 1,
- 'doctype': u'DocPerm',
- 'permlevel': 0,
- 'role': u'HR User',
- 'submit': 1,
- 'write': 1
- },
-
- # DocField
- {
- 'doctype': u'DocField',
- 'fieldname': u'details',
- 'fieldtype': u'Section Break',
- 'label': u'Details',
- 'oldfieldtype': u'Section Break',
- 'permlevel': 0
- },
-
- # DocField
- {
- 'colour': u'White:FFF',
- 'default': u'Draft',
- 'doctype': u'DocField',
- 'fieldname': u'approval_status',
- 'fieldtype': u'Select',
- 'in_filter': 1,
- 'label': u'Approval Status',
- 'no_copy': 1,
- 'oldfieldname': u'approval_status',
- 'oldfieldtype': u'Select',
- 'options': u'\nDraft\nSubmitted\nApproved \nRejected\nCancelled',
- 'permlevel': 1,
- 'search_index': 1
- },
-
- # DocField
- {
- 'colour': u'White:FFF',
- 'doctype': u'DocField',
- 'fieldname': u'employee',
- 'fieldtype': u'Link',
- 'in_filter': 1,
- 'label': u'From Employee',
- 'oldfieldname': u'employee',
- 'oldfieldtype': u'Link',
- 'options': u'Employee',
- 'permlevel': 0,
- 'reqd': 1,
- 'search_index': 1,
- 'trigger': u'Client'
- },
-
- # DocField
- {
- 'doctype': u'DocField',
- 'fieldname': u'employee_name',
- 'fieldtype': u'Data',
- 'in_filter': 1,
- 'label': u'Employee Name',
- 'oldfieldname': u'employee_name',
- 'oldfieldtype': u'Data',
- 'permlevel': 1,
- 'search_index': 0,
- 'width': u'150px'
- },
-
- # DocField
- {
- 'doctype': u'DocField',
- 'fieldname': u'fiscal_year',
- 'fieldtype': u'Select',
- 'in_filter': 1,
- 'label': u'Fiscal Year',
- 'oldfieldname': u'fiscal_year',
- 'oldfieldtype': u'Select',
- 'options': u'link:Fiscal Year',
- 'permlevel': 0,
- 'reqd': 1
- },
-
- # DocField
- {
- 'doctype': u'DocField',
- 'fieldname': u'company',
- 'fieldtype': u'Select',
- 'in_filter': 1,
- 'label': u'Company',
- 'oldfieldname': u'company',
- 'oldfieldtype': u'Link',
- 'options': u'link:Company',
- 'permlevel': 0,
- 'reqd': 1
- },
-
- # DocField
- {
- 'doctype': u'DocField',
- 'fieldname': u'column_break0',
- 'fieldtype': u'Column Break',
- 'oldfieldtype': u'Column Break',
- 'permlevel': 0,
- 'width': u'50%'
- },
-
- # DocField
- {
- 'doctype': u'DocField',
- 'fieldname': u'posting_date',
- 'fieldtype': u'Date',
- 'in_filter': 1,
- 'label': u'Posting Date',
- 'oldfieldname': u'posting_date',
- 'oldfieldtype': u'Date',
- 'permlevel': 0,
- 'reqd': 1
- },
-
- # DocField
- {
- 'doctype': u'DocField',
- 'fieldname': u'exp_approver',
- 'fieldtype': u'Select',
- 'label': u'Approver',
- 'oldfieldname': u'exp_approver',
- 'oldfieldtype': u'Select',
- 'permlevel': 0,
- 'width': u'160px'
- },
-
- # DocField
- {
- 'allow_on_submit': 1,
- 'colour': u'White:FFF',
- 'doctype': u'DocField',
- 'fieldname': u'remark',
- 'fieldtype': u'Small Text',
- 'label': u'Remark',
- 'no_copy': 1,
- 'oldfieldname': u'remark',
- 'oldfieldtype': u'Small Text',
- 'permlevel': 0
- },
-
- # DocField
- {
- 'colour': u'White:FFF',
- 'doctype': u'DocField',
- 'fieldname': u'amended_from',
- 'fieldtype': u'Data',
- 'label': u'Amended From',
- 'no_copy': 1,
- 'oldfieldname': u'amended_from',
- 'oldfieldtype': u'Data',
- 'permlevel': 1,
- 'print_hide': 1,
- 'report_hide': 1,
- 'width': u'160px'
- },
-
- # DocField
- {
- 'colour': u'White:FFF',
- 'doctype': u'DocField',
- 'fieldname': u'amendment_date',
- 'fieldtype': u'Date',
- 'label': u'Amendment Date',
- 'no_copy': 1,
- 'oldfieldname': u'amendment_date',
- 'oldfieldtype': u'Date',
- 'permlevel': 1,
- 'print_hide': 1,
- 'report_hide': 1,
- 'width': u'160px'
- },
-
- # DocField
- {
- 'allow_on_submit': 1,
- 'doctype': u'DocField',
- 'fieldname': u'approve',
- 'fieldtype': u'Button',
- 'hidden': 1,
- 'label': u'Approve',
- 'oldfieldtype': u'Button',
- 'permlevel': 0,
- 'print_hide': 1,
- 'trigger': u'Client'
- },
-
- # DocField
- {
- 'allow_on_submit': 1,
- 'doctype': u'DocField',
- 'fieldname': u'reject',
- 'fieldtype': u'Button',
- 'hidden': 1,
- 'label': u'Reject',
- 'oldfieldtype': u'Button',
- 'permlevel': 0,
- 'print_hide': 1,
- 'trigger': u'Client'
- },
-
- # DocField
- {
- 'doctype': u'DocField',
- 'fieldname': u'expense_details',
- 'fieldtype': u'Section Break',
- 'label': u'Expense Details',
- 'oldfieldtype': u'Section Break',
- 'permlevel': 0
- },
-
- # DocField
- {
- 'allow_on_submit': 1,
- 'colour': u'White:FFF',
- 'doctype': u'DocField',
- 'fieldname': u'calculate_total_amount',
- 'fieldtype': u'Button',
- 'label': u'Calculate Total Amount',
- 'oldfieldtype': u'Button',
- 'permlevel': 0,
- 'print_hide': 1,
- 'report_hide': 1,
- 'trigger': u'Client'
- },
-
- # DocField
- {
- 'colour': u'White:FFF',
- 'doctype': u'DocField',
- 'fieldname': u'total_claimed_amount',
- 'fieldtype': u'Currency',
- 'in_filter': 0,
- 'label': u'Total Claimed Amount',
- 'no_copy': 1,
- 'oldfieldname': u'total_claimed_amount',
- 'oldfieldtype': u'Currency',
- 'permlevel': 1,
- 'reqd': 0,
- 'width': u'160px'
- },
-
- # DocField
- {
- 'colour': u'White:FFF',
- 'doctype': u'DocField',
- 'fieldname': u'total_sanctioned_amount',
- 'fieldtype': u'Currency',
- 'in_filter': 0,
- 'label': u'Total Sanctioned Amount',
- 'no_copy': 1,
- 'oldfieldname': u'total_sanctioned_amount',
- 'oldfieldtype': u'Currency',
- 'permlevel': 1,
- 'width': u'160px'
- },
-
- # DocField
- {
- 'allow_on_submit': 1,
- 'doctype': u'DocField',
- 'fieldname': u'update_voucher',
- 'fieldtype': u'Button',
- 'hidden': 1,
- 'label': u'Update Voucher',
- 'oldfieldtype': u'Button',
- 'permlevel': 0,
- 'print_hide': 1,
- 'trigger': u'Client'
- },
-
- # DocField
- {
- 'allow_on_submit': 1,
- 'doctype': u'DocField',
- 'fieldname': u'expense_voucher_details',
- 'fieldtype': u'Table',
- 'label': u'Expense Claim Details',
- 'oldfieldname': u'expense_voucher_details',
- 'oldfieldtype': u'Table',
- 'options': u'Expense Claim Detail',
- 'permlevel': 0
- },
-
- # DocField
- {
- 'doctype': u'DocField',
- 'fieldname': u'email_id',
- 'fieldtype': u'Data',
- 'hidden': 1,
- 'label': u'Employees Email Id',
- 'oldfieldname': u'email_id',
- 'oldfieldtype': u'Data',
- 'permlevel': 0,
- 'print_hide': 1
- }
+ {
+ "owner": "harshada@webnotestech.com",
+ "docstatus": 0,
+ "creation": "2012-12-05 14:11:53",
+ "modified_by": "Administrator",
+ "modified": "2012-12-05 14:22:27"
+ },
+ {
+ "is_submittable": 1,
+ "autoname": "EXP.######",
+ "name": "__common__",
+ "default_print_format": "Standard",
+ "search_fields": "approval_status,employee,employee_name",
+ "module": "HR",
+ "doctype": "DocType"
+ },
+ {
+ "name": "__common__",
+ "parent": "Expense Claim",
+ "doctype": "DocField",
+ "parenttype": "DocType",
+ "parentfield": "fields"
+ },
+ {
+ "name": "__common__",
+ "parent": "Expense Claim",
+ "read": 1,
+ "doctype": "DocPerm",
+ "parenttype": "DocType",
+ "parentfield": "permissions"
+ },
+ {
+ "name": "Expense Claim",
+ "doctype": "DocType"
+ },
+ {
+ "oldfieldtype": "Section Break",
+ "doctype": "DocField",
+ "label": "Details",
+ "fieldname": "details",
+ "fieldtype": "Section Break",
+ "permlevel": 0
+ },
+ {
+ "permlevel": 1,
+ "no_copy": 1,
+ "oldfieldtype": "Select",
+ "colour": "White:FFF",
+ "doctype": "DocField",
+ "label": "Approval Status",
+ "oldfieldname": "approval_status",
+ "default": "Draft",
+ "fieldname": "approval_status",
+ "fieldtype": "Select",
+ "search_index": 1,
+ "options": "\nDraft\nApproved\nRejected",
+ "in_filter": 1
+ },
+ {
+ "oldfieldtype": "Select",
+ "doctype": "DocField",
+ "label": "Approver",
+ "oldfieldname": "exp_approver",
+ "width": "160px",
+ "fieldname": "exp_approver",
+ "fieldtype": "Select",
+ "permlevel": 0
+ },
+ {
+ "oldfieldtype": "Date",
+ "doctype": "DocField",
+ "label": "Posting Date",
+ "oldfieldname": "posting_date",
+ "fieldname": "posting_date",
+ "fieldtype": "Date",
+ "reqd": 1,
+ "permlevel": 0,
+ "in_filter": 1
+ },
+ {
+ "oldfieldtype": "Column Break",
+ "doctype": "DocField",
+ "width": "50%",
+ "fieldname": "column_break0",
+ "fieldtype": "Column Break",
+ "permlevel": 0
+ },
+ {
+ "oldfieldtype": "Link",
+ "colour": "White:FFF",
+ "doctype": "DocField",
+ "label": "From Employee",
+ "oldfieldname": "employee",
+ "permlevel": 0,
+ "trigger": "Client",
+ "fieldname": "employee",
+ "fieldtype": "Link",
+ "search_index": 1,
+ "reqd": 1,
+ "options": "Employee",
+ "in_filter": 1
+ },
+ {
+ "oldfieldtype": "Data",
+ "doctype": "DocField",
+ "label": "Employee Name",
+ "oldfieldname": "employee_name",
+ "width": "150px",
+ "fieldname": "employee_name",
+ "fieldtype": "Data",
+ "search_index": 0,
+ "permlevel": 1,
+ "in_filter": 1
+ },
+ {
+ "no_copy": 1,
+ "oldfieldtype": "Small Text",
+ "colour": "White:FFF",
+ "allow_on_submit": 0,
+ "doctype": "DocField",
+ "label": "Remark",
+ "oldfieldname": "remark",
+ "fieldname": "remark",
+ "fieldtype": "Small Text",
+ "permlevel": 0
+ },
+ {
+ "print_hide": 1,
+ "no_copy": 1,
+ "oldfieldtype": "Data",
+ "colour": "White:FFF",
+ "doctype": "DocField",
+ "label": "Amended From",
+ "oldfieldname": "amended_from",
+ "width": "160px",
+ "fieldname": "amended_from",
+ "fieldtype": "Data",
+ "permlevel": 1,
+ "report_hide": 1
+ },
+ {
+ "print_hide": 1,
+ "no_copy": 1,
+ "oldfieldtype": "Date",
+ "colour": "White:FFF",
+ "doctype": "DocField",
+ "label": "Amendment Date",
+ "oldfieldname": "amendment_date",
+ "width": "160px",
+ "fieldname": "amendment_date",
+ "fieldtype": "Date",
+ "permlevel": 1,
+ "report_hide": 1
+ },
+ {
+ "oldfieldtype": "Section Break",
+ "doctype": "DocField",
+ "label": "Expense Details",
+ "fieldname": "expense_details",
+ "fieldtype": "Section Break",
+ "permlevel": 0
+ },
+ {
+ "oldfieldtype": "Table",
+ "allow_on_submit": 0,
+ "doctype": "DocField",
+ "label": "Expense Claim Details",
+ "oldfieldname": "expense_voucher_details",
+ "options": "Expense Claim Detail",
+ "fieldname": "expense_voucher_details",
+ "fieldtype": "Table",
+ "permlevel": 0
+ },
+ {
+ "no_copy": 1,
+ "oldfieldtype": "Currency",
+ "colour": "White:FFF",
+ "doctype": "DocField",
+ "label": "Total Claimed Amount",
+ "oldfieldname": "total_claimed_amount",
+ "width": "160px",
+ "fieldname": "total_claimed_amount",
+ "fieldtype": "Currency",
+ "reqd": 0,
+ "permlevel": 1,
+ "in_filter": 0
+ },
+ {
+ "no_copy": 1,
+ "oldfieldtype": "Currency",
+ "colour": "White:FFF",
+ "doctype": "DocField",
+ "label": "Total Sanctioned Amount",
+ "oldfieldname": "total_sanctioned_amount",
+ "width": "160px",
+ "fieldname": "total_sanctioned_amount",
+ "fieldtype": "Currency",
+ "permlevel": 1,
+ "in_filter": 0
+ },
+ {
+ "print_hide": 1,
+ "oldfieldtype": "Data",
+ "doctype": "DocField",
+ "label": "Employees Email Id",
+ "oldfieldname": "email_id",
+ "fieldname": "email_id",
+ "fieldtype": "Data",
+ "hidden": 1,
+ "permlevel": 0
+ },
+ {
+ "oldfieldtype": "Select",
+ "doctype": "DocField",
+ "label": "Fiscal Year",
+ "oldfieldname": "fiscal_year",
+ "options": "link:Fiscal Year",
+ "fieldname": "fiscal_year",
+ "fieldtype": "Select",
+ "reqd": 1,
+ "permlevel": 0,
+ "in_filter": 1
+ },
+ {
+ "oldfieldtype": "Link",
+ "doctype": "DocField",
+ "label": "Company",
+ "oldfieldname": "company",
+ "options": "link:Company",
+ "fieldname": "company",
+ "fieldtype": "Select",
+ "reqd": 1,
+ "permlevel": 0,
+ "in_filter": 1
+ },
+ {
+ "create": 1,
+ "doctype": "DocPerm",
+ "write": 1,
+ "role": "Employee",
+ "permlevel": 0,
+ "match": "owner"
+ },
+ {
+ "amend": 1,
+ "create": 1,
+ "doctype": "DocPerm",
+ "submit": 1,
+ "write": 1,
+ "cancel": 1,
+ "role": "Expense Approver",
+ "permlevel": 0,
+ "match": "exp_approver:user"
+ },
+ {
+ "amend": 1,
+ "create": 1,
+ "doctype": "DocPerm",
+ "submit": 1,
+ "write": 1,
+ "cancel": 1,
+ "role": "HR User",
+ "permlevel": 0
+ },
+ {
+ "doctype": "DocPerm",
+ "role": "All",
+ "permlevel": 1
+ }
]
\ No newline at end of file
diff --git a/hr/doctype/expense_claim_detail/expense_claim_detail.txt b/hr/doctype/expense_claim_detail/expense_claim_detail.txt
index a11ce5c..f28811f 100644
--- a/hr/doctype/expense_claim_detail/expense_claim_detail.txt
+++ b/hr/doctype/expense_claim_detail/expense_claim_detail.txt
@@ -1,103 +1,80 @@
-# DocType, Expense Claim Detail
[
-
- # These values are common in all dictionaries
- {
- 'creation': '2012-03-27 14:35:56',
- 'docstatus': 0,
- 'modified': '2012-03-27 14:35:56',
- 'modified_by': u'Administrator',
- 'owner': u'harshada@webnotestech.com'
- },
-
- # These values are common for all DocType
- {
- 'colour': u'White:FFF',
- 'doctype': 'DocType',
- 'istable': 1,
- 'module': u'HR',
- 'name': '__common__',
- 'section_style': u'Simple',
- 'server_code_error': u' ',
- 'version': 5
- },
-
- # These values are common for all DocField
- {
- 'doctype': u'DocField',
- 'name': '__common__',
- 'parent': u'Expense Claim Detail',
- 'parentfield': u'fields',
- 'parenttype': u'DocType',
- 'permlevel': 0
- },
-
- # DocType, Expense Claim Detail
- {
- 'doctype': 'DocType',
- 'name': u'Expense Claim Detail'
- },
-
- # DocField
- {
- 'doctype': u'DocField',
- 'fieldname': u'expense_date',
- 'fieldtype': u'Date',
- 'label': u'Expense Date',
- 'oldfieldname': u'expense_date',
- 'oldfieldtype': u'Date',
- 'reqd': 0,
- 'width': u'150px'
- },
-
- # DocField
- {
- 'doctype': u'DocField',
- 'fieldname': u'expense_type',
- 'fieldtype': u'Link',
- 'label': u'Expense Claim Type',
- 'oldfieldname': u'expense_type',
- 'oldfieldtype': u'Link',
- 'options': u'Expense Claim Type',
- 'reqd': 1,
- 'width': u'150px'
- },
-
- # DocField
- {
- 'doctype': u'DocField',
- 'fieldname': u'description',
- 'fieldtype': u'Small Text',
- 'label': u'Description',
- 'oldfieldname': u'description',
- 'oldfieldtype': u'Small Text',
- 'width': u'300px'
- },
-
- # DocField
- {
- 'doctype': u'DocField',
- 'fieldname': u'claim_amount',
- 'fieldtype': u'Currency',
- 'label': u'Claim Amount',
- 'oldfieldname': u'claim_amount',
- 'oldfieldtype': u'Currency',
- 'reqd': 1,
- 'trigger': u'Client',
- 'width': u'150px'
- },
-
- # DocField
- {
- 'allow_on_submit': 1,
- 'doctype': u'DocField',
- 'fieldname': u'sanctioned_amount',
- 'fieldtype': u'Currency',
- 'label': u'Sanctioned Amount',
- 'no_copy': 1,
- 'oldfieldname': u'sanctioned_amount',
- 'oldfieldtype': u'Currency',
- 'trigger': u'Client',
- 'width': u'150px'
- }
+ {
+ "owner": "harshada@webnotestech.com",
+ "docstatus": 0,
+ "creation": "2012-07-03 13:30:39",
+ "modified_by": "Administrator",
+ "modified": "2012-12-05 14:22:03"
+ },
+ {
+ "istable": 1,
+ "name": "__common__",
+ "doctype": "DocType",
+ "module": "HR"
+ },
+ {
+ "name": "__common__",
+ "parent": "Expense Claim Detail",
+ "doctype": "DocField",
+ "parenttype": "DocType",
+ "permlevel": 0,
+ "parentfield": "fields"
+ },
+ {
+ "name": "Expense Claim Detail",
+ "doctype": "DocType"
+ },
+ {
+ "oldfieldtype": "Date",
+ "doctype": "DocField",
+ "label": "Expense Date",
+ "oldfieldname": "expense_date",
+ "width": "150px",
+ "fieldname": "expense_date",
+ "fieldtype": "Date",
+ "reqd": 0
+ },
+ {
+ "oldfieldtype": "Link",
+ "doctype": "DocField",
+ "label": "Expense Claim Type",
+ "oldfieldname": "expense_type",
+ "width": "150px",
+ "fieldname": "expense_type",
+ "fieldtype": "Select",
+ "reqd": 1,
+ "options": "link:Expense Claim Type"
+ },
+ {
+ "oldfieldtype": "Small Text",
+ "doctype": "DocField",
+ "label": "Description",
+ "oldfieldname": "description",
+ "width": "300px",
+ "fieldname": "description",
+ "fieldtype": "Small Text"
+ },
+ {
+ "oldfieldtype": "Currency",
+ "doctype": "DocField",
+ "label": "Claim Amount",
+ "oldfieldname": "claim_amount",
+ "width": "150px",
+ "trigger": "Client",
+ "fieldname": "claim_amount",
+ "fieldtype": "Currency",
+ "reqd": 1
+ },
+ {
+ "no_copy": 1,
+ "oldfieldtype": "Currency",
+ "allow_on_submit": 0,
+ "doctype": "DocField",
+ "label": "Sanctioned Amount",
+ "oldfieldname": "sanctioned_amount",
+ "width": "150px",
+ "trigger": "Client",
+ "fieldname": "sanctioned_amount",
+ "fieldtype": "Currency"
+ }
]
\ No newline at end of file
diff --git a/hr/doctype/leave_application/leave_application.js b/hr/doctype/leave_application/leave_application.js
index 00df476..2d71aac 100755
--- a/hr/doctype/leave_application/leave_application.js
+++ b/hr/doctype/leave_application/leave_application.js
@@ -8,14 +8,23 @@
//
// 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
+// 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/>.
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+cur_frm.add_fetch('employee','employee_name','employee_name');
cur_frm.cscript.onload = function(doc, dt, dn) {
- if(!doc.posting_date) set_multiple(dt,dn,{posting_date:get_today()});
+ if(!doc.posting_date)
+ set_multiple(dt,dn,{posting_date:get_today()});
+ cur_frm.call({
+ method:"get_approver_list",
+ callback: function(r) {
+ cur_frm.set_df_property("leave_approver", "options", r.message);
+ }
+ });
}
cur_frm.cscript.refresh = function(doc, dt, dn) {
@@ -23,14 +32,16 @@
if(doc.__islocal && !in_list(user_roles, "HR User")) {
cur_frm.set_intro("Fill the form and save it")
} else {
- if(in_list(user_roles, "HR User")) {
- if(doc.status=="Open") {
- cur_frm.set_intro("Please Approve (and Submit) or Reject, or re-assign to applicant for further review.");
+ if(doc.status=="Open") {
+ if(user==doc.leave_approver) {
+ cur_frm.set_intro("You are the Leave Approver for this record. Please Update the 'Status' and Save");
+ cur_frm.toggle_enable("status", true);
+ } else {
+ cur_frm.set_intro("This Leave Application is pending approval. Only the Leave Apporver can update status.")
+ cur_frm.toggle_enable("status", false);
}
} else {
- if(doc.status=="Open") {
- cur_frm.set_intro("Leave application is pending approval.");
- } else if(doc.status=="Approved") {
+ if(doc.status=="Approved") {
cur_frm.set_intro("Leave application has been approved.");
} else if(doc.status=="Rejected") {
cur_frm.set_intro("Leave application has been rejected.");
@@ -38,61 +49,67 @@
}
}
- if(doc.status=="Approved" && doc.docstatus!=1) {
+ if(doc.status=="Approved" && doc.docstatus==0) {
cur_frm.savesubmit()
}
}
-cur_frm.add_fetch('employee','employee_name','employee_name');
-
cur_frm.cscript.employee = function (doc, dt, dn){
- get_leave_balance(doc, dt, dn);
+ get_leave_balance(doc, dt, dn);
}
cur_frm.cscript.fiscal_year = function (doc, dt, dn){
- get_leave_balance(doc, dt, dn);
+ get_leave_balance(doc, dt, dn);
}
cur_frm.cscript.leave_type = function (doc, dt, dn){
- get_leave_balance(doc, dt, dn);
+ get_leave_balance(doc, dt, dn);
}
cur_frm.cscript.half_day = function(doc, dt, dn) {
- if(doc.from_date) {
- set_multiple(dt,dn,{to_date:doc.from_date});
- calculate_total_days(doc, dt, dn);
- }
+ if(doc.from_date) {
+ set_multiple(dt,dn,{to_date:doc.from_date});
+ calculate_total_days(doc, dt, dn);
+ }
}
cur_frm.cscript.from_date = function(doc, dt, dn) {
- if(cint(doc.half_day) == 1){
- set_multiple(dt,dn,{to_date:doc.from_date});
- }
- calculate_total_days(doc, dt, dn);
+ if(cint(doc.half_day) == 1){
+ set_multiple(dt,dn,{to_date:doc.from_date});
+ }
+ calculate_total_days(doc, dt, dn);
}
cur_frm.cscript.to_date = function(doc, dt, dn) {
- if(cint(doc.half_day) == 1 && cstr(doc.from_date) && doc.from_date != doc.to_date){
- msgprint("To Date should be same as From Date for Half Day leave");
- set_multiple(dt,dn,{to_date:doc.from_date});
- }
- calculate_total_days(doc, dt, dn);
+ if(cint(doc.half_day) == 1 && cstr(doc.from_date) && doc.from_date != doc.to_date){
+ msgprint("To Date should be same as From Date for Half Day leave");
+ set_multiple(dt,dn,{to_date:doc.from_date});
+ }
+ calculate_total_days(doc, dt, dn);
}
-
+
get_leave_balance = function(doc, dt, dn) {
- if(doc.employee && doc.leave_type && doc.fiscal_year)
- get_server_fields('get_leave_balance', '','', doc, dt, dn, 1);
+ if(doc.employee && doc.leave_type && doc.fiscal_year) {
+ cur_frm.call({
+ method: "get_leave_balance",
+ args: {
+ employee: doc.employee,
+ fiscal_year: doc.fiscal_year,
+ leave_type: doc.leave_type
+ }
+ })
+ }
}
calculate_total_days = function(doc, dt, dn) {
- if(doc.from_date && doc.to_date){
- if(cint(doc.half_day) == 1) set_multiple(dt,dn,{total_leave_days:0.5});
- else{
- //d = new DateFn();
- //set_multiple(dt,dn,{total_leave_days:d.get_diff(d.str_to_obj(doc.to_date),d.str_to_obj(doc.from_date))+1});
- get_server_fields('get_total_leave_days', '', '', doc, dt, dn, 1);
- }
- }
+ if(doc.from_date && doc.to_date){
+ if(cint(doc.half_day) == 1) set_multiple(dt,dn,{total_leave_days:0.5});
+ else{
+ //d = new DateFn();
+ //set_multiple(dt,dn,{total_leave_days:d.get_diff(d.str_to_obj(doc.to_date),d.str_to_obj(doc.from_date))+1});
+ get_server_fields('get_total_leave_days', '', '', doc, dt, dn, 1);
+ }
+ }
}
cur_frm.fields_dict.employee.get_query = erpnext.utils.employee_query;
\ No newline at end of file
diff --git a/hr/doctype/leave_application/leave_application.py b/hr/doctype/leave_application/leave_application.py
index 91c9d8c..cdddb9f 100755
--- a/hr/doctype/leave_application/leave_application.py
+++ b/hr/doctype/leave_application/leave_application.py
@@ -30,14 +30,6 @@
self.doc = doc
self.doclist = doclist
- def get_leave_balance(self):
- leave_all = sql("select total_leaves_allocated from `tabLeave Allocation` where employee = '%s' and leave_type = '%s' and fiscal_year = '%s' and docstatus = 1" % (self.doc.employee, self.doc.leave_type, self.doc.fiscal_year))
- leave_all = leave_all and flt(leave_all[0][0]) or 0
- leave_app = sql("select SUM(total_leave_days) from `tabLeave Application` where employee = '%s' and leave_type = '%s' and fiscal_year = '%s' and docstatus = 1" % (self.doc.employee, self.doc.leave_type, self.doc.fiscal_year))
- leave_app = leave_app and flt(leave_app[0][0]) or 0
- ret = {'leave_balance':leave_all - leave_app}
- return ret
-
def get_holidays(self):
"""
get total holidays
@@ -71,7 +63,8 @@
def validate_balance_leaves(self):
if self.doc.from_date and self.doc.to_date and not self.is_lwp():
- bal = self.get_leave_balance()
+ bal = get_leave_balance(self.doc.leave_type, self.doc.employee,
+ self.doc.fiscal_year)["leave_balance"]
tot_leaves = self.get_total_leave_days()
bal, tot_leaves = bal, tot_leaves
webnotes.conn.set(self.doc,'leave_balance',flt(bal['leave_balance']))
@@ -98,6 +91,9 @@
raise Exception
def validate(self):
+ if self.doc.leave_approver == self.doc.owner:
+ webnotes.msgprint("""Self Approval is not allowed.""", raise_exception=1)
+
self.validate_to_date()
self.validate_balance_leaves()
self.validate_leave_overlap()
@@ -107,3 +103,30 @@
if self.doc.status != "Approved":
webnotes.msgprint("""Only Approved Leave Applications can be Submitted.""",
raise_exception=True)
+
+@webnotes.whitelist()
+def get_leave_balance(employee, leave_type, fiscal_year):
+ leave_all = webnotes.conn.sql("""select total_leaves_allocated
+ from `tabLeave Allocation` where employee = %s and leave_type = %s
+ and fiscal_year = %s and docstatus = 1""", (employee,
+ leave_type, fiscal_year))
+
+ leave_all = leave_all and flt(leave_all[0][0]) or 0
+
+ leave_app = webnotes.conn.sql("""select SUM(total_leave_days)
+ from `tabLeave Application`
+ where employee = %s and leave_type = %s and fiscal_year = %s
+ and docstatus = 1""", (employee, leave_type, fiscal_year))
+ leave_app = leave_app and flt(leave_app[0][0]) or 0
+
+ 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
diff --git a/hr/doctype/leave_application/leave_application.txt b/hr/doctype/leave_application/leave_application.txt
index 6a33df6..b205d18 100644
--- a/hr/doctype/leave_application/leave_application.txt
+++ b/hr/doctype/leave_application/leave_application.txt
@@ -2,9 +2,9 @@
{
"owner": "Administrator",
"docstatus": 0,
- "creation": "2012-11-02 17:16:54",
+ "creation": "2012-12-05 14:11:53",
"modified_by": "Administrator",
- "modified": "2012-11-30 12:17:27"
+ "modified": "2012-12-05 17:38:26"
},
{
"is_submittable": 1,
@@ -45,6 +45,15 @@
"permlevel": 3
},
{
+ "description": "Leave can be approved by users with Role, \"Leave Approver\"",
+ "colour": "White:FFF",
+ "doctype": "DocField",
+ "label": "Leave Approver",
+ "fieldname": "leave_approver",
+ "fieldtype": "Select",
+ "permlevel": 0
+ },
+ {
"search_index": 1,
"doctype": "DocField",
"label": "Leave Type",
@@ -216,12 +225,29 @@
"permlevel": 0
},
{
+ "amend": 1,
+ "create": 1,
+ "doctype": "DocPerm",
+ "submit": 1,
+ "write": 1,
+ "role": "Leave Approver",
+ "cancel": 1,
+ "permlevel": 0,
+ "match": "leave_approver:user"
+ },
+ {
+ "doctype": "DocPerm",
+ "write": 1,
+ "role": "HR User",
+ "permlevel": 2
+ },
+ {
"amend": 0,
"create": 0,
"doctype": "DocPerm",
"submit": 0,
"write": 1,
- "role": "HR User",
+ "role": "Leave Approver",
"cancel": 0,
"permlevel": 2
},
@@ -229,11 +255,5 @@
"doctype": "DocPerm",
"role": "All",
"permlevel": 3
- },
- {
- "doctype": "DocPerm",
- "write": 1,
- "role": "HR User",
- "permlevel": 3
}
]
\ No newline at end of file
diff --git a/patches/december_2012/expense_leave_reload.py b/patches/december_2012/expense_leave_reload.py
new file mode 100644
index 0000000..06c67e6
--- /dev/null
+++ b/patches/december_2012/expense_leave_reload.py
@@ -0,0 +1,26 @@
+import webnotes
+
+def execute():
+ # new roles
+ roles = [r[0] for r in webnotes.conn.sql("""select name from tabRole""")]
+ if not "Leave Approver" in roles:
+ webnotes.model_wrapper([{"doctype":"Role", "role_name":"Leave Approver",
+ "__islocal":1, "module":"HR"}]).save()
+ if not "Expense Approver" in roles:
+ webnotes.model_wrapper([{"doctype":"Role", "role_name":"Expense Approver",
+ "__islocal":1, "module":"HR"}]).save()
+
+ # reload
+ webnotes.clear_perms("Leave Application")
+ webnotes.reload_doc("hr", "doctype", "leave_application")
+
+ webnotes.clear_perms("Expense Claim")
+ webnotes.reload_doc("hr", "doctype", "expense_claim")
+
+ # remove extra space in Approved Expense Vouchers
+ webnotes.conn.sql("""update `tabExpense Claim` set approval_status='Approved'
+ where approval_status='Approved '""")
+
+ webnotes.conn.commit()
+ for t in ['__CacheItem', '__SessionCache', 'tabSupport Ticket Response']:
+ webnotes.conn.sql("drop table if exists `%s`" % t)
\ No newline at end of file
diff --git a/patches/december_2012/reload_debtors_creditors_ledger.py b/patches/december_2012/reload_debtors_creditors_ledger.py
new file mode 100644
index 0000000..7f88a6f
--- /dev/null
+++ b/patches/december_2012/reload_debtors_creditors_ledger.py
@@ -0,0 +1,5 @@
+def execute():
+ import webnotes
+ from webnotes.modules import reload_doc
+ reload_doc("accounts", "search_criteria", "debtors_ledger")
+ reload_doc("accounts", "search_criteria", "creditors_ledger")
\ No newline at end of file
diff --git a/patches/patch_list.py b/patches/patch_list.py
index ce03fb2..38847eb 100644
--- a/patches/patch_list.py
+++ b/patches/patch_list.py
@@ -711,10 +711,18 @@
},
{
'patch_module': 'patches.december_2012',
+ 'patch_file': 'expense_leave_reload',
+ },
+ {
+ 'patch_module': 'patches.december_2012',
'patch_file': 'repost_ordered_qty',
},
{
'patch_module': 'patches.december_2012',
'patch_file': 'repost_projected_qty',
},
+ {
+ 'patch_module': 'patches.december_2012',
+ 'patch_file': 'reload_debtors_creditors_ledger',
+ },
]
\ No newline at end of file
diff --git a/stock/doctype/packing_slip/packing_slip.js b/stock/doctype/packing_slip/packing_slip.js
index d3cf9be..7e26a09 100644
--- a/stock/doctype/packing_slip/packing_slip.js
+++ b/stock/doctype/packing_slip/packing_slip.js
@@ -43,8 +43,8 @@
}
-cur_frm.cscript.onload = function(doc, cdt, cdn) {
- if(doc.delivery_note) {
+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[0].net_weight) && cstr(ps_detail[0].weight_uom))) {
cur_frm.cscript.update_item_details(doc);
diff --git a/stock/doctype/packing_slip/packing_slip.py b/stock/doctype/packing_slip/packing_slip.py
index 9e544b6..7ef7d36 100644
--- a/stock/doctype/packing_slip/packing_slip.py
+++ b/stock/doctype/packing_slip/packing_slip.py
@@ -16,7 +16,7 @@
from __future__ import unicode_literals
import webnotes
-from webnotes.utils import flt, cint
+from webnotes.utils import flt, cint, now
class DocType:
def __init__(self, d, dl):
@@ -56,6 +56,15 @@
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)
+ 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.'",
+ raise_exception=1)
+
+
res = webnotes.conn.sql("""\
SELECT name FROM `tabPacking Slip`
WHERE delivery_note = %(delivery_note)s AND docstatus = 1 AND
@@ -92,16 +101,24 @@
item_codes = ", ".join([('"' + d.item_code + '"') for d in
self.doclist])
+ items = [d.item_code for d in self.doclist.get({"parentfield": "item_details"})]
+
if not item_codes: webnotes.msgprint("No Items to Pack",
raise_exception=1)
-
- res = webnotes.conn.sql("""\
- SELECT item_code, IFNULL(SUM(qty), 0) as qty, IFNULL(packed_qty, 0) as packed_qty, stock_uom
- FROM `tabDelivery Note Item`
- WHERE parent = "%s" AND item_code IN (%s)
- GROUP BY item_code""" % (self.doc.delivery_note, item_codes),
- as_dict=1)
-
+
+ # 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
+ 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, debug=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
@@ -148,28 +165,29 @@
dn_details, ps_item_qty, no_of_cases = self.get_details_for_packing()
for item in dn_details:
- if event=='submit':
- new_packed_qty = flt(item['packed_qty']) + (flt(ps_item_qty[item['item_code']]) * no_of_cases)
-
- elif event=='cancel':
- new_packed_qty = flt(item['packed_qty']) - (flt(ps_item_qty[item['item_code']]) * no_of_cases)
-
+ 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)
-
+
+ delivery_note_item = webnotes.conn.get_value("Delivery Note Item", {
+ "parent": self.doc.delivery_note, "item_code": item["item_code"]})
+
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']))
+ (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
"""
- self.doc.from_case_no = self.get_recommended_case_no()
+ if not self.doc.from_case_no:
+ self.doc.from_case_no = self.get_recommended_case_no()
from webnotes.model.code import get_obj
for d in self.doclist:
diff --git a/stock/doctype/purchase_receipt/purchase_receipt.py b/stock/doctype/purchase_receipt/purchase_receipt.py
index 04ad4dc..9e23c27 100644
--- a/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -64,10 +64,6 @@
doc.fields[r] = ret[r]
- # Get UOM Details
- def get_uom_details(self, arg = ''):
- return get_obj(dt='Purchase Common').get_uom_details(arg)
-
# GET TERMS & CONDITIONS
# =====================================================================================
def get_tc_details(self):
diff --git a/utilities/page/question_view/question_view.py b/utilities/page/question_view/question_view.py
index e79a808..175a8ed 100644
--- a/utilities/page/question_view/question_view.py
+++ b/utilities/page/question_view/question_view.py
@@ -19,8 +19,8 @@
from webnotes.utils import load_json, cstr, now
@webnotes.whitelist()
-def update_item(args):
- args = load_json(args)
+def update_item(arg):
+ args = load_json(arg)
webnotes.conn.sql("update `tab%s` set `%s`=%s, modified=%s where name=%s" \
% (args['dt'], args['fn'], '%s', '%s', '%s'), (args['text'], now(), args['dn']))
diff --git a/utilities/page/users/__init__.py b/utilities/page/users/__init__.py
deleted file mode 100644
index baffc48..0000000
--- a/utilities/page/users/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/utilities/page/users/users.css b/utilities/page/users/users.css
deleted file mode 100644
index b739a57..0000000
--- a/utilities/page/users/users.css
+++ /dev/null
@@ -1,46 +0,0 @@
-.user-card {
- border-radius: 5px;
- width: 200px;
- margin: 11px;
- padding: 11px;
- background-color: #FFEDBD;
- box-shadow: 3px 3px 5px #888;
- float: left;
- overflow: hidden;
-}
-
-.user-card.disabled {
- background-color: #eee;
-}
-
-.user-card img {
- height: 60px;
-}
-
-.user-role {
- padding: 5px;
- width: 45%;
- float: left;
-}
-
-table.user-perm {
- border-collapse: collapse;
-}
-
-table.user-perm td, table.user-perm th {
- padding: 5px;
- text-align: center;
- border-bottom: 1px solid #aaa;
- min-width: 30px;
-}
-
-.subscription-info-box {
- margin: 0px 11px;
- background-color: #EEEEEE;
- border: 1px solid #DDDBDB;
- padding: 5px 3px;
-}
-
-.subscription-info {
- padding: 0px 10px;
-}
\ No newline at end of file
diff --git a/utilities/page/users/users.html b/utilities/page/users/users.html
deleted file mode 100644
index e69de29..0000000
--- a/utilities/page/users/users.html
+++ /dev/null
diff --git a/utilities/page/users/users.js b/utilities/page/users/users.js
deleted file mode 100644
index d09b207..0000000
--- a/utilities/page/users/users.js
+++ /dev/null
@@ -1,415 +0,0 @@
-// 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/>.
-
-$.extend(wn.pages.users, {
- onload: function(wrapper) {
- var w = wn.pages.users;
- wn.ui.make_app_page({
- parent: w,
- title: "Users",
- single_column: true
- });
- w.profiles = {};
- w.refresh();
- w.setup();
- w.role_editor = new erpnext.RoleEditor();
- },
- setup: function() {
- wn.pages.users.appframe.add_button('+ Add User', function() {
- wn.pages.users.add_user();
- });
-
- // set roles
- var w = wn.pages.users;
- $(w).on('click', '.btn.user-roles', function() {
- var uid = $(this).parent().parent().attr('data-name');
- wn.pages.users.role_editor.show(uid);
- });
-
- // settings
- $(w).on('click', '.btn.user-settings', function() {
- var uid = $(this).parent().parent().attr('data-name');
- wn.pages.users.show_settings(uid);
- });
-
- // delete
- $(w).on('click', 'a.close', function() {
- $card = $(this).parent();
- var uid = $card.attr('data-name');
- $card.css('opacity', 0.6);
- wn.call({
- method: 'utilities.page.users.users.delete',
- args: {'uid': uid},
- callback: function(r,rt) {
- if(!r.exc)
- $card.fadeOut()
- }
- });
- })
-
- },
- refresh: function() {
- // make the list
- wn.call({
- method:'utilities.page.users.users.get',
- callback: function(r, rt) {
- $(wn.pages.users).find('.layout-main').empty();
- for(var i in r.message) {
- var p = r.message[i];
- wn.pages.users.profiles[p.name] = p;
- wn.pages.users.render(p);
- }
- }
- });
- if(!$('.subscription-info').length && (wn.boot.max_users || wn.boot.expires_on)) {
- var $sub_info = $('<div class="subscription-info-box"><div>')
- .insertAfter($(wn.pages.users).find('.help'));
- if(wn.boot.max_users) {
- $sub_info.append(repl('\
- <span class="subscription-info"> \
- Max Users: <b>%(max_users)s</b> \
- </span>', { max_users: wn.boot.max_users }));
- }
- if(wn.boot.expires_on) {
- $sub_info.append(repl('\
- <span class="subscription-info"> \
- Expires On: <b>%(expires_on)s</b> \
- </span>', { expires_on: dateutil.str_to_user(wn.boot.expires_on) }));
- }
- }
- },
- render: function(data) {
- if(data.file_list) {
- data.imgsrc = 'files/' + data.file_list.split('\n')[0].split(',')[1];
- } else {
- data.imgsrc = 'lib/images/ui/no_img_' + (data.gender=='Female' ? 'f' : 'm') + '.gif';
- }
- data.fullname = wn.user_info(data.name).fullname;
- data.delete_html = '';
- if(!data.enabled)
- data.delete_html = '<a class="close" title="delete">×</a>';
-
- $(wn.pages.users).find('.layout-main').append(repl('<div class="user-card" data-name="%(name)s">\
- %(delete_html)s\
- <img src="%(imgsrc)s">\
- <div class="user-info">\
- <b class="user-fullname">%(fullname)s</b><br>\
- %(name)s<br>\
- <button class="btn btn-small user-roles"><i class="icon-user"></i> Roles</button>\
- <button class="btn btn-small user-settings"><i class="icon-cog"></i> Settings</button>\
- </div>\
- </div>', data));
-
- if(!data.enabled) {
- $(wn.pages.users).find('.layout-main .user-card:last')
- .addClass('disabled')
- .find('.user-fullname').html('Disabled');
- }
- },
- show_settings: function(uid) {
- var me = wn.pages.users;
- if(!me.settings_dialog)
- me.make_settings_dialog();
-
- var p = me.profiles[uid];
- me.uid = uid;
-
- me.settings_dialog.set_values({
- restrict_ip: p.restrict_ip || '',
- login_before: p.login_before || '',
- login_after: p.login_after || '',
- enabled: p.enabled || 0,
- new_password: ''
- });
-
- me.settings_dialog.show();
-
- },
- make_settings_dialog: function() {
- var me = wn.pages.users;
- me.settings_dialog = new wn.ui.Dialog({
- title: 'Set User Security',
- width: 500,
- fields: [
- {
- label:'Enabled',
- description: 'Uncheck to disable',
- fieldtype: 'Check', fieldname: 'enabled'
- },
- {
- label:'IP Address',
- description: 'Restrict user login by IP address, partial ips (111.111.111), \
- multiple addresses (separated by commas) allowed',
- fieldname:'restrict_ip', fieldtype:'Data'
- },
- {
- label:'Login After',
- description: 'User can only login after this hour (0-24)',
- fieldtype: 'Int', fieldname: 'login_after'
- },
- {
- label:'Login Before',
- description: 'User can only login before this hour (0-24)',
- fieldtype: 'Int', fieldname: 'login_before'
- },
- {
- label:'New Password',
- description: 'Update the current user password',
- fieldtype: 'Data', fieldname: 'new_password'
- },
- {
- label:'Update', fieldtype:'Button', fieldname:'update'
- }
- ]
- });
-
- this.settings_dialog.fields_dict.update.input.onclick = function() {
- var btn = this;
- var args = me.settings_dialog.get_values();
- args.user = me.uid;
-
- if (args.new_password) {
- me.get_password(btn, args);
- } else {
- me.update_security(btn, args);
- }
- };
-
- },
- update_security: function(btn, args) {
- var me = wn.pages.users;
- $(btn).set_working();
- $c_page('utilities', 'users', 'update_security', JSON.stringify(args), function(r,rt) {
- $(btn).done_working();
- if(r.exc) {
- msgprint(r.exc);
- return;
- }
- me.settings_dialog.hide();
- $.extend(me.profiles[me.uid], me.settings_dialog.get_values());
- me.refresh();
- });
- },
- get_password: function(btn, args) {
- var me = wn.pages.users;
- var pass_d = new wn.ui.Dialog({
- title: 'Your Password',
- width: 300,
- fields: [
- {
- label: 'Please Enter <b style="color: black">Your Password</b>',
- description: "Your password is required to update the user's password",
- fieldtype: 'Password', fieldname: 'sys_admin_pwd', reqd: 1
- },
- {
- label: 'Continue', fieldtype: 'Button', fieldname: 'continue'
- }
- ]
- });
-
- pass_d.fields_dict.continue.input.onclick = function() {
- btn.pwd_dialog.hide();
- args.sys_admin_pwd = btn.pwd_dialog.get_values().sys_admin_pwd;
- btn.set_working();
- me.update_security(btn, args);
- btn.done_working();
- }
-
- pass_d.show();
- btn.pwd_dialog = pass_d;
- btn.done_working();
- },
- add_user: function() {
- var me = wn.pages.users;
- var active_users = $('.user-card:not(.disabled)');
- if(wn.boot.max_users && (active_users.length >= wn.boot.max_users)) {
- msgprint(repl("You already have <b>%(active_users)s</b> active users, \
- which is the maximum number that you are currently allowed to add. <br /><br /> \
- So, to add more users, you can:<br /> \
- 1. <b>Upgrade to the unlimited users plan</b>, or<br /> \
- 2. <b>Disable one or more of your existing users and try again</b>",
- {active_users: active_users.length}));
- return;
- }
- var d = new wn.ui.Dialog({
- title: 'Add User',
- width: 400,
- fields: [{
- fieldtype: 'Data', fieldname: 'user', reqd: 1,
- label: 'Email Id of the user to add'
- }, {
- fieldtype: 'Data', fieldname: 'first_name', reqd: 1, label: 'First Name'
- }, {
- fieldtype: 'Data', fieldname: 'last_name', label: 'Last Name'
- }, {
- fieldtype: 'Data', fieldname: 'password', reqd: 1, label: 'Password'
- }, {
- fieldtype: 'Button', label: 'Add', fieldname: 'add'
- }]
- });
-
- d.make();
- d.fields_dict.add.input.onclick = function() {
- v = d.get_values();
- if(v) {
- d.fields_dict.add.input.set_working();
- $c_page('utilities', 'users', 'add_user', v, function(r,rt) {
- if(r.exc) { msgprint(r.exc); return; }
- else {
- wn.boot.user_info[v.user] = {fullname:v.first_name + ' ' + (v.last_name || '')};
- d.hide();
- me.refresh();
- }
- })
- }
- }
- d.show();
- }
-});
-
-erpnext.RoleEditor = Class.extend({
- init: function() {
- this.dialog = new wn.ui.Dialog({
- title: 'Set Roles'
- });
- var me = this;
- $(this.dialog.body).html('<div class="help">Loading...</div>')
- wn.call({
- method:'utilities.page.users.users.get_roles',
- callback: function(r) {
- me.roles = r.message;
- me.show_roles();
- }
- });
- },
- show_roles: function() {
- var me = this;
- $(this.dialog.body).empty();
- for(var i in this.roles) {
- $(this.dialog.body).append(repl('<div class="user-role" \
- data-user-role="%(role)s">\
- <input type="checkbox"> \
- <a href="#"><i class="icon-question-sign"></i></a> %(role)s\
- </div>', {role: this.roles[i]}));
- }
- $(this.dialog.body).append('<div style="clear: both">\
- <button class="btn btn-small btn-info">Save</button></div>');
- $(this.dialog.body).find('button.btn-info').click(function() {
- me.save();
- });
- $(this.dialog.body).find('.user-role a').click(function() {
- me.show_permissions($(this).parent().attr('data-user-role'))
- return false;
- })
- },
- show: function(uid) {
- var me = this;
- this.uid = uid;
- this.dialog.show();
- // set user roles
- wn.call({
- method:'utilities.page.users.users.get_user_roles',
- args: {uid:uid},
- callback: function(r, rt) {
- $(me.dialog.body).find('input[type="checkbox"]').attr('checked', false);
- for(var i in r.message) {
- $(me.dialog.body)
- .find('[data-user-role="'+r.message[i]
- +'"] input[type="checkbox"]').attr('checked',true);
- }
- }
- })
- },
- save: function() {
- var set_roles = [];
- var unset_roles = [];
- $(this.dialog.body).find('[data-user-role]').each(function() {
- var $check = $(this).find('input[type="checkbox"]');
- if($check.attr('checked')) {
- set_roles.push($(this).attr('data-user-role'));
- } else {
- unset_roles.push($(this).attr('data-user-role'));
- }
- })
- wn.call({
- method:'utilities.page.users.users.update_roles',
- args: {
- set_roles: JSON.stringify(set_roles),
- unset_roles: JSON.stringify(unset_roles),
- uid: this.uid
- },
- btn: $(this.dialog.body).find('.btn-info').get(0),
- callback: function() {
-
- }
- })
- },
- show_permissions: function(role) {
- // show permissions for a role
- var me = this;
- if(!this.perm_dialog)
- this.make_perm_dialog()
- $(this.perm_dialog.body).empty();
- wn.call({
- method:'utilities.page.users.users.get_perm_info',
- args: {role: role},
- callback: function(r) {
- var $body = $(me.perm_dialog.body);
- $body.append('<table class="user-perm"><tbody><tr>\
- <th style="text-align: left">Document Type</th>\
- <th>Level</th>\
- <th>Read</th>\
- <th>Write</th>\
- <th>Submit</th>\
- <th>Cancel</th>\
- <th>Amend</th></tr></tbody></table>');
- for(var i in r.message) {
- var perm = r.message[i];
-
- // if permission -> icon
- for(key in perm) {
- if(key!='parent' && key!='permlevel') {
- if(perm[key]) {
- perm[key] = '<i class="icon-ok"></i>';
- } else {
- perm[key] = '';
- }
- }
- }
-
- $body.find('tbody').append(repl('<tr>\
- <td style="text-align: left">%(parent)s</td>\
- <td>%(permlevel)s</td>\
- <td>%(read)s</td>\
- <td>%(write)s</td>\
- <td>%(submit)s</td>\
- <td>%(cancel)s</td>\
- <td>%(amend)s</td>\
- </tr>', perm))
- }
-
- me.perm_dialog.show();
- }
- });
-
- },
- make_perm_dialog: function() {
- this.perm_dialog = new wn.ui.Dialog({
- title:'Role Permissions',
- width: 500
- });
- }
-})
diff --git a/utilities/page/users/users.py b/utilities/page/users/users.py
deleted file mode 100644
index 9878d3c..0000000
--- a/utilities/page/users/users.py
+++ /dev/null
@@ -1,202 +0,0 @@
-# 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
-import json
-
-from webnotes.model.doc import Document
-from webnotes.utils import cint
-
-@webnotes.whitelist()
-def get(arg=None):
- """return all users"""
- return webnotes.conn.sql("""select name, file_list, enabled, gender,
- restrict_ip, login_before, login_after from tabProfile
- where docstatus<2 and name not in ('Administrator', 'Guest') order by
- ifnull(enabled,0) desc, name""", as_dict=1)
-
-@webnotes.whitelist()
-def get_roles(arg=None):
- """return all roles except standard"""
- return _get_roles(webnotes.form_dict['uid'])
-
-def _get_roles(user):
- """return all roles except standard"""
- return [r[0] for r in webnotes.conn.sql("""select name from tabRole
- where name not in ('Administrator', 'Guest', 'All') order by name""", user)]
-
-@webnotes.whitelist()
-def get_user_roles(arg=None):
- """get roles for a user"""
- return [r[0] for r in webnotes.conn.sql("""select role from tabUserRole
- where parent=%s""", webnotes.form_dict['uid'])]
-
-@webnotes.whitelist()
-def get_perm_info(arg=None):
- """get permission info"""
- return webnotes.conn.sql("""select parent, permlevel, `read`, `write`, submit,
- cancel, amend from tabDocPerm where role=%s
- and docstatus<2 order by parent, permlevel""",
- webnotes.form_dict['role'], as_dict=1)
-
-@webnotes.whitelist()
-def update_roles(arg=None):
- """update set and unset roles"""
- # remove roles
- unset = json.loads(webnotes.form_dict['unset_roles'])
- webnotes.conn.sql("""delete from tabUserRole where parent='%s'
- and role in ('%s')""" % (webnotes.form_dict['uid'], "','".join(unset)))
-
- # check for 1 system manager
- if not webnotes.conn.sql("""select parent from tabUserRole where role='System Manager'
- and docstatus<2"""):
- webnotes.msgprint("Sorry there must be atleast one 'System Manager'")
- raise webnotes.ValidationError
-
- # add roles
- roles = get_user_roles()
- toset = json.loads(webnotes.form_dict['set_roles'])
- for role in toset:
- if not role in roles:
- d = Document('UserRole')
- d.role = role
- d.parent = webnotes.form_dict['uid']
- d.save()
-
- webnotes.msgprint('Roles Updated')
-
-@webnotes.whitelist()
-def update_security(args=''):
- args = json.loads(args)
- webnotes.conn.set_value('Profile', args['user'], 'restrict_ip', args.get('restrict_ip') or '')
- webnotes.conn.set_value('Profile', args['user'], 'login_after', args.get('login_after') or None)
- webnotes.conn.set_value('Profile', args['user'], 'login_before', args.get('login_before') or None)
- webnotes.conn.set_value('Profile', args['user'], 'enabled', int(args.get('enabled',0)) or 0)
-
- # logout a disabled user
- if not int(args.get('enabled',0) or 0):
- webnotes.login_manager.logout(user=args['user'])
-
- if args.get('new_password') and args.get('sys_admin_pwd'):
- from webnotes.utils import cint
- webnotes.conn.sql("update tabProfile set password=password(%s) where name=%s",
- (args['new_password'], args['user']))
- else:
- webnotes.msgprint('Settings Updated')
-
-
-
-#
-# user addition
-#
-
-@webnotes.whitelist()
-def add_user(args):
- args = json.loads(args)
- add_profile(args)
-
-@webnotes.whitelist()
-def add_profile(args):
- from webnotes.utils import validate_email_add, now
- email = args['user']
- sql = webnotes.conn.sql
-
- # validate max number of users exceeded or not
- import conf
- if hasattr(conf, 'max_users'):
- active_users = sql("""select count(*) from tabProfile
- where ifnull(enabled, 0)=1 and docstatus<2
- and name not in ('Administrator', 'Guest')""")[0][0]
- if active_users >= conf.max_users and conf.max_users:
- # same message as in users.js
- webnotes.msgprint("""Alas! <br />\
- You already have <b>%(active_users)s</b> active users, \
- which is the maximum number that you are currently allowed to add. <br /><br /> \
- So, to add more users, you can:<br /> \
- 1. <b>Upgrade to the unlimited users plan</b>, or<br /> \
- 2. <b>Disable one or more of your existing users and try again</b>""" \
- % {'active_users': active_users}, raise_exception=1)
-
- if not email:
- email = webnotes.form_dict.get('user')
- if not validate_email_add(email):
- raise Exception
- return 'Invalid Email Id'
-
- if sql("select name from tabProfile where name = %s", email):
- # exists, enable it
- sql("update tabProfile set enabled = 1, docstatus=0 where name = %s", email)
- webnotes.msgprint('Profile exists, enabled it with new password')
- else:
- # does not exist, create it!
- pr = Document('Profile')
- pr.name = email
- pr.email = email
- pr.first_name = args.get('first_name')
- pr.last_name = args.get('last_name')
- pr.enabled = 1
- pr.user_type = 'System User'
- pr.save(1)
-
- if args.get('password'):
- sql("""
- UPDATE tabProfile
- SET password = PASSWORD(%s), modified = %s
- WHERE name = %s""", (args.get('password'), now, email))
-
- send_welcome_mail(email, args)
-
-@webnotes.whitelist()
-def send_welcome_mail(email, args):
- """send welcome mail to user with password and login url"""
- pr = Document('Profile', email)
- from webnotes.utils.email_lib import sendmail_md
- args.update({
- 'company': webnotes.conn.get_default('company'),
- 'password': args.get('password'),
- 'account_url': webnotes.conn.get_value('Website Settings',
- 'Website Settings', 'subdomain') or ""
- })
- if not args.get('last_name'): args['last_name'] = ''
- sendmail_md(pr.email, subject="Welcome to ERPNext", msg=welcome_txt % args)
-
-#
-# delete user
-#
-@webnotes.whitelist()
-def delete(arg=None):
- """delete user"""
- webnotes.conn.sql("update tabProfile set enabled=0, docstatus=2 where name=%s",
- webnotes.form_dict['uid'])
- webnotes.login_manager.logout(user=webnotes.form_dict['uid'])
-
-welcome_txt = """
-## %(company)s
-
-Dear %(first_name)s %(last_name)s
-
-Welcome!
-
-A new account has been created for you, here are your details:
-
-login-id: %(user)s
-password: %(password)s
-
-To login to your new ERPNext account, please go to:
-
-%(account_url)s
-"""
diff --git a/utilities/page/users/users.txt b/utilities/page/users/users.txt
deleted file mode 100644
index 165cc16..0000000
--- a/utilities/page/users/users.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-# Page, users
-[
-
- # These values are common in all dictionaries
- {
- 'creation': '2012-02-28 10:29:39',
- 'docstatus': 0,
- 'modified': '2012-02-28 10:29:39',
- 'modified_by': u'Administrator',
- 'owner': u'Administrator'
- },
-
- # These values are common for all Page
- {
- 'doctype': 'Page',
- 'module': u'Utilities',
- 'name': '__common__',
- 'page_name': u'users',
- 'standard': u'Yes',
- 'title': u'Users'
- },
-
- # Page, users
- {
- 'doctype': 'Page',
- 'name': u'users'
- }
-]
\ No newline at end of file