diff --git a/accounts/Module Def/Accounts/Accounts.txt b/accounts/Module Def/Accounts/Accounts.txt index 35e7e5d38d4..512b460b829 100644 --- a/accounts/Module Def/Accounts/Accounts.txt +++ b/accounts/Module Def/Accounts/Accounts.txt @@ -5,7 +5,7 @@ { 'creation': '2010-09-25 10:50:34', 'docstatus': 0, - 'modified': '2011-07-27 11:43:40', + 'modified': '2011-07-28 12:01:10', 'modified_by': 'Administrator', 'owner': 'Administrator' }, @@ -358,7 +358,7 @@ # Module Def Item { 'display_name': 'Lease Agreement List', - 'doc_name': 'Lease Agreement List', + 'doc_name': 'GL Entry', 'doc_type': 'Reports', 'doctype': 'Module Def Item', 'idx': 33 @@ -367,7 +367,7 @@ # Module Def Item { 'display_name': 'Lease Monthly Future Installment Inflows', - 'doc_name': 'Lease Monthly Future Installment Inflows', + 'doc_name': 'GL Entry', 'doc_type': 'Reports', 'doctype': 'Module Def Item', 'idx': 34 @@ -376,7 +376,7 @@ # Module Def Item { 'display_name': 'Lease Overdue Age Wise', - 'doc_name': 'Lease Overdue Age Wise', + 'doc_name': 'GL Entry', 'doc_type': 'Reports', 'doctype': 'Module Def Item', 'idx': 35 @@ -385,7 +385,7 @@ # Module Def Item { 'display_name': 'Lease Overdue List', - 'doc_name': 'Lease Overdue List', + 'doc_name': 'GL Entry', 'doc_type': 'Reports', 'doctype': 'Module Def Item', 'idx': 36 @@ -394,7 +394,7 @@ # Module Def Item { 'display_name': 'Lease Receipts Client Wise', - 'doc_name': 'Lease Receipts Client Wise', + 'doc_name': 'GL Entry', 'doc_type': 'Reports', 'doctype': 'Module Def Item', 'idx': 37 @@ -402,8 +402,8 @@ # Module Def Item { - 'display_name': 'Lease Receipt Summary Year to Date', - 'doc_name': 'Lease Receipt Summary Year to Date', + 'display_name': 'Lease Receipt Summary Month Wise', + 'doc_name': 'GL Entry', 'doc_type': 'Reports', 'doctype': 'Module Def Item', 'idx': 38 @@ -412,7 +412,7 @@ # Module Def Item { 'display_name': 'Lease Yearly Future Installment Inflows', - 'doc_name': 'Lease Yearly Future Installment Inflows', + 'doc_name': 'GL Entry', 'doc_type': 'Reports', 'doctype': 'Module Def Item', 'idx': 39 diff --git a/accounts/doctype/account/account.js b/accounts/doctype/account/account.js index 071bf570184..51cacdaf367 100644 --- a/accounts/doctype/account/account.js +++ b/accounts/doctype/account/account.js @@ -72,16 +72,6 @@ cur_frm.fields_dict['master_name'].get_query=function(doc){ else alert("Please select master type"); } -/* -// Get customer/supplier address -// ----------------------------------------- -cur_frm.cscript.master_name = function(doc,cdt,cdn){ - if(doc.master_name){ - get_server_fields('get_address','','',doc,cdt,cdn); - } -} -*/ - // parent account get query // ----------------------------------------- cur_frm.fields_dict['parent_account'].get_query = function(doc){ diff --git a/accounts/doctype/account/account.py b/accounts/doctype/account/account.py index 52c66a9adf7..6c8003a5817 100644 --- a/accounts/doctype/account/account.py +++ b/accounts/doctype/account/account.py @@ -31,7 +31,7 @@ class DocType: def get_address(self): add=sql("Select address from `tab%s` where name='%s'"%(self.doc.master_type,self.doc.master_name)) ret={'address':add[0][0]} - return cstr(ret) + return ret # check whether master name entered for supplier/customer diff --git a/accounts/doctype/account/account.txt b/accounts/doctype/account/account.txt index b29c61782fd..bf48a24d0c3 100644 --- a/accounts/doctype/account/account.txt +++ b/accounts/doctype/account/account.txt @@ -455,7 +455,8 @@ 'description': "Don't delete this field at any cost", 'doctype': 'DocField', 'fieldname': 'old_parent', - 'fieldtype': 'Data', + 'fieldtype': 'Link', + 'options': 'Account', 'hidden': 1, 'idx': 24, 'label': 'Old Parent', @@ -517,4 +518,4 @@ 'oldfieldtype': 'Small Text', 'permlevel': 1 } -] \ No newline at end of file +] diff --git a/accounts/doctype/bank_reconciliation/bank_reconciliation.py b/accounts/doctype/bank_reconciliation/bank_reconciliation.py index 8434f628d36..3ba477b3193 100644 --- a/accounts/doctype/bank_reconciliation/bank_reconciliation.py +++ b/accounts/doctype/bank_reconciliation/bank_reconciliation.py @@ -18,32 +18,32 @@ convert_to_lists = webnotes.conn.convert_to_lists class DocType: - def __init__(self, d, dl): - self.doc, self.doclist = d, dl + def __init__(self, d, dl): + self.doc, self.doclist = d, dl - def get_details(self): - if not (self.doc.bank_account and self.doc.from_date and self.doc.to_date): - msgprint("Bank Account, From Date and To Date are Mandatory") - return - - dl = sql("select t1.name, t1.cheque_no, t1.cheque_date, t2.debit, t2.credit, t1.posting_date, t2.against_account from `tabJournal Voucher` t1, `tabJournal Voucher Detail` t2 where t2.parent = t1.name and t2.account = %s and (clearance_date is null or clearance_date = '0000-00-00' or clearance_date = '') and (t1.cheque_no is not null or t1.cheque_no != '') and t1.posting_date >= %s and t1.posting_date <= %s and t1.docstatus=1", (self.doc.bank_account, self.doc.from_date, self.doc.to_date)) - - self.doc.clear_table(self.doclist, 'entries') - self.doc.total_amount = 0.0 + def get_details(self): + if not (self.doc.bank_account and self.doc.from_date and self.doc.to_date): + msgprint("Bank Account, From Date and To Date are Mandatory") + return + + dl = sql("select t1.name, t1.cheque_no, t1.cheque_date, t2.debit, t2.credit, t1.posting_date, t2.against_account from `tabJournal Voucher` t1, `tabJournal Voucher Detail` t2 where t2.parent = t1.name and t2.account = %s and (clearance_date is null or clearance_date = '0000-00-00' or clearance_date = '') and (t1.cheque_no is not null or t1.cheque_no != '') and t1.posting_date >= %s and t1.posting_date <= %s and t1.docstatus=1", (self.doc.bank_account, self.doc.from_date, self.doc.to_date)) + + self.doc.clear_table(self.doclist, 'entries') + self.doc.total_amount = 0.0 - for d in dl: - nl = addchild(self.doc, 'entries', 'Bank Reconciliation Detail', 1, self.doclist) - nl.posting_date = str(d[5]) - nl.voucher_id = str(d[0]) - nl.cheque_number = str(d[1]) - nl.cheque_date = str(d[2]) - nl.debit = flt(d[3]) - nl.credit = flt(d[4]) - nl.against_account = d[6] - self.doc.total_amount += flt(flt(d[4]) - flt(d[3])) + for d in dl: + nl = addchild(self.doc, 'entries', 'Bank Reconciliation Detail', 1, self.doclist) + nl.posting_date = str(d[5]) + nl.voucher_id = str(d[0]) + nl.cheque_number = str(d[1]) + nl.cheque_date = str(d[2]) + nl.debit = flt(d[3]) + nl.credit = flt(d[4]) + nl.against_account = d[6] + self.doc.total_amount += flt(flt(d[4]) - flt(d[3])) - def update_details(self): - for d in getlist(self.doclist, 'entries'): - if d.clearance_date: - sql("update `tabJournal Voucher` set clearance_date = %s where name=%s", (d.clearance_date, d.voucher_id)) - msgprint("Updated") \ No newline at end of file + def update_details(self): + for d in getlist(self.doclist, 'entries'): + if d.clearance_date: + sql("update `tabJournal Voucher` set clearance_date = %s, modified = %s where name=%s", (d.clearance_date, nowdate(), d.voucher_id)) + msgprint("Updated") diff --git a/accounts/doctype/cost_center/cost_center.py b/accounts/doctype/cost_center/cost_center.py index 060225da0be..521712b1f95 100644 --- a/accounts/doctype/cost_center/cost_center.py +++ b/accounts/doctype/cost_center/cost_center.py @@ -31,7 +31,7 @@ class DocType: ret = { 'company_abbr' : abbr } - return cstr(ret) + return ret def validate(self): # Cost Center name must be unique diff --git a/accounts/doctype/form_16a/form_16a.py b/accounts/doctype/form_16a/form_16a.py index 292c52a2da4..018b834763c 100644 --- a/accounts/doctype/form_16a/form_16a.py +++ b/accounts/doctype/form_16a/form_16a.py @@ -39,7 +39,7 @@ class DocType(TransactionBase): 'company_address': cstr(comp_det[0][0]), 'registration_details': cstr(comp_det[0][1]) } - return cstr(ret) + return ret # Get party details #------------------ @@ -56,7 +56,7 @@ class DocType(TransactionBase): 'party_address': cstr(address_display) } - return cstr(ret) + return ret # Get TDS Return acknowledgement #------------------------------- diff --git a/accounts/doctype/journal_voucher/journal_voucher.js b/accounts/doctype/journal_voucher/journal_voucher.js index dce570b4d4b..f65ee3169dc 100644 --- a/accounts/doctype/journal_voucher/journal_voucher.js +++ b/accounts/doctype/journal_voucher/journal_voucher.js @@ -1,9 +1,5 @@ cur_frm.cscript.onload = function(doc, cdt, cdn) { var cp = locals['Control Panel']['Control Panel']; - if(doc.__islocal){ - doc.clearance_date =''; - refresh_field('clearance_date'); - } if (!doc.voucher_date) doc.voucher_date = dateutil.obj_to_str(new Date()); @@ -155,4 +151,4 @@ cur_frm.cscript['View Ledger Entry'] = function(doc,cdt,cdn){ report.dt.run(); } loadreport('GL Entry','General Ledger', callback); -} \ No newline at end of file +} diff --git a/accounts/doctype/journal_voucher/journal_voucher.py b/accounts/doctype/journal_voucher/journal_voucher.py index 4f5e67a79b9..5942ca18aca 100644 --- a/accounts/doctype/journal_voucher/journal_voucher.py +++ b/accounts/doctype/journal_voucher/journal_voucher.py @@ -38,9 +38,9 @@ class DocType: args = eval(args) o_s = sql("select outstanding_amount from `tab%s` where name = '%s'" % (args['doctype'],args['docname'])) if args['doctype'] == 'Payable Voucher': - return cstr({'debit': o_s and flt(o_s[0][0]) or 0}) + return {'debit': o_s and flt(o_s[0][0]) or 0} if args['doctype'] == 'Receivable Voucher': - return cstr({'credit': o_s and flt(o_s[0][0]) or 0}) + return {'credit': o_s and flt(o_s[0][0]) or 0} #-------------------------------------------------------------------------------------------------------- # Create remarks diff --git a/accounts/doctype/journal_voucher/journal_voucher.txt b/accounts/doctype/journal_voucher/journal_voucher.txt new file mode 100644 index 00000000000..104d3d1c2da --- /dev/null +++ b/accounts/doctype/journal_voucher/journal_voucher.txt @@ -0,0 +1,802 @@ +# DocType, Journal Voucher +[ + + # These values are common in all dictionaries + { + 'creation': '2010-08-08 17:09:06', + 'docstatus': 0, + 'modified': '2011-07-28 15:28:12', + 'modified_by': 'Administrator', + 'owner': 'Administrator' + }, + + # These values are common for all DocType + { + '_last_update': '1311251040', + 'colour': 'White:FFF', + 'doctype': 'DocType', + 'module': 'Accounts', + 'name': '__common__', + 'search_fields': 'voucher_type,posting_date, due_date, cheque_no', + 'section_style': 'Tabbed', + 'server_code_error': ' ', + 'show_in_menu': 0, + 'subject': ' ', + 'tag_fields': 'voucher_type', + 'version': 309 + }, + + # These values are common for all DocField + { + 'doctype': 'DocField', + 'name': '__common__', + 'parent': 'Journal Voucher', + 'parentfield': 'fields', + 'parenttype': 'DocType' + }, + + # These values are common for all DocPerm + { + 'doctype': 'DocPerm', + 'name': '__common__', + 'parent': 'Journal Voucher', + 'parentfield': 'permissions', + 'parenttype': 'DocType', + 'read': 1 + }, + + # DocType, Journal Voucher + { + 'doctype': 'DocType', + 'name': 'Journal Voucher' + }, + + # DocPerm + { + 'amend': 0, + 'cancel': 0, + 'create': 0, + 'doctype': 'DocPerm', + 'idx': 1, + 'permlevel': 1, + 'role': 'Accounts Manager', + 'submit': 0, + 'write': 0 + }, + + # DocPerm + { + 'amend': 1, + 'cancel': 1, + 'create': 1, + 'doctype': 'DocPerm', + 'idx': 2, + 'permlevel': 0, + 'role': 'Accounts Manager', + 'submit': 1, + 'write': 1 + }, + + # DocPerm + { + 'amend': 1, + 'cancel': 1, + 'create': 1, + 'doctype': 'DocPerm', + 'idx': 3, + 'permlevel': 0, + 'role': 'Accounts User', + 'submit': 1, + 'write': 1 + }, + + # DocPerm + { + 'amend': 0, + 'cancel': 0, + 'create': 0, + 'doctype': 'DocPerm', + 'idx': 4, + 'permlevel': 1, + 'role': 'Accounts User', + 'submit': 0, + 'write': 0 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldtype': 'Section Break', + 'idx': 1, + 'label': 'Basic Info', + 'oldfieldtype': 'Section Break', + 'permlevel': 0 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldtype': 'Section Break', + 'idx': 2, + 'label': '1. Select Series and Dates', + 'oldfieldtype': 'Section Break', + 'options': 'Simple', + 'permlevel': 0 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldtype': 'Column Break', + 'idx': 3, + 'oldfieldtype': 'Column Break', + 'permlevel': 0, + 'width': '50%' + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'voucher_type', + 'fieldtype': 'Select', + 'idx': 4, + 'in_filter': 1, + 'label': 'Voucher Type', + 'oldfieldname': 'voucher_type', + 'oldfieldtype': 'Select', + 'options': '\nJournal Entry\nBank Voucher\nCash Voucher\nCredit Card Voucher\nDebit Note\nCredit Note\nContra Voucher\nExcise Voucher\nWrite Off Voucher\nLoan Receipt', + 'permlevel': 0, + 'print_hide': 0, + 'search_index': 1 + }, + + # DocField + { + 'colour': 'White:FFF', + 'depends_on': "eval:doc.voucher_type == 'Write Off Voucher'", + 'doctype': 'DocField', + 'fieldname': 'write_off_amount', + 'fieldtype': 'Currency', + 'idx': 5, + 'label': 'Write Off Amount <=', + 'permlevel': 0, + 'print_hide': 1, + 'report_hide': 1 + }, + + # DocField + { + 'colour': 'White:FFF', + 'default': 'Accounts Receivable', + 'depends_on': "eval:doc.voucher_type == 'Write Off Voucher'", + 'doctype': 'DocField', + 'fieldname': 'write_off_based_on', + 'fieldtype': 'Select', + 'idx': 6, + 'label': 'Write Off Based On', + 'options': 'Accounts Receivable\nAccounts Payable', + 'permlevel': 0, + 'print_hide': 1, + 'report_hide': 1 + }, + + # DocField + { + 'colour': 'White:FFF', + 'description': 'To manage multiple series please go to Setup > Manage Series', + 'doctype': 'DocField', + 'fieldname': 'naming_series', + 'fieldtype': 'Select', + 'idx': 7, + 'label': 'Series', + 'no_copy': 1, + 'oldfieldname': 'naming_series', + 'oldfieldtype': 'Select', + 'options': 'JV', + 'permlevel': 0, + 'print_hide': 1, + 'reqd': 1 + }, + + # DocField + { + 'colour': 'White:FFF', + 'default': 'Today', + 'doctype': 'DocField', + 'fieldname': 'voucher_date', + 'fieldtype': 'Date', + 'idx': 8, + 'in_filter': 1, + 'label': 'Voucher Date', + 'no_copy': 1, + 'oldfieldname': 'voucher_date', + 'oldfieldtype': 'Date', + 'permlevel': 0, + 'print_hide': 0, + 'reqd': 1, + 'search_index': 1 + }, + + # DocField + { + 'description': 'The date at which current entry will get or has actually executed.', + 'doctype': 'DocField', + 'fieldname': 'posting_date', + 'fieldtype': 'Date', + 'idx': 9, + 'in_filter': 1, + 'label': 'Posting Date', + 'no_copy': 1, + 'oldfieldname': 'posting_date', + 'oldfieldtype': 'Date', + 'permlevel': 0, + 'reqd': 1, + 'search_index': 1 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'due_date', + 'fieldtype': 'Date', + 'idx': 10, + 'label': 'Due Date', + 'oldfieldname': 'due_date', + 'oldfieldtype': 'Date', + 'permlevel': 0, + 'print_hide': 0 + }, + + # DocField + { + 'description': 'The date at which current entry is corrected in the system.', + 'doctype': 'DocField', + 'fieldname': 'amendment_date', + 'fieldtype': 'Date', + 'idx': 11, + 'label': 'Amendment Date', + 'no_copy': 1, + 'oldfieldname': 'amendment_date', + 'oldfieldtype': 'Date', + 'permlevel': 0, + 'print_hide': 1 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'amended_from', + 'fieldtype': 'Link', + 'idx': 12, + 'label': 'Amended From', + 'no_copy': 1, + 'oldfieldname': 'amended_from', + 'oldfieldtype': 'Link', + 'options': 'Journal Voucher', + 'permlevel': 1, + 'print_hide': 1 + }, + + # DocField + { + 'colour': 'White:FFF', + 'depends_on': "eval:doc.voucher_type == 'Write Off Voucher'", + 'doctype': 'DocField', + 'fieldtype': 'Button', + 'idx': 13, + 'label': 'Get Outstanding Invoices', + 'options': 'get_outstanding_invoices', + 'permlevel': 0, + 'print_hide': 1, + 'trigger': 'Server' + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldtype': 'Column Break', + 'idx': 14, + 'oldfieldtype': 'Column Break', + 'permlevel': 0, + 'width': '50%' + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'cheque_no', + 'fieldtype': 'Data', + 'idx': 15, + 'in_filter': 1, + 'label': 'Cheque No', + 'no_copy': 1, + 'oldfieldname': 'cheque_no', + 'oldfieldtype': 'Data', + 'permlevel': 0, + 'search_index': 1 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'cheque_date', + 'fieldtype': 'Date', + 'idx': 16, + 'label': 'Cheque Date', + 'no_copy': 1, + 'oldfieldname': 'cheque_date', + 'oldfieldtype': 'Date', + 'permlevel': 0 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'clearance_date', + 'fieldtype': 'Date', + 'idx': 17, + 'in_filter': 1, + 'label': 'Clearance Date', + 'no_copy': 1, + 'oldfieldname': 'clearance_date', + 'oldfieldtype': 'Date', + 'permlevel': 1, + 'print_hide': 0, + 'search_index': 1 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'user_remark', + 'fieldtype': 'Small Text', + 'idx': 18, + 'in_filter': 1, + 'label': 'User Remark', + 'no_copy': 1, + 'oldfieldname': 'user_remark', + 'oldfieldtype': 'Small Text', + 'permlevel': 0 + }, + + # DocField + { + 'description': 'User Remark will be added to Auto Remark', + 'doctype': 'DocField', + 'fieldname': 'remark', + 'fieldtype': 'Small Text', + 'idx': 19, + 'label': 'Remark', + 'no_copy': 1, + 'oldfieldname': 'remark', + 'oldfieldtype': 'Small Text', + 'permlevel': 1, + 'reqd': 0 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldtype': 'Section Break', + 'idx': 20, + 'label': '2. Add / Edit GL Entries', + 'oldfieldtype': 'Section Break', + 'options': 'Simple', + 'permlevel': 0 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'entries', + 'fieldtype': 'Table', + 'idx': 21, + 'label': 'Entries', + 'oldfieldname': 'entries', + 'oldfieldtype': 'Table', + 'options': 'Journal Voucher Detail', + 'permlevel': 0, + 'print_hide': 0 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldtype': 'Button', + 'idx': 22, + 'label': 'Get Balance', + 'oldfieldtype': 'Button', + 'permlevel': 0, + 'trigger': 'Client' + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'total_debit', + 'fieldtype': 'Currency', + 'idx': 23, + 'in_filter': 1, + 'label': 'Total Debit', + 'no_copy': 1, + 'oldfieldname': 'total_debit', + 'oldfieldtype': 'Currency', + 'permlevel': 1 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'total_credit', + 'fieldtype': 'Currency', + 'idx': 24, + 'in_filter': 1, + 'label': 'Total Credit', + 'no_copy': 1, + 'oldfieldname': 'total_credit', + 'oldfieldtype': 'Currency', + 'permlevel': 1 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'difference', + 'fieldtype': 'Currency', + 'idx': 25, + 'label': 'Difference', + 'no_copy': 1, + 'oldfieldname': 'difference', + 'oldfieldtype': 'Currency', + 'permlevel': 1, + 'print_hide': 1 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldtype': 'Section Break', + 'idx': 26, + 'label': 'Addtional Info', + 'oldfieldtype': 'Section Break', + 'permlevel': 0 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldtype': 'Column Break', + 'idx': 27, + 'oldfieldtype': 'Column Break', + 'permlevel': 0, + 'width': '50%' + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'bill_no', + 'fieldtype': 'Data', + 'idx': 28, + 'label': 'Bill No', + 'oldfieldname': 'bill_no', + 'oldfieldtype': 'Data', + 'permlevel': 0, + 'print_hide': 1 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'bill_date', + 'fieldtype': 'Date', + 'idx': 29, + 'label': 'Bill Date', + 'oldfieldname': 'bill_date', + 'oldfieldtype': 'Date', + 'permlevel': 0, + 'print_hide': 1 + }, + + # DocField + { + 'colour': 'White:FFF', + 'default': 'No', + 'doctype': 'DocField', + 'fieldname': 'is_opening', + 'fieldtype': 'Select', + 'idx': 30, + 'in_filter': 1, + 'label': 'Is Opening', + 'oldfieldname': 'is_opening', + 'oldfieldtype': 'Select', + 'options': 'No\nYes', + 'permlevel': 0, + 'print_hide': 1, + 'search_index': 1, + 'trigger': 'Client' + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'aging_date', + 'fieldtype': 'Date', + 'idx': 31, + 'label': 'Aging Date', + 'no_copy': 0, + 'oldfieldname': 'aging_date', + 'oldfieldtype': 'Date', + 'permlevel': 0, + 'print_hide': 1 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'cancel_reason', + 'fieldtype': 'Data', + 'idx': 32, + 'label': 'Cancel Reason', + 'no_copy': 1, + 'oldfieldname': 'cancel_reason', + 'oldfieldtype': 'Data', + 'permlevel': 1, + 'print_hide': 1 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'pay_to_recd_from', + 'fieldtype': 'Data', + 'hidden': 0, + 'idx': 33, + 'label': 'Pay To / Recd From', + 'no_copy': 1, + 'permlevel': 0, + 'print_hide': 1, + 'report_hide': 1 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'total_amount', + 'fieldtype': 'Data', + 'hidden': 0, + 'idx': 34, + 'label': 'Total Amount', + 'no_copy': 1, + 'permlevel': 1, + 'print_hide': 1, + 'report_hide': 1 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'total_amount_in_words', + 'fieldtype': 'Data', + 'hidden': 0, + 'idx': 35, + 'label': 'Total Amount in Words', + 'no_copy': 1, + 'permlevel': 1, + 'print_hide': 1, + 'report_hide': 1 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldtype': 'Column Break', + 'idx': 36, + 'oldfieldtype': 'Column Break', + 'permlevel': 0, + 'width': '50%' + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'fiscal_year', + 'fieldtype': 'Select', + 'idx': 37, + 'in_filter': 1, + 'label': 'Fiscal Year', + 'oldfieldname': 'fiscal_year', + 'oldfieldtype': 'Select', + 'options': 'link:Fiscal Year', + 'permlevel': 0, + 'print_hide': 1, + 'reqd': 1, + 'search_index': 1 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'company', + 'fieldtype': 'Link', + 'idx': 38, + 'in_filter': 1, + 'label': 'Company', + 'oldfieldname': 'company', + 'oldfieldtype': 'Link', + 'options': 'Company', + 'permlevel': 0, + 'print_hide': 1, + 'reqd': 1, + 'search_index': 1 + }, + + # DocField + { + 'allow_on_submit': 1, + 'colour': 'White:FFF', + 'doctype': 'DocField', + 'fieldname': 'select_print_heading', + 'fieldtype': 'Link', + 'idx': 39, + 'label': 'Select Print Heading', + 'no_copy': 1, + 'oldfieldname': 'select_print_heading', + 'oldfieldtype': 'Link', + 'options': 'Print Heading', + 'permlevel': 0, + 'print_hide': 1, + 'report_hide': 1, + 'trigger': 'Client' + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldtype': 'Section Break', + 'idx': 40, + 'oldfieldtype': 'Section Break', + 'options': 'Simple', + 'permlevel': 0 + }, + + # DocField + { + 'allow_on_submit': 1, + 'doctype': 'DocField', + 'fieldtype': 'Button', + 'idx': 41, + 'label': 'View Ledger Entry', + 'oldfieldtype': 'Button', + 'permlevel': 0, + 'print_hide': 1, + 'trigger': 'Client' + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldtype': 'Section Break', + 'idx': 42, + 'label': 'TDS', + 'oldfieldtype': 'Section Break', + 'permlevel': 0, + 'print_hide': 0 + }, + + # DocField + { + 'default': 'No', + 'doctype': 'DocField', + 'fieldname': 'tds_applicable', + 'fieldtype': 'Select', + 'idx': 43, + 'in_filter': 1, + 'label': 'TDS Applicable', + 'no_copy': 1, + 'oldfieldname': 'tds_applicable', + 'oldfieldtype': 'Select', + 'options': '\nYes\nNo', + 'permlevel': 0, + 'print_hide': 1, + 'search_index': 1 + }, + + # DocField + { + 'colour': 'White:FFF', + 'doctype': 'DocField', + 'fieldname': 'tds_category', + 'fieldtype': 'Select', + 'hidden': 0, + 'idx': 44, + 'in_filter': 1, + 'label': 'TDS Category', + 'no_copy': 1, + 'oldfieldname': 'tds_category', + 'oldfieldtype': 'Select', + 'options': 'link:TDS Category', + 'permlevel': 0, + 'print_hide': 1, + 'search_index': 1, + 'trigger': 'Client' + }, + + # DocField + { + 'colour': 'White:FFF', + 'doctype': 'DocField', + 'fieldname': 'supplier_account', + 'fieldtype': 'Link', + 'hidden': 0, + 'idx': 45, + 'label': 'Supplier Account', + 'no_copy': 1, + 'oldfieldname': 'supplier_account', + 'oldfieldtype': 'Link', + 'options': 'Account', + 'permlevel': 0, + 'print_hide': 1, + 'trigger': 'Client' + }, + + # DocField + { + 'colour': 'White:FFF', + 'doctype': 'DocField', + 'fieldtype': 'Button', + 'idx': 46, + 'label': 'Get TDS', + 'no_copy': 0, + 'oldfieldtype': 'Button', + 'permlevel': 0, + 'trigger': 'Client' + }, + + # DocField + { + 'colour': 'White:FFF', + 'description': 'Tax Code will be populated based on account head mentioned in TDS Category master', + 'doctype': 'DocField', + 'fieldname': 'tax_code', + 'fieldtype': 'Link', + 'idx': 47, + 'label': 'TDS Account Head', + 'no_copy': 1, + 'oldfieldname': 'tax_code', + 'oldfieldtype': 'Link', + 'options': 'Account', + 'permlevel': 0, + 'print_hide': 1 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'rate', + 'fieldtype': 'Currency', + 'idx': 48, + 'label': 'Rate', + 'no_copy': 1, + 'oldfieldname': 'rate', + 'oldfieldtype': 'Currency', + 'permlevel': 0, + 'print_hide': 1, + 'trigger': 'Client' + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'ded_amount', + 'fieldtype': 'Currency', + 'idx': 49, + 'label': 'Amount', + 'no_copy': 1, + 'oldfieldname': 'ded_amount', + 'oldfieldtype': 'Currency', + 'permlevel': 0, + 'print_hide': 1, + 'trigger': 'Client' + } +] \ No newline at end of file diff --git a/accounts/doctype/lease_agreement/lease_agreement.js b/accounts/doctype/lease_agreement/lease_agreement.js index 8c681a11b26..8ffd522c8d0 100644 --- a/accounts/doctype/lease_agreement/lease_agreement.js +++ b/accounts/doctype/lease_agreement/lease_agreement.js @@ -1,5 +1,17 @@ $.extend(cur_frm.cscript, { Generate: function(doc, dt, dn) { + if(doc.installment_amount==''){ + msgprint('Set Installment Amount before generating schedule'); + return; + } + if(doc.no_of_installments==''){ + msgprint('Set Number of Installments before generating schedule'); + return; + } + if(doc.start_date==''){ + msgprint('Set Start Date before generating schedule'); + return; + } cur_frm.cscript.clear_installments(doc); tot=0;i=0; while(tot '%(date)s') + +group by date_format(due_date,'%M-%Y') + +order by year(due_date),month(due_date) \ No newline at end of file diff --git a/accounts/search_criteria/lease_over_due_list/lease_over_due_list.js b/accounts/search_criteria/lease_over_due_list/lease_over_due_list.js new file mode 100644 index 00000000000..2d89611410e --- /dev/null +++ b/accounts/search_criteria/lease_over_due_list/lease_over_due_list.js @@ -0,0 +1,14 @@ +report.customize_filters = function() { + this.hide_all_filters(); + + this.add_filter({fieldname:'date', label:'Date', fieldtype:'Date', options:'',ignore : 1, parent:'GL Entry', 'in_first_page':1}); + + this.filter_fields_dict['GL Entry'+FILTER_SEP +'From Date'].df['report_default']=dateutil.obj_to_str(new Date()); +// this.filter_fields_dict['GL Entry'+FILTER_SEP +'To Date'].df['report_default']=dateutil.obj_to_str(new Date()); + + this.filter_fields_dict['GL Entry'+FILTER_SEP +'To Date'].df.filter_hide=1; + +} + +$dh(this.mytabs.tabs['More Filters']); +$dh(this.mytabs.tabs['Select Columns']); diff --git a/accounts/search_criteria/lease_over_due_list/lease_over_due_list.py b/accounts/search_criteria/lease_over_due_list/lease_over_due_list.py new file mode 100644 index 00000000000..869d46a55f8 --- /dev/null +++ b/accounts/search_criteria/lease_over_due_list/lease_over_due_list.py @@ -0,0 +1,14 @@ +data =[ + ['Agreement No.','Data','100px',''], + ['Lessee Name','Data','300px',''], + ['Amount','Currency','120px',''], + ['Age','Data','100px',''] + ] + +for d in data: + colnames.append(d[0]) + coltypes.append(d[1]) + colwidths.append(d[2]) + coloptions.append(d[3]) + col_idx[d[0]] = len(colnames)-1 + diff --git a/accounts/search_criteria/lease_over_due_list/lease_over_due_list.sql b/accounts/search_criteria/lease_over_due_list/lease_over_due_list.sql new file mode 100644 index 00000000000..1789f7e5434 --- /dev/null +++ b/accounts/search_criteria/lease_over_due_list/lease_over_due_list.sql @@ -0,0 +1,7 @@ +select la.name,la.account,lai.amount,cast('%(date)s' as date)-due_date as age + +from `tabLease Agreement` la,`tabLease Installment` lai + +where la.name=lai.parent and lai.due_date cast('%(date)s' as date)) + +order by cast('%(date)s' as date)-due_date desc \ No newline at end of file diff --git a/accounts/search_criteria/lease_overdue_age_wise/lease_overdue_age_wise.js b/accounts/search_criteria/lease_overdue_age_wise/lease_overdue_age_wise.js new file mode 100644 index 00000000000..2d89611410e --- /dev/null +++ b/accounts/search_criteria/lease_overdue_age_wise/lease_overdue_age_wise.js @@ -0,0 +1,14 @@ +report.customize_filters = function() { + this.hide_all_filters(); + + this.add_filter({fieldname:'date', label:'Date', fieldtype:'Date', options:'',ignore : 1, parent:'GL Entry', 'in_first_page':1}); + + this.filter_fields_dict['GL Entry'+FILTER_SEP +'From Date'].df['report_default']=dateutil.obj_to_str(new Date()); +// this.filter_fields_dict['GL Entry'+FILTER_SEP +'To Date'].df['report_default']=dateutil.obj_to_str(new Date()); + + this.filter_fields_dict['GL Entry'+FILTER_SEP +'To Date'].df.filter_hide=1; + +} + +$dh(this.mytabs.tabs['More Filters']); +$dh(this.mytabs.tabs['Select Columns']); diff --git a/accounts/search_criteria/lease_overdue_age_wise/lease_overdue_age_wise.py b/accounts/search_criteria/lease_overdue_age_wise/lease_overdue_age_wise.py new file mode 100644 index 00000000000..5e164898419 --- /dev/null +++ b/accounts/search_criteria/lease_overdue_age_wise/lease_overdue_age_wise.py @@ -0,0 +1,16 @@ +data =[ + ['Lessee Name','Data','300px',''], + ['Below 30 Days','Currency','120px',''], + ['Below 90 Days','Currency','120px',''], + ['Below 180 Days','Currency','120px',''], + ['Below 360 Days','Currency','120px',''], + ['Above 360 Days','Currency','120px',''], + ] + +for d in data: + colnames.append(d[0]) + coltypes.append(d[1]) + colwidths.append(d[2]) + coloptions.append(d[3]) + col_idx[d[0]] = len(colnames)-1 + diff --git a/accounts/search_criteria/lease_overdue_age_wise/lease_overdue_age_wise.sql b/accounts/search_criteria/lease_overdue_age_wise/lease_overdue_age_wise.sql new file mode 100644 index 00000000000..2e6912e23ab --- /dev/null +++ b/accounts/search_criteria/lease_overdue_age_wise/lease_overdue_age_wise.sql @@ -0,0 +1,9 @@ +select account,sum(od_30)as od_30,sum(od_90)as od_90,sum(od_180)as od_180,sum(od_360)as od_360,sum(od_1yr)as od_1yr from +( + select account,case when age<=30 then amount end as od_30,case when age between 31 and 90 then amount end as od_90,case when age between 91 and 180 then amount end as od_180,case when age between 181 and 360 then amount end as od_360,case when age>360 then amount end as od_1yr from + ( + select la.account,lai.amount,cast('%(date)s' as date)-due_date as age + from `tabLease Agreement` la,`tabLease Installment` lai + where la.name=lai.parent and lai.due_date<'%(date)s' and (lai.cheque_date is null or lai.cheque_date > '%(date)s') + )a +)b group by account order by account diff --git a/accounts/doctype/loan/__init__.py b/accounts/search_criteria/lease_receipt_summary_month_wise/__init__.py similarity index 100% rename from accounts/doctype/loan/__init__.py rename to accounts/search_criteria/lease_receipt_summary_month_wise/__init__.py diff --git a/accounts/search_criteria/lease_receipt_summary_month_wise/lease_receipt_summary_month_wise.js b/accounts/search_criteria/lease_receipt_summary_month_wise/lease_receipt_summary_month_wise.js new file mode 100644 index 00000000000..4cb3d2b336c --- /dev/null +++ b/accounts/search_criteria/lease_receipt_summary_month_wise/lease_receipt_summary_month_wise.js @@ -0,0 +1,11 @@ +report.customize_filters = function() { + this.hide_all_filters(); + + this.add_filter({fieldname:'date', label:'Date', fieldtype:'Date', options:'',ignore : 1, parent:'GL Entry', 'in_first_page':1}); + + this.filter_fields_dict['GL Entry'+FILTER_SEP +'From Date'].df['report_default']=sys_defaults.year_start_date; + this.filter_fields_dict['GL Entry'+FILTER_SEP +'To Date'].df['report_default']=dateutil.obj_to_str(new Date()); +} + +$dh(this.mytabs.tabs['More Filters']); +$dh(this.mytabs.tabs['Select Columns']); diff --git a/accounts/search_criteria/lease_receipt_summary_month_wise/lease_receipt_summary_month_wise.py b/accounts/search_criteria/lease_receipt_summary_month_wise/lease_receipt_summary_month_wise.py new file mode 100644 index 00000000000..8e5b8ad00bb --- /dev/null +++ b/accounts/search_criteria/lease_receipt_summary_month_wise/lease_receipt_summary_month_wise.py @@ -0,0 +1,13 @@ +data =[ + ['Month','Data','100px',''], + ['Year','Data','100px',''], + ['Amount','Currency','120px',''] + ] + +for d in data: + colnames.append(d[0]) + coltypes.append(d[1]) + colwidths.append(d[2]) + coloptions.append(d[3]) + col_idx[d[0]] = len(colnames)-1 + diff --git a/accounts/search_criteria/lease_receipt_summary_month_wise/lease_receipt_summary_month_wise.sql b/accounts/search_criteria/lease_receipt_summary_month_wise/lease_receipt_summary_month_wise.sql new file mode 100644 index 00000000000..cdd48b8915e --- /dev/null +++ b/accounts/search_criteria/lease_receipt_summary_month_wise/lease_receipt_summary_month_wise.sql @@ -0,0 +1,5 @@ +SELECT date_format(gl.posting_date,'%M'),year(gl.posting_date),sum(gl.credit) as amount +FROM `tabGL Entry` gl, `tabAccount` a +WHERE gl.account=a.name and a.master_type='Customer' and gl.credit>0 and gl.posting_date between '%(date)s' and '%(date1)s' +GROUP BY month(gl.posting_date),year(gl.posting_date) +ORDER BY year(gl.posting_date),month(gl.posting_date) diff --git a/accounts/search_criteria/lease_receipt_summary_year_to_date/lease_receipt_summary_year_to_date.txt b/accounts/search_criteria/lease_receipt_summary_month_wise/lease_receipt_summary_month_wise.txt similarity index 75% rename from accounts/search_criteria/lease_receipt_summary_year_to_date/lease_receipt_summary_year_to_date.txt rename to accounts/search_criteria/lease_receipt_summary_month_wise/lease_receipt_summary_month_wise.txt index c61f17bb656..e6da15c2704 100644 --- a/accounts/search_criteria/lease_receipt_summary_year_to_date/lease_receipt_summary_year_to_date.txt +++ b/accounts/search_criteria/lease_receipt_summary_month_wise/lease_receipt_summary_month_wise.txt @@ -1,4 +1,4 @@ -# Search Criteria, lease_receipt_summary_year_to_date +# Search Criteria, lease_receipt_summary_month_wise [ # These values are common in all dictionaries @@ -13,21 +13,18 @@ # These values are common for all Search Criteria { 'columns': 'GL Entry\x01ID,GL Entry\x01Owner,GL Entry\x01Posting Date,GL Entry\x01Aging Date,GL Entry\x01Account,GL Entry\x01Cost Center,GL Entry\x01Against,GL Entry\x01Against Voucher,GL Entry\x01Voucher Type,GL Entry\x01Voucher No,GL Entry\x01Remarks,GL Entry\x01Is Cancelled,GL Entry\x01Is Opening,GL Entry\x01Fiscal Year,GL Entry\x01Company', - 'criteria_name': 'Lease Receipt Summary (Year to date)', + 'criteria_name': 'Lease Receipt Summary Month Wise', 'doc_type': 'GL Entry', 'doctype': 'Search Criteria', 'filters': "{'GL Entry\x01Voucher Type':'','GL Entry\x01Is Cancelled':'','GL Entry\x01Is Opening':'','GL Entry\x01Fiscal Year':''}", 'module': 'Accounts', 'name': '__common__', - 'page_len': 50, - 'sort_by': '`tabGL Entry`.`company`', - 'sort_order': 'DESC', 'standard': 'Yes' }, - # Search Criteria, lease_receipt_summary_year_to_date + # Search Criteria, lease_receipt_summary_month_wise { 'doctype': 'Search Criteria', - 'name': 'lease_receipt_summary_year_to_date' + 'name': 'lease_receipt_summary_month_wise' } -] \ No newline at end of file +] diff --git a/accounts/search_criteria/lease_receipts_client_wise/lease_receipts_client_wise.js b/accounts/search_criteria/lease_receipts_client_wise/lease_receipts_client_wise.js new file mode 100644 index 00000000000..4cb3d2b336c --- /dev/null +++ b/accounts/search_criteria/lease_receipts_client_wise/lease_receipts_client_wise.js @@ -0,0 +1,11 @@ +report.customize_filters = function() { + this.hide_all_filters(); + + this.add_filter({fieldname:'date', label:'Date', fieldtype:'Date', options:'',ignore : 1, parent:'GL Entry', 'in_first_page':1}); + + this.filter_fields_dict['GL Entry'+FILTER_SEP +'From Date'].df['report_default']=sys_defaults.year_start_date; + this.filter_fields_dict['GL Entry'+FILTER_SEP +'To Date'].df['report_default']=dateutil.obj_to_str(new Date()); +} + +$dh(this.mytabs.tabs['More Filters']); +$dh(this.mytabs.tabs['Select Columns']); diff --git a/accounts/search_criteria/lease_receipts_client_wise/lease_receipts_client_wise.py b/accounts/search_criteria/lease_receipts_client_wise/lease_receipts_client_wise.py new file mode 100644 index 00000000000..b84ff9fe5a7 --- /dev/null +++ b/accounts/search_criteria/lease_receipts_client_wise/lease_receipts_client_wise.py @@ -0,0 +1,12 @@ +data =[ + ['Lessee Name','Data','300px',''], + ['Amount','Currency','120px',''] + ] + +for d in data: + colnames.append(d[0]) + coltypes.append(d[1]) + colwidths.append(d[2]) + coloptions.append(d[3]) + col_idx[d[0]] = len(colnames)-1 + diff --git a/accounts/search_criteria/lease_receipts_client_wise/lease_receipts_client_wise.sql b/accounts/search_criteria/lease_receipts_client_wise/lease_receipts_client_wise.sql new file mode 100644 index 00000000000..f951388aaf8 --- /dev/null +++ b/accounts/search_criteria/lease_receipts_client_wise/lease_receipts_client_wise.sql @@ -0,0 +1,5 @@ +SELECT gl.account,sum(gl.credit) as amount +FROM `tabGL Entry` gl, `tabAccount` a +WHERE gl.account=a.name and a.master_type='Customer' and gl.posting_date between '%(date)s' and '%(date1)s' +GROUP BY gl.account +ORDER BY posting_date diff --git a/accounts/search_criteria/lease_receipts_client_wise/lease_receipts_client_wise.txt b/accounts/search_criteria/lease_receipts_client_wise/lease_receipts_client_wise.txt index ff3194c5a57..44500cc408c 100644 --- a/accounts/search_criteria/lease_receipts_client_wise/lease_receipts_client_wise.txt +++ b/accounts/search_criteria/lease_receipts_client_wise/lease_receipts_client_wise.txt @@ -13,12 +13,13 @@ # These values are common for all Search Criteria { 'columns': 'GL Entry\x01ID,GL Entry\x01Owner,GL Entry\x01Posting Date,GL Entry\x01Aging Date,GL Entry\x01Account,GL Entry\x01Cost Center,GL Entry\x01Against,GL Entry\x01Against Voucher,GL Entry\x01Voucher Type,GL Entry\x01Voucher No,GL Entry\x01Remarks,GL Entry\x01Is Cancelled,GL Entry\x01Is Opening,GL Entry\x01Fiscal Year,GL Entry\x01Company', - 'criteria_name': 'Lease Receipts Client wise', + 'criteria_name': 'Lease Receipts Client Wise', 'doc_type': 'GL Entry', 'doctype': 'Search Criteria', 'filters': "{'GL Entry\x01Voucher Type':'','GL Entry\x01Is Cancelled':'','GL Entry\x01Is Opening':'','GL Entry\x01Fiscal Year':''}", 'module': 'Accounts', 'name': '__common__', + 'page_len': 50, 'standard': 'Yes' }, @@ -27,4 +28,4 @@ 'doctype': 'Search Criteria', 'name': 'lease_receipts_client_wise' } -] \ No newline at end of file +] diff --git a/accounts/search_criteria/lease_yearly_future_installment_inflows/lease_yearly_future_installment_inflows.js b/accounts/search_criteria/lease_yearly_future_installment_inflows/lease_yearly_future_installment_inflows.js new file mode 100644 index 00000000000..2d89611410e --- /dev/null +++ b/accounts/search_criteria/lease_yearly_future_installment_inflows/lease_yearly_future_installment_inflows.js @@ -0,0 +1,14 @@ +report.customize_filters = function() { + this.hide_all_filters(); + + this.add_filter({fieldname:'date', label:'Date', fieldtype:'Date', options:'',ignore : 1, parent:'GL Entry', 'in_first_page':1}); + + this.filter_fields_dict['GL Entry'+FILTER_SEP +'From Date'].df['report_default']=dateutil.obj_to_str(new Date()); +// this.filter_fields_dict['GL Entry'+FILTER_SEP +'To Date'].df['report_default']=dateutil.obj_to_str(new Date()); + + this.filter_fields_dict['GL Entry'+FILTER_SEP +'To Date'].df.filter_hide=1; + +} + +$dh(this.mytabs.tabs['More Filters']); +$dh(this.mytabs.tabs['Select Columns']); diff --git a/accounts/search_criteria/lease_yearly_future_installment_inflows/lease_yearly_future_installment_inflows.py b/accounts/search_criteria/lease_yearly_future_installment_inflows/lease_yearly_future_installment_inflows.py new file mode 100644 index 00000000000..0163ba62f25 --- /dev/null +++ b/accounts/search_criteria/lease_yearly_future_installment_inflows/lease_yearly_future_installment_inflows.py @@ -0,0 +1,12 @@ +data =[ + ['Year','Data','100px',''], + ['Amount','Currency','120px',''] + ] + +for d in data: + colnames.append(d[0]) + coltypes.append(d[1]) + colwidths.append(d[2]) + coloptions.append(d[3]) + col_idx[d[0]] = len(colnames)-1 + diff --git a/accounts/search_criteria/lease_yearly_future_installment_inflows/lease_yearly_future_installment_inflows.sql b/accounts/search_criteria/lease_yearly_future_installment_inflows/lease_yearly_future_installment_inflows.sql new file mode 100644 index 00000000000..ec6c8166d01 --- /dev/null +++ b/accounts/search_criteria/lease_yearly_future_installment_inflows/lease_yearly_future_installment_inflows.sql @@ -0,0 +1,9 @@ +select year(date_sub(due_date,interval 6 MONTH)) as yr,sum(amount) + +from `tabLease Agreement` la,`tabLease Installment` lai + +where la.name=lai.parent and (lai.cheque_date is null or lai.cheque_date > '%(date)s') + +group by year(date_sub(due_date,interval 6 MONTH)) + +order by yr \ No newline at end of file diff --git a/buying/doctype/indent/indent.py b/buying/doctype/indent/indent.py index 450ea641ea6..882098f2380 100644 --- a/buying/doctype/indent/indent.py +++ b/buying/doctype/indent/indent.py @@ -90,12 +90,12 @@ class DocType: # get item details # --------------------------------- def get_item_details(self, arg =''): - return cstr( get_obj(dt='Purchase Common').get_item_details(self,arg) ) + return get_obj(dt='Purchase Common').get_item_details(self,arg) # Get UOM Details # --------------------------------- def get_uom_details(self, arg = ''): - return cstr(get_obj(dt='Purchase Common').get_uom_details(arg)) + return get_obj(dt='Purchase Common').get_uom_details(arg) # GET TERMS & CONDITIONS #----------------------------- diff --git a/buying/doctype/purchase_common/purchase_common.py b/buying/doctype/purchase_common/purchase_common.py index fe8c8e69a70..29658cba48c 100644 --- a/buying/doctype/purchase_common/purchase_common.py +++ b/buying/doctype/purchase_common/purchase_common.py @@ -84,7 +84,7 @@ class DocType(TransactionBase): # ********** get primary contact details (this is done separately coz. , in case there is no primary contact thn it would not be able to fetch customer details in case of join query) contact_det = sql("select contact_name, contact_no, email_id from `tabContact` where supplier = '%s' and is_supplier = 1 and is_primary_contact = 'Yes' and docstatus != 2" %(name), as_dict = 1) ret['contact_person'] = contact_det and contact_det[0]['contact_name'] or '' - return cstr(ret) + return ret else: msgprint("Supplier : %s does not exists" % (name)) raise Exception @@ -142,14 +142,14 @@ class DocType(TransactionBase): ret['purchase_rate'] = item and flt(item[0]['last_purchase_rate']) or 0 ret['import_rate'] = flt(item and flt(item[0]['last_purchase_rate']) or 0) / flt(obj.doc.fields.has_key('conversion_rate') and flt(obj.doc.conversion_rate) or 1) - return cstr(ret) + return ret # Get Available Qty at Warehouse def get_bin_details( self, arg = ''): arg = eval(arg) bin = sql("select projected_qty from `tabBin` where item_code = %s and warehouse = %s", (arg['item_code'], arg['warehouse']), as_dict=1) ret = { 'projected_qty' : bin and flt(bin[0]['projected_qty']) or 0 } - return str(ret) + return ret # Get UOM Details def get_uom_details(self, arg = ''): @@ -163,7 +163,7 @@ class DocType(TransactionBase): 'purchase_rate' : (lpr and flt(lpr[0]['last_purchase_rate']) * flt(uom[0]['conversion_factor'])) or 0 } - return str(ret) + return ret # get last purchase rate def get_last_purchase_rate( self, obj): @@ -522,7 +522,7 @@ class DocType(TransactionBase): 'rate' : rate and (rate[0]['account_type'] == 'Tax' and not arg['charge_type'] == 'Actual') and flt(rate[0]['tax_rate']) or 0 } #msgprint(ret) - return cstr(ret) + return ret diff --git a/buying/doctype/purchase_order/purchase_order.py b/buying/doctype/purchase_order/purchase_order.py index 7d9e1da03be..1a5d2d73e7f 100644 --- a/buying/doctype/purchase_order/purchase_order.py +++ b/buying/doctype/purchase_order/purchase_order.py @@ -38,23 +38,17 @@ class DocType(TransactionBase): get_obj(dt = 'Purchase Common').validate_fiscal_year(self.doc.fiscal_year,self.doc.transaction_date,'PO Date') - # Client Trigger Functions - #---------------------------------------------------------------------------------------------------- - # Get Supplier Details - #def get_supplier_details(self, name = ''): - #return cstr(get_obj(dt='Purchase Common').get_supplier_details(name)) - # Get Item Details def get_item_details(self, arg =''): - return cstr(get_obj(dt='Purchase Common').get_item_details(self,arg)) + return get_obj(dt='Purchase Common').get_item_details(self,arg) # Get UOM Details def get_uom_details(self, arg = ''): - return cstr(get_obj(dt='Purchase Common').get_uom_details(arg)) + return get_obj(dt='Purchase Common').get_uom_details(arg) # get available qty at warehouse def get_bin_details(self, arg = ''): - return cstr(get_obj(dt='Purchase Common').get_bin_details(arg)) + return get_obj(dt='Purchase Common').get_bin_details(arg) # Pull Indent def get_indent_details(self): diff --git a/buying/doctype/supplier_quotation/supplier_quotation.py b/buying/doctype/supplier_quotation/supplier_quotation.py index 0c659bc1d52..ac594303066 100755 --- a/buying/doctype/supplier_quotation/supplier_quotation.py +++ b/buying/doctype/supplier_quotation/supplier_quotation.py @@ -18,7 +18,7 @@ class DocType: 'supplier_name' : cd and cd[0][4] or '', 'supplier_address': cd and cd[0][5] or '' } - return cstr(ret) + return ret def get_rfq_details(self): self.doc.clear_table(self.doclist, 'supplier_quotation_details') @@ -28,12 +28,12 @@ class DocType: def update_approval_status(self): if not self.doc.approval_status or self.doc.approval_status == 'Not Approved': set(self.doc, 'approval_status','Approved') - return cstr(self.doc.approval_status) + return self.doc.approval_status elif self.doc.approval_status == 'Approved': pc_obj = get_obj('Purchase Common') pc_obj.check_docstatus(check = 'Next', doctype = 'Purchase Order', docname = self.doc.name, detail_doctype = 'PO Detail') set(self.doc, 'approval_status', 'Not Approved') - return cstr(self.doc.approval_status) + return self.doc.approval_status def validate_item_list(self): if not getlist(self.doclist, 'supplier_quotation_details'): @@ -101,4 +101,4 @@ class DocType: # Get Supplier Details # -------------------- def get_supplier_details(self, name = ''): - return cstr(get_obj('Purchase Common').get_supplier_details(name)) \ No newline at end of file + return get_obj('Purchase Common').get_supplier_details(name) \ No newline at end of file diff --git a/accounts/doctype/loan_installment/__init__.py b/home/page/dashboard/__init__.py similarity index 100% rename from accounts/doctype/loan_installment/__init__.py rename to home/page/dashboard/__init__.py diff --git a/home/page/dashboard/dashboard.css b/home/page/dashboard/dashboard.css new file mode 100644 index 00000000000..d8e8b54d18b --- /dev/null +++ b/home/page/dashboard/dashboard.css @@ -0,0 +1,12 @@ +div.dashboard_table td { + width: 50%; +} + +div.dashboard-title { + font-weight: bold; + padding: '3px 0px'; +} + +div.dashboard-graph { + height: 180px; +} \ No newline at end of file diff --git a/home/page/dashboard/dashboard.html b/home/page/dashboard/dashboard.html new file mode 100644 index 00000000000..5ffef2f7b2c --- /dev/null +++ b/home/page/dashboard/dashboard.html @@ -0,0 +1,8 @@ +
+
+
+ +
Loading...
+
+
+
\ No newline at end of file diff --git a/home/page/dashboard/dashboard.js b/home/page/dashboard/dashboard.js new file mode 100644 index 00000000000..c5dd36150e1 --- /dev/null +++ b/home/page/dashboard/dashboard.js @@ -0,0 +1,139 @@ +pscript.onload_dashboard = function() { + // load jqplot + $.scriptPath = 'js/' + $.require(['jquery/jquery.jqplot.min.js', + 'jquery/jqplot-plugins/jqplot.barRenderer.js', + 'jquery/jqplot-plugins/jqplot.canvasAxisTickRenderer.min.js', + 'jquery/jqplot-plugins/jqplot.canvasTextRenderer.min.js', + 'jquery/jqplot-plugins/jqplot.categoryAxisRenderer.min.js']); + + + pscript.dashboard_settings = { + company: sys_defaults.company, + start: dateutil.obj_to_str(dateutil.add_days(new Date(), -60)), + end: dateutil.obj_to_str(new Date()), + interval: 7 + } + + var ph = new PageHeader($('.dashboard .header').get(0), 'Dashboards'); + var db = new Dashboard(); + + ph.add_button('Settings', db.show_settings); + + db.refresh(); + +} + +Dashboard = function() { + var me = this; + $.extend(me, { + refresh: function() { + $('.dashboard .help_box').css('display', 'block'); + $c_page('home', 'dashboard', 'load_dashboard', JSON.stringify(pscript.dashboard_settings), function(r,rt) { + $('.dashboard .help_box').css('display', 'none'); + me.render(r.message); + }) + }, + + render: function(data) { + $('.dashboard_table').html(''); + var t = make_table($('.dashboard_table').get(0), 4, 2, '100%', ['50%', '50%'], {padding: '5px'}); + var ridx=0; var cidx=0; + for(var i=0; i< data.length; i++) { + // switch columns and rows + if(cidx==2) { cidx=0; ridx++} + + // give an id! + var cell = $td(t,ridx,cidx); + var title = $a(cell, 'div', 'dashboard-title', '', data[i][0].title); + var parent = $a(cell, 'div', 'dashboard-graph') + + parent.id = '_dashboard' + ridx + '-' + cidx; + + // render graph + me.render_graph(parent.id, data[i][1]); + cidx++; + } + }, + + render_graph: function(parent, values) { + var vl = []; + $.each(values, function(i,v) { + vl.push([dateutil.str_to_user(v[0]), v[1]]); + }); + $.jqplot(parent, [vl], { + seriesDefaults:{ + renderer:$.jqplot.BarRenderer, + rendererOptions: {fillToZero: true}, + }, + axes: { + // Use a category axis on the x axis and use our custom ticks. + xaxis: { + min: 0, + renderer: $.jqplot.CategoryAxisRenderer, + tickRenderer: $.jqplot.CanvasAxisTickRenderer, + tickOptions: { + angle: -30, + fontSize: '8pt' + } + }, + // Pad the y axis just a little so bars can get close to, but + // not touch, the grid boundaries. 1.2 is the default padding. + yaxis: { + min: 0, + pad: 1.05, + tickOptions: {formatString: '%d'} + } + } + }); + }, + + show_settings: function() { + var d = new wn.widgets.Dialog({ + title: 'Set Company Settings', + width: 500, + fields: [ + { + label:'Company', + reqd: 1, + fieldname:'company', + fieldtype:'Link', + options: 'Company' + }, + { + label:'Start Date', + reqd: 1, + fieldname:'start', + fieldtype:'Date', + }, + { + label:'End Date', + reqd: 1, + fieldname:'end', + fieldtype:'Date', + }, + { + label:'Interval', + reqd: 1, + fieldname:'interval', + fieldtype:'Int' + }, + { + label:'Regenerate', + fieldname:'refresh', + fieldtype:'Button' + } + ] + }); + d.onshow = function() { + d.set_values(pscript.dashboard_settings); + } + d.fields_dict.refresh.input.onclick = function() { + pscript.dashboard_settings = d.get_values(); + me.refresh(); + d.hide(); + } + d.show(); + } + }) +} diff --git a/home/page/dashboard/dashboard.py b/home/page/dashboard/dashboard.py new file mode 100644 index 00000000000..2c76b15630c --- /dev/null +++ b/home/page/dashboard/dashboard.py @@ -0,0 +1,220 @@ +dashboards = [ + { + 'type': 'account', + 'account': 'Income', + 'title': 'Income' + }, + + { + 'type': 'account', + 'account': 'Expenses', + 'title': 'Expenses' + }, + + { + 'type': 'from_company', + 'account': 'receivables_group', + 'title': 'Receivables' + }, + + { + 'type': 'from_company', + 'account': 'payables_group', + 'title': 'Payables' + }, + + { + 'type': 'cash', + 'debit_or_credit': 'Debit', + 'title': 'Cash Inflow' + }, + + { + 'type': 'cash', + 'debit_or_credit': 'Credit', + 'title': 'Cash Outflow' + }, + + { + 'type': 'creation', + 'doctype': 'Quotation', + 'title': 'New Quotations' + }, + + { + 'type': 'creation', + 'doctype': 'Sales Order', + 'title': 'New Orders' + } +] + + +class DashboardWidget: + def __init__(self, company, start, end, interval): + import webnotes + from webnotes.utils import getdate + from webnotes.model.code import get_obj + + self.company = company + self.abbr = webnotes.conn.get_value('Company', company, 'abbr') + self.start = getdate(start) + self.end = getdate(end) + + self.interval = interval + self.fiscal_year = webnotes.conn.sql(""" + select name from `tabFiscal Year` + where year_start_date <= %s and + DATE_ADD(year_start_date, INTERVAL 1 YEAR) >= %s + """, (start, start))[0][0] + self.glc = get_obj('GL Control') + self.cash_accounts = [d[0] for d in webnotes.conn.sql(""" + select name from tabAccount + where account_type='Bank or Cash' + and company = %s and docstatus = 0 + """, company)] + + def timeline(self): + """ + get the timeline for the dashboard + """ + import webnotes + from webnotes.utils import add_days + tl = [] + + if self.start > self.end: + webnotes.msgprint("Start must be before end", raise_exception=1) + + curr = self.start + tl.append(curr) + + while curr < self.end: + curr = add_days(curr, self.interval, 'date') + tl.append(curr) + + tl.append(self.end) + + return tl + + def generate(self, opts): + """ + Generate the dasboard + """ + tl = self.timeline() + self.out = [] + + for i in range(len(tl)-1): + self.out.append([tl[i+1].strftime('%Y-%m-%d'), self.value(opts, tl[i], tl[i+1]) or 0]) + + return self.out + + def get_account_balance(self, acc, start): + """ + Get as on account balance + """ + import webnotes + # add abbreviation to company + + if not acc.endswith(self.abbr): + acc += ' - ' + self.abbr + + # get other reqd parameters + try: + globals().update(webnotes.conn.sql('select debit_or_credit, lft, rgt from tabAccount where name=%s', acc, as_dict=1)[0]) + except Exception,e: + webnotes.msgprint('Wrongly defined account: ' + acc) + print acc + raise e + + return self.glc.get_as_on_balance(acc, self.fiscal_year, start, debit_or_credit, lft, rgt) + + def get_creation_trend(self, doctype, start, end): + """ + Get creation # of creations in period + """ + import webnotes + return int(webnotes.conn.sql(""" + select count(*) from `tab%s` where creation between %s and %s and docstatus=1 + """ % (doctype, '%s','%s'), (start, end))[0][0]) + + def get_account_amt(self, acc, start, end, debit_or_credit): + """ + Get debit, credit over a period + """ + import webnotes + # add abbreviation to company + + if not acc.endswith(self.abbr): + acc += ' - ' + self.abbr + + ret = webnotes.conn.sql(""" + select ifnull(sum(ifnull(t1.debit,0)),0), ifnull(sum(ifnull(t1.credit,0)),0) + from `tabGL Entry` t1, tabAccount t2 + where t1.account = t2.name + and t2.is_pl_account = 'Yes' + and t2.debit_or_credit=%s + and ifnull(t1.is_cancelled, 'No')='No' + and t1.posting_date between %s and %s + """, (debit_or_credit, start, end))[0] + + return debit_or_credit=='Credit' and float(ret[1]-ret[0]) or float(ret[0]-ret[1]) + + def value(self, opts, start, end): + """ + Value of the series on a particular date + """ + import webnotes + if opts['type']=='account': + debit_or_credit = 'Debit' + if opts['account']=='Income': + debit_or_credit = 'Credit' + + return self.get_account_amt(opts['account'], start, end, debit_or_credit) + + elif opts['type']=='from_company': + acc = webnotes.conn.get_value('Company', self.company, \ + opts['account'].split('.')[-1]) + + return self.get_account_balance(acc, start)[2] + + elif opts['type']=='cash': + if opts['debit_or_credit']=='Credit': + return sum([self.get_account_amt(acc, start, end, opts['debit_or_credit']) for acc in self.cash_accounts]) or 0 + elif opts['debit_or_credit']=='Debit': + return sum([self.get_account_amt(acc, start, end, opts['debit_or_credit']) for acc in self.cash_accounts]) or 0 + + elif opts['type']=='creation': + return self.get_creation_trend(opts['doctype'], start, end) + + +def load_dashboard(args): + """ + Get dashboard based on + 1. Company (default company) + 2. Start Date (last 3 months) + 3. End Date (today) + 4. Interval (7 days) + """ + dl = [] + import json + args = json.loads(args) + dw = DashboardWidget(args['company'], args['start'], args['end'], int(args['interval'])) + + # render the dashboards + for d in dashboards: + dl.append([d, dw.generate(d)]) + + return dl + +if __name__=='__main__': + import sys + sys.path.append('/var/www/webnotes/wnframework/cgi-bin') + from webnotes.db import Database + import webnotes + webnotes.conn = Database(use_default=1) + webnotes.session = {'user':'Administrator'} + print load_dashboard("""{ + "company": "My Test", + "start": "2011-05-01", + "end": "2011-08-01", + "interval": "7" + }""") \ No newline at end of file diff --git a/home/page/dashboard/dashboard.txt b/home/page/dashboard/dashboard.txt new file mode 100644 index 00000000000..46bc2bc0bce --- /dev/null +++ b/home/page/dashboard/dashboard.txt @@ -0,0 +1,49 @@ +# Page, dashboard +[ + + # These values are common in all dictionaries + { + 'creation': '2011-08-25 16:22:44', + 'docstatus': 0, + 'modified': '2011-08-25 16:22:54', + 'modified_by': 'Administrator', + 'owner': 'Administrator' + }, + + # These values are common for all Page + { + 'category': 'Standard', + 'doctype': 'Page', + 'module': 'Home', + 'name': '__common__', + 'page_name': 'Dashboard', + 'standard': 'Yes' + }, + + # These values are common for all Page Role + { + 'doctype': 'Page Role', + 'name': '__common__', + 'parent': 'dashboard', + 'parentfield': 'roles', + 'parenttype': 'Page' + }, + + # Page, dashboard + { + 'doctype': 'Page', + 'name': 'dashboard' + }, + + # Page Role + { + 'doctype': 'Page Role', + 'role': 'System Manager' + }, + + # Page Role + { + 'doctype': 'Page Role', + 'role': 'Accounts Manager' + } +] \ No newline at end of file diff --git a/home/page/event_updates/event_updates.css b/home/page/event_updates/event_updates.css index ed503519732..a88fed48b16 100644 --- a/home/page/event_updates/event_updates.css +++ b/home/page/event_updates/event_updates.css @@ -14,4 +14,49 @@ span.home-status-unread { font-size: 11px; color: #FFF; background-color: RED; -} \ No newline at end of file +} + +div.setup-wizard { + display: none; + margin: 13px 0px; + background-color: #FED; + padding: 13px; +} + +div.setup-wizard .header { + font-size: 12px; + font-weight: bold; + color: #322; + margin-bottom: 7px; +} + + +div.setup-wizard .percent-outer { + height: 17px; + background-color: #FFF; + border: 2px solid #322; +} + +div.setup-wizard .percent-inner { + height: 17px; + background-color: GREEN; +} + +div.setup-wizard .suggestion { + margin: 7px 0px; + color: #322; +} + +div.setup-wizard .prev-next { + height: 13px; +} + +div.setup-wizard .prev-next span { + display: none; + float: right; + margin-left: 13px; + color: #877; + font-size: 11px; +} + + diff --git a/home/page/event_updates/event_updates.js b/home/page/event_updates/event_updates.js index 7ecfbdcf3cb..1574f537ef6 100644 --- a/home/page/event_updates/event_updates.js +++ b/home/page/event_updates/event_updates.js @@ -24,8 +24,8 @@ pscript.home_make_body = function() { wrapper.head = $a(wrapper.body, 'div'); wrapper.banner_area = $a(wrapper.head, 'div'); - wrapper.toolbar_area = $a(wrapper.head, 'div'); + wrapper.setup_wizard_area = $a(wrapper.body, 'div', 'setup-wizard') wrapper.system_message_area = $a(wrapper.body, 'div', '', {marginBottom:'16px', padding:'8px', backgroundColor:'#FFD', border:'1px dashed #AA6', display:'none'}) @@ -612,7 +612,6 @@ pscript.home_make_status = function() { // get values $c_page('home', 'event_updates', 'get_status_details', user, function(r,rt) { - home_status_bar.render(r.message); // system_messages @@ -622,6 +621,11 @@ pscript.home_make_status = function() { // render online users pscript.online_users_obj.render(r.message.online_users); pscript.online_users = r.message.online_users; + + // setup wizard + if(r.message.setup_status) { + new SetupWizard(r.message.setup_status) + } } ); } @@ -633,7 +637,7 @@ pscript.show_system_message = function(wrapper, msg) { var txt = $a(wrapper.system_message_area, 'div', '', {lineHeight:'1.6em'}); txt.innerHTML = msg; - var span = $ln($a(wrapper.system_message_area, 'div'), 'Dismiss', + var span = $ln($a(wrapper.system_message_area, 'div', '', {textAlign:'right'}), 'Dismiss'.bold(), function(me) { me.set_working(); $c_obj('Home Control', 'dismiss_message', '', function(r,rt) { @@ -729,3 +733,53 @@ pscript.validate_fields = function(d) if(!flag) alert(msg); return flag; } + +SetupWizard = function(status) { + var me = this; + $.extend(this, { + make: function(status) { + me.status = status; + me.wrapper = page_body.pages['Event Updates'].setup_wizard_area; + $ds(me.wrapper); + me.make_percent(status.percent); + me.make_suggestion(status.ret); + }, + make_percent: function(percent) { + $a(me.wrapper, 'div', 'header', {}, 'Your setup is '+percent+'% complete'); + var o = $a(me.wrapper, 'div', 'percent-outer'); + $a(o, 'div', 'percent-inner', {width:percent + '%'}); + }, + make_suggestion: function(ret) { + me.suggest_area = $a(me.wrapper, 'div', 'suggestion'); + if(me.status.ret.length>1) { + me.prev_next = $a(me.wrapper, 'div', 'prev-next'); + + // next + me.next = $a(me.prev_next, 'span', 'link_type', null, 'Next Suggestion', + function() { me.show_suggestion(me.cur_sugg+1) }); + + // prev + me.prev = $a(me.prev_next, 'span', 'link_type', null, 'Previous Suggestion', + function() { me.show_suggestion(me.cur_sugg-1) }); + + } + if(me.status.ret.length) { + me.show_suggestion(0); + } else { + me.suggest_area.innerHTML = 'Congratulations: '.bold() + 'You are now on your track... Good luck'; + } + }, + show_suggestion: function(idx) { + me.cur_sugg = idx; + me.suggest_area.innerHTML = 'What you can do next: '.bold() + me.status.ret[idx]; + + // show hide prev, next + if(me.status.ret.length>1) { + $dh(me.prev); $dh(me.next); + if(idx>0) $ds(me.prev); + if(idx'\ + +webnotes.conn.get_value('Control Panel', None, 'company_name')): + ret.append('Upload your company banner') + else: + percent += 20 + + def check_type(doctype, ret, percent): + if not webnotes.conn.sql("select count(*) from tab%s" % doctype)[0][0]: + ret.append(''' + + Create a new %(dt)s + or + + Import from a spreadsheet''' % {'dt':doctype}) + else: + percent += 20 + return ret, percent + + ret, percent = check_type('Item', ret, percent) + ret, percent = check_type('Customer', ret, percent) + ret, percent = check_type('Supplier', ret, percent) + + if percent==100: + webnotes.conn.set_global('setup_done', '1') + return '' + + return {'ret': ret, 'percent': percent} + \ No newline at end of file diff --git a/home/page/my_company/my_company.js b/home/page/my_company/my_company.js index 08506076440..c2a55eab03c 100644 --- a/home/page/my_company/my_company.js +++ b/home/page/my_company/my_company.js @@ -134,24 +134,28 @@ MemberList.prototype.make_search = function() { MemberList.prototype.make_list = function() { var me = this; this.lst_area = $a(this.list_wrapper, 'div'); - this.lst = new Listing('Profiles',1); - this.lst.colwidths = ['100%']; - this.lst.opts.cell_style = {padding:'0px'} - this.lst.get_query = function() { - var c1 = ''; - if(me.search_inp.value && me.search_inp.value != 'Search') { - var c1 = repl(' AND (first_name LIKE "%(txt)s" OR last_name LIKE "%(txt)s" OR name LIKE "%(txt)s")', {txt:'%' + me.search_inp.value + '%'}); + + this.lst = new wn.widgets.Listing({ + parent: this.lst_area, + as_dict: 1, + get_query: function() { + var c1 = ''; + if(me.search_inp.value && me.search_inp.value != 'Search') { + var c1 = repl(' AND (first_name LIKE "%(txt)s" OR last_name LIKE "%(txt)s" OR name LIKE "%(txt)s")', {txt:'%' + me.search_inp.value + '%'}); + } + + return repl("SELECT name, \ + ifnull(concat_ws(' ', first_name, last_name),'') as full_name, \ + gender, file_list, enabled \ + FROM tabProfile \ + WHERE docstatus != 2 \ + AND name not in ('Guest','Administrator') %(cond)s \ + ORDER BY name asc",{cond:c1}); + }, + render_row: function(parent, data) { + me.member_items[data.name] = new MemberItem(parent, data, me); } - - this.query = repl("SELECT distinct ifnull(name,''), ifnull(concat_ws(' ', first_name, last_name),''), \ - ifnull(messanger_status,''), ifnull(gender,''), ifnull(file_list,''), 0, enabled, last_login \ - from tabProfile where docstatus != 2 AND name not in ('Guest','Administrator') %(cond)s \ - ORDER BY name asc",{cond:c1}); - } - this.lst.make(this.lst_area); - this.lst.show_cell= function(cell, ri, ci, d) { - me.member_items[d[ri][0]] = new MemberItem(cell, d[ri], me); - } + }); this.lst.run(); } @@ -186,14 +190,14 @@ MemberItem = function(parent, det, mlist) { var me = this; this.det = det; this.wrapper = $a(parent, 'div'); - this.enabled = det[6]; + this.enabled = det.enabled; this.tab = make_table(this.wrapper, 1,2,'100%', ['20%', '70%'], {padding:'4px', overflow:'hidden'}); $y(this.tab, {tableLayout:'fixed', borderCollapse:'collapse'}) this.is_online = function() { for(var i=0;iEmergency Contact Details', 'permlevel': 0 @@ -643,7 +620,7 @@ 'doctype': 'DocField', 'fieldname': 'person_to_be_contacted', 'fieldtype': 'Data', - 'idx': 41, + 'idx': 40, 'label': 'Person To Be Contacted', 'permlevel': 0 }, @@ -653,7 +630,7 @@ 'doctype': 'DocField', 'fieldname': 'relation', 'fieldtype': 'Data', - 'idx': 42, + 'idx': 41, 'label': 'Relation', 'permlevel': 0 }, @@ -663,7 +640,7 @@ 'doctype': 'DocField', 'fieldname': 'emergency_phone_number', 'fieldtype': 'Data', - 'idx': 43, + 'idx': 42, 'label': 'Emergency Phone Number', 'permlevel': 0 }, @@ -672,7 +649,7 @@ { 'doctype': 'DocField', 'fieldtype': 'Column Break', - 'idx': 44, + 'idx': 43, 'permlevel': 0, 'width': '50%' }, @@ -682,7 +659,7 @@ 'doctype': 'DocField', 'fieldname': 'permanent_accommodation_type', 'fieldtype': 'Select', - 'idx': 45, + 'idx': 44, 'label': 'Permanent Accommodation Type', 'options': '\nRented\nOwned', 'permlevel': 0 @@ -693,7 +670,7 @@ 'doctype': 'DocField', 'fieldname': 'permanent_address', 'fieldtype': 'Small Text', - 'idx': 46, + 'idx': 45, 'label': 'Permanent Address', 'permlevel': 0 }, @@ -703,7 +680,7 @@ 'doctype': 'DocField', 'fieldname': 'current_accommodation_type', 'fieldtype': 'Select', - 'idx': 47, + 'idx': 46, 'label': 'Current Accommodation Type', 'options': '\nRented\nOwned', 'permlevel': 0 @@ -714,7 +691,7 @@ 'doctype': 'DocField', 'fieldname': 'current_address', 'fieldtype': 'Small Text', - 'idx': 48, + 'idx': 47, 'label': 'Current Address', 'permlevel': 0 }, @@ -723,7 +700,7 @@ { 'doctype': 'DocField', 'fieldtype': 'Section Break', - 'idx': 49, + 'idx': 48, 'label': 'Personal Details', 'permlevel': 0 }, @@ -732,7 +709,7 @@ { 'doctype': 'DocField', 'fieldtype': 'Column Break', - 'idx': 50, + 'idx': 49, 'permlevel': 0, 'width': '50%' }, @@ -742,7 +719,7 @@ 'doctype': 'DocField', 'fieldname': 'pan_number', 'fieldtype': 'Data', - 'idx': 51, + 'idx': 50, 'label': 'PAN Number', 'permlevel': 0 }, @@ -752,7 +729,7 @@ 'doctype': 'DocField', 'fieldname': 'passport_number', 'fieldtype': 'Data', - 'idx': 52, + 'idx': 51, 'label': 'Passport Number', 'permlevel': 0 }, @@ -763,7 +740,7 @@ 'doctype': 'DocField', 'fieldtype': 'Button', 'hidden': 1, - 'idx': 53, + 'idx': 52, 'label': 'Employee Profile', 'oldfieldtype': 'Button', 'permlevel': 0, @@ -775,7 +752,7 @@ 'doctype': 'DocField', 'fieldname': 'date_of_issue', 'fieldtype': 'Date', - 'idx': 54, + 'idx': 53, 'label': 'Date of Issue', 'permlevel': 0 }, @@ -785,7 +762,7 @@ 'doctype': 'DocField', 'fieldname': 'valid_upto', 'fieldtype': 'Date', - 'idx': 55, + 'idx': 54, 'label': 'Valid Upto', 'permlevel': 0 }, @@ -796,7 +773,7 @@ 'doctype': 'DocField', 'fieldtype': 'Button', 'hidden': 1, - 'idx': 56, + 'idx': 55, 'label': 'Salary Structure', 'oldfieldtype': 'Button', 'permlevel': 0, @@ -808,7 +785,7 @@ 'doctype': 'DocField', 'fieldname': 'place_of_issue', 'fieldtype': 'Data', - 'idx': 57, + 'idx': 56, 'label': 'Place of Issue', 'permlevel': 0 }, @@ -818,7 +795,7 @@ 'doctype': 'DocField', 'fieldname': 'marital_status', 'fieldtype': 'Select', - 'idx': 58, + 'idx': 57, 'label': 'Marital Status', 'options': '\nSingle\nMarried\nDivorced\nWidowed', 'permlevel': 0 @@ -829,7 +806,7 @@ 'doctype': 'DocField', 'fieldname': 'blood_group', 'fieldtype': 'Select', - 'idx': 59, + 'idx': 58, 'label': 'Blood Group', 'options': '\nA+\nA-\nB+\nB-\nAB+\nAB-\nO+\nO-', 'permlevel': 0 @@ -839,7 +816,7 @@ { 'doctype': 'DocField', 'fieldtype': 'Column Break', - 'idx': 60, + 'idx': 59, 'permlevel': 0, 'width': '50%' }, @@ -851,7 +828,7 @@ 'doctype': 'DocField', 'fieldname': 'family_background', 'fieldtype': 'Small Text', - 'idx': 61, + 'idx': 60, 'label': 'Family Background', 'permlevel': 0 }, @@ -863,7 +840,7 @@ 'doctype': 'DocField', 'fieldname': 'health_details', 'fieldtype': 'Small Text', - 'idx': 62, + 'idx': 61, 'label': 'Health Details', 'permlevel': 0 }, @@ -872,7 +849,7 @@ { 'doctype': 'DocField', 'fieldtype': 'Section Break', - 'idx': 63, + 'idx': 62, 'label': 'Educational Qualification', 'permlevel': 0 }, @@ -882,7 +859,7 @@ 'doctype': 'DocField', 'fieldname': 'educational_qualification_details', 'fieldtype': 'Table', - 'idx': 64, + 'idx': 63, 'label': 'Educational Qualification Details', 'options': 'Educational Qualifications Detail', 'permlevel': 0 @@ -892,7 +869,7 @@ { 'doctype': 'DocField', 'fieldtype': 'Section Break', - 'idx': 65, + 'idx': 64, 'label': 'Career History', 'permlevel': 0 }, @@ -901,7 +878,7 @@ { 'doctype': 'DocField', 'fieldtype': 'Section Break', - 'idx': 66, + 'idx': 65, 'label': 'Previous Work Experience', 'options': 'Simple', 'permlevel': 0 @@ -912,7 +889,7 @@ 'doctype': 'DocField', 'fieldname': 'previous_experience_details', 'fieldtype': 'Table', - 'idx': 67, + 'idx': 66, 'label': 'Previous Experience Details', 'options': 'Previous Experience Detail', 'permlevel': 0 @@ -922,7 +899,7 @@ { 'doctype': 'DocField', 'fieldtype': 'Section Break', - 'idx': 68, + 'idx': 67, 'label': 'History In Company', 'options': 'Simple', 'permlevel': 0 @@ -933,7 +910,7 @@ 'doctype': 'DocField', 'fieldname': 'experience_in_company_details', 'fieldtype': 'Table', - 'idx': 69, + 'idx': 68, 'label': 'Experience In Company Details', 'options': 'Experience In Company Detail', 'permlevel': 0 @@ -943,7 +920,7 @@ { 'doctype': 'DocField', 'fieldtype': 'Section Break', - 'idx': 70, + 'idx': 69, 'label': 'Exit', 'oldfieldtype': 'Section Break', 'permlevel': 0 @@ -953,7 +930,7 @@ { 'doctype': 'DocField', 'fieldtype': 'Column Break', - 'idx': 71, + 'idx': 70, 'permlevel': 0, 'width': '50%' }, @@ -963,7 +940,7 @@ 'doctype': 'DocField', 'fieldname': 'resignation_letter_date', 'fieldtype': 'Date', - 'idx': 72, + 'idx': 71, 'label': 'Resignation Letter Date', 'oldfieldname': 'resignation_letter_date', 'oldfieldtype': 'Date', @@ -975,7 +952,7 @@ 'doctype': 'DocField', 'fieldname': 'relieving_date', 'fieldtype': 'Date', - 'idx': 73, + 'idx': 72, 'in_filter': 1, 'label': 'Relieving Date', 'oldfieldname': 'relieving_date', @@ -988,7 +965,7 @@ 'doctype': 'DocField', 'fieldname': 'reason_for_leaving', 'fieldtype': 'Data', - 'idx': 74, + 'idx': 73, 'label': 'Reason for Leaving', 'oldfieldname': 'reason_for_leaving', 'oldfieldtype': 'Data', @@ -1000,7 +977,7 @@ 'doctype': 'DocField', 'fieldname': 'leave_encashed', 'fieldtype': 'Select', - 'idx': 75, + 'idx': 74, 'label': 'Leave Encashed?', 'oldfieldname': 'leave_encashed', 'oldfieldtype': 'Select', @@ -1013,7 +990,7 @@ 'doctype': 'DocField', 'fieldname': 'encashment_date', 'fieldtype': 'Date', - 'idx': 76, + 'idx': 75, 'label': 'Encashment Date', 'oldfieldname': 'encashment_date', 'oldfieldtype': 'Date', @@ -1024,7 +1001,7 @@ { 'doctype': 'DocField', 'fieldtype': 'Column Break', - 'idx': 77, + 'idx': 76, 'label': 'Exit Interview Details', 'oldfieldname': 'col_brk6', 'oldfieldtype': 'Column Break', @@ -1037,7 +1014,7 @@ 'doctype': 'DocField', 'fieldname': 'held_on', 'fieldtype': 'Date', - 'idx': 78, + 'idx': 77, 'label': 'Held On', 'oldfieldname': 'held_on', 'oldfieldtype': 'Date', @@ -1049,7 +1026,7 @@ 'doctype': 'DocField', 'fieldname': 'reason_for_resignation', 'fieldtype': 'Select', - 'idx': 79, + 'idx': 78, 'label': 'Reason for Resignation', 'oldfieldname': 'reason_for_resignation', 'oldfieldtype': 'Select', @@ -1062,7 +1039,7 @@ 'doctype': 'DocField', 'fieldname': 'new_workplace', 'fieldtype': 'Data', - 'idx': 80, + 'idx': 79, 'label': 'New Workplace', 'oldfieldname': 'new_workplace', 'oldfieldtype': 'Data', @@ -1074,7 +1051,7 @@ 'doctype': 'DocField', 'fieldname': 'feedback', 'fieldtype': 'Small Text', - 'idx': 81, + 'idx': 80, 'label': 'Feedback', 'oldfieldname': 'feedback', 'oldfieldtype': 'Text', @@ -1087,7 +1064,7 @@ 'fieldname': 'file_list', 'fieldtype': 'Text', 'hidden': 1, - 'idx': 82, + 'idx': 81, 'label': 'File List', 'permlevel': 0, 'print_hide': 1 @@ -1098,7 +1075,7 @@ 'doctype': 'DocField', 'fieldname': 'trash_reason', 'fieldtype': 'Small Text', - 'idx': 83, + 'idx': 82, 'label': 'Trash Reason', 'oldfieldname': 'trash_reason', 'oldfieldtype': 'Small Text', diff --git a/hr/doctype/leave_allocation/leave_allocation.py b/hr/doctype/leave_allocation/leave_allocation.py index e11a3357d61..12fe37a85b1 100755 --- a/hr/doctype/leave_allocation/leave_allocation.py +++ b/hr/doctype/leave_allocation/leave_allocation.py @@ -66,7 +66,7 @@ class DocType: 'carry_forwarded_leaves' : prev_bal, 'total_leaves_allocated' : flt(prev_bal) + flt(self.doc.new_leaves_allocated) } - return str(ret) + return ret # ********************************************** validate ***************************************************** @@ -75,7 +75,7 @@ class DocType: # get total allocated leaves # --------------------------- def get_total_allocated_leaves(self): - leave_det = eval(self.get_carry_forwarded_leaves()) + leave_det = self.get_carry_forwarded_leaves() set(self.doc,'carry_forwarded_leaves',flt(leave_det['carry_forwarded_leaves'])) set(self.doc,'total_leaves_allocated',flt(leave_det['total_leaves_allocated'])) diff --git a/hr/doctype/leave_application/leave_application.js b/hr/doctype/leave_application/leave_application.js index ba00a31a7c8..1eda69fcc6e 100755 --- a/hr/doctype/leave_application/leave_application.js +++ b/hr/doctype/leave_application/leave_application.js @@ -52,12 +52,9 @@ cur_frm.cscript.from_date = function(doc, dt, dn) { // to date // -------- cur_frm.cscript.to_date = function(doc, dt, dn) { - if(cint(doc.half_day) == 1 && doc.from_date && doc.from_date != doc.to_date){ + 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"); - return; - } - if(cint(doc.half_day) == 1){ - set_multiple(dt,dn,{to_date:doc.from_date}); + set_multiple(dt,dn,{to_date:doc.from_date}); } calculate_total_days(doc, dt, dn); } diff --git a/hr/doctype/leave_application/leave_application.py b/hr/doctype/leave_application/leave_application.py index 5f69c63a198..1756f2a7ca8 100755 --- a/hr/doctype/leave_application/leave_application.py +++ b/hr/doctype/leave_application/leave_application.py @@ -33,7 +33,7 @@ class DocType: leave_app = sql("select 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 str(ret) + return ret # ************************************************ utilities ************************************************* @@ -55,7 +55,7 @@ class DocType: tot_days = date_diff(self.doc.to_date, self.doc.from_date) + 1 holidays = self.get_holidays() ret = {'total_leave_days':flt(tot_days)-flt(holidays)} - return str(ret) + return ret # ************************************************ validate ************************************************* @@ -82,7 +82,7 @@ class DocType: if not self.is_lwp(): bal = self.get_leave_balance() tot_leaves = self.get_total_leave_days() - bal, tot_leaves = eval(bal), eval(tot_leaves) + bal, tot_leaves = bal, tot_leaves set(self.doc,'leave_balance',flt(bal['leave_balance'])) set(self.doc,'total_leave_days',flt(tot_leaves['total_leave_days'])) if flt(bal['leave_balance']) < flt(tot_leaves['total_leave_days']): diff --git a/hr/doctype/salary_manager/__init__.py b/hr/doctype/salary_manager/__init__.py new file mode 100644 index 00000000000..cb6c600133b --- /dev/null +++ b/hr/doctype/salary_manager/__init__.py @@ -0,0 +1,4 @@ +from webnotes import ValidationError + +class SalarySlipExistsError(ValidationError): pass + diff --git a/hr/doctype/salary_manager/salary_manager.js b/hr/doctype/salary_manager/salary_manager.js new file mode 100644 index 00000000000..cf470be8c71 --- /dev/null +++ b/hr/doctype/salary_manager/salary_manager.js @@ -0,0 +1,67 @@ +var display_activity_log = function(msg) { + if(!pscript.ss_html) + pscript.ss_html = $a(cur_frm.fields_dict['Activity Log'].wrapper,'div','',{border:'1px solid #CCC', backgroundColor:'#CCC'}); + pscript.ss_html.innerHTML = '
Activity Log:
'; + pscript.ss_html.innerHTML += '
'+ msg + '
'; +} + +//Create salary slip +//----------------------- +cur_frm.cscript['Create Salary Slip'] = function(doc, cdt, cdn) { + var callback = function(r, rt){ + if (r.message) + display_activity_log(r.message); + } + $c('runserverobj', args={'method':'create_sal_slip','docs':compress_doclist(make_doclist (cdt, cdn))},callback); +} + + + +//Submit salary slip +//----------------------- +cur_frm.cscript['Submit Salary Slip'] = function(doc, cdt, cdn) { + var check = confirm("Do you really want to Submit all Salary Slip for month : " + doc.month+" and fiscal year : "+doc.fiscal_year); + if(check){ + var callback = function(r, rt){ + if (r.message) + display_activity_log(r.message); + } + $c('runserverobj', args={'method':'submit_salary_slip','docs':compress_doclist(make_doclist (cdt, cdn))},callback); + } +} + +// Make Bank Voucher +//----------------------- +cur_frm.cscript['Make Bank Voucher'] = function(doc,cdt,cdn){ + if(doc.month && doc.fiscal_year){ + cur_frm.cscript.make_jv(doc, cdt, cdn); + } +} + + +// Make JV +//----------------------- +cur_frm.cscript.make_jv = function(doc, dt, dn) { + var call_back = function(r,rt){ + var jv = LocalDB.create('Journal Voucher'); + jv = locals['Journal Voucher'][jv]; + jv.voucher_type = 'Bank Voucher'; + jv.user_remark = 'Payment of salary for the month: ' + doc.month + 'and fiscal year: ' + doc.fiscal_year; + jv.fiscal_year = doc.fiscal_year; + jv.company = doc.company; + jv.posting_date = dateutil.obj_to_str(new Date()); + + // credit to bank + var d1 = LocalDB.add_child(jv, 'Journal Voucher Detail', 'entries'); + d1.account = r.message['default_bank_account']; + d1.credit = r.message['amount'] + + // debit to salary account + var d2 = LocalDB.add_child(jv, 'Journal Voucher Detail', 'entries'); + d2.account = r.message['default_salary_account']; + d2.debit = r.message['amount'] + + loaddoc('Journal Voucher', jv.name); + } + $c_obj(make_doclist(dt,dn),'get_acc_details','',call_back); +} diff --git a/hr/doctype/salary_manager/salary_manager.py b/hr/doctype/salary_manager/salary_manager.py new file mode 100644 index 00000000000..50710568e81 --- /dev/null +++ b/hr/doctype/salary_manager/salary_manager.py @@ -0,0 +1,172 @@ +# Please edit this list and import only required elements +import webnotes + +from webnotes.utils import add_days, add_months, add_years, cint, cstr, date_diff, default_fields, flt, fmt_money, formatdate, generate_hash, getTraceback, get_defaults, get_first_day, get_last_day, getdate, has_common, month_name, now, nowdate, replace_newlines, sendmail, set_default, str_esc_quote, user_format, validate_email_add +from webnotes.model import db_exists +from webnotes.model.doc import Document, addchild, removechild, getchildren, make_autoname, SuperDocType +from webnotes.model.doclist import getlist, copy_doclist +from webnotes.model.code import get_obj, get_server_obj, run_server_obj, updatedb, check_syntax +from webnotes import session, form, is_testing, msgprint, errprint + +set = webnotes.conn.set +sql = webnotes.conn.sql +get_value = webnotes.conn.get_value +in_transaction = webnotes.conn.in_transaction +convert_to_lists = webnotes.conn.convert_to_lists + +# ----------------------------------------------------------------------------------------- + + +class DocType: + def __init__(self, doc, doclist): + self.doc = doc + self.doclist = doclist + + + def get_emp_list(self): + """ + Returns list of active employees based on selected criteria + and for which salary structure exists + """ + + cond = self.get_filter_condition() + + emp_list = sql(""" + select t1.name + from `tabEmployee` t1, `tabSalary Structure` t2 + where t1.docstatus!=2 and t2.docstatus != 2 + and ifnull(t1.status, 'Left') = 'Active' and ifnull(t2.is_active, 'No') = 'Yes' + and t1.name = t2.employee + %s """% cond) + + return emp_list + + + def get_filter_condition(self): + self.check_mandatory() + + cond = '' + for f in ['company', 'branch', 'department', 'designation', 'grade', 'employment_type']: + if self.doc.fields.get(f): + cond += " and t1." + f + " = '" + self.doc.fields.get(f) + "'" + + return cond + + + def check_mandatory(self): + for f in ['company', 'month', 'fiscal_year']: + if not self.doc.fields[f]: + msgprint("Please select %s to proceed" % f, raise_exception=1) + + + def create_sal_slip(self): + """ + Creates salary slip for selected employees if already not created + + """ + + emp_list = self.get_emp_list() + log = "" + if emp_list: + log = "" + else: + log = "
Following Salary Slip has been created:
SAL SLIP IDEMPLOYEE NAME
" + + for emp in emp_list: + if not sql("""select name from `tabSalary Slip` + where docstatus!= 2 and employee = %s and month = %s and fiscal_year = %s and company = %s + """, (emp[0], self.doc.month, self.doc.fiscal_year, self.doc.company)): + ss = Document('Salary Slip') + ss.fiscal_year = self.doc.fiscal_year + ss.employee = emp[0] + ss.month = self.doc.month + ss.email_check = self.doc.send_email + ss.company = self.doc.company + ss.save(1) + + ss_obj = get_obj('Salary Slip', ss.name, with_children=1) + ss_obj.get_emp_and_leave_details() + ss_obj.calculate_net_pay() + ss_obj.validate() + ss_obj.doc.save() + + for d in getlist(ss_obj.doclist, 'earning_details'): + d.save() + for d in getlist(ss_obj.doclist, 'deduction_details'): + d.save() + + log += '' + log += '
No employee found for the above selected criteria
' + ss.name + '' + ss_obj.doc.employee_name + '
' + return log + + def get_sal_slip_list(self): + """ + Returns list of salary slips based on selected criteria + which are not submitted + """ + cond = self.get_filter_condition() + ss_list = sql(""" + select t1.name from `tabSalary Slip` t1 + where t1.docstatus = 0 and month = '%s' and fiscal_year = '%s' %s + """ % (self.doc.month, self.doc.fiscal_year, cond)) + return ss_list + + + def submit_salary_slip(self): + """ + Submit all salary slips based on selected criteria + """ + ss_list = self.get_sal_slip_list() + log = "" + if ss_list: + log = """ + + + + + + + + """ + else: + log = "
Following Salary Slip has been submitted:
SAL SLIP IDEMPLOYEE NAME
" + + for ss in ss_list: + ss_obj = get_obj("Salary Slip",ss[0],with_children=1) + set(ss_obj.doc, 'docstatus', 1) + ss_obj.on_submit() + + log += '' + log += '
No salary slip found to submit for the above selected criteria
' + ss[0] + '' + ss_obj.doc.employee_name + '
' + return log + + + def get_total_salary(self): + """ + Get total salary amount from submitted salary slip based on selected criteria + """ + cond = self.get_filter_condition() + tot = sql(""" + select sum(rounded_total) from `tabSalary Slip` t1 + where t1.docstatus = 1 and month = '%s' and fiscal_year = '%s' %s + """ % (self.doc.month, self.doc.fiscal_year, cond)) + + return flt(tot[0][0]) + + + def get_acc_details(self): + """ + get default bank account,default salary acount from company + """ + amt = self.get_total_salary() + com = sql("select default_bank_account from `tabCompany` where name = '%s'" % self.doc.company) + + if not com[0][0] or not com[0][1]: + msgprint("You can set Default Bank Account in Company master.") + + ret = { + 'def_bank_acc' : com and com[0][0] or '', + 'def_sal_acc' : com and com[0][1] or '', + 'amount' : amt + } + return ret diff --git a/hr/doctype/salary_slip_control_panel/salary_slip_control_panel.txt b/hr/doctype/salary_manager/salary_manager.txt similarity index 60% rename from hr/doctype/salary_slip_control_panel/salary_slip_control_panel.txt rename to hr/doctype/salary_manager/salary_manager.txt index b83e0c771b5..66a72823803 100644 --- a/hr/doctype/salary_slip_control_panel/salary_slip_control_panel.txt +++ b/hr/doctype/salary_manager/salary_manager.txt @@ -1,42 +1,37 @@ -# DocType, Salary Slip Control Panel +# DocType, Salary Manager [ # These values are common in all dictionaries { - 'creation': '2010-08-08 17:09:20', + 'creation': '2011-08-11 16:40:04', 'docstatus': 0, - 'modified': '2010-12-29 18:02:38', - 'modified_by': 'umair@iwebnotes.com', + 'modified': '2011-08-25 12:02:57', + 'modified_by': 'Administrator', 'owner': 'Administrator' }, # These values are common for all DocType { - '_last_update': '1294312182', + '_last_update': '1314179318', 'allow_copy': 1, 'allow_email': 1, 'allow_print': 1, 'colour': 'White:FFF', 'doctype': 'DocType', - 'hide_heading': 0, - 'hide_toolbar': 0, - 'in_create': 0, + 'document_type': 'Other', 'issingle': 1, 'module': 'HR', 'name': '__common__', - 'read_only': 1, 'section_style': 'Simple', - 'server_code_error': ' ', - 'show_in_menu': 0, - 'use_template': 0, - 'version': 113 + 'show_in_menu': 1, + 'version': 29 }, # These values are common for all DocField { 'doctype': 'DocField', 'name': '__common__', - 'parent': 'Salary Slip Control Panel', + 'parent': 'Salary Manager', 'parentfield': 'fields', 'parenttype': 'DocType', 'permlevel': 0 @@ -47,7 +42,7 @@ 'create': 1, 'doctype': 'DocPerm', 'name': '__common__', - 'parent': 'Salary Slip Control Panel', + 'parent': 'Salary Manager', 'parentfield': 'permissions', 'parenttype': 'DocType', 'permlevel': 0, @@ -55,10 +50,10 @@ 'write': 1 }, - # DocType, Salary Slip Control Panel + # DocType, Salary Manager { 'doctype': 'DocType', - 'name': 'Salary Slip Control Panel' + 'name': 'Salary Manager' }, # DocPerm @@ -84,22 +79,76 @@ # DocField { + 'colour': 'White:FFF', 'doctype': 'DocField', - 'fieldtype': 'Section Break', + 'fieldtype': 'HTML', 'idx': 1, - 'label': 'Salary Slip Control Panel' + 'label': 'Document Description', + 'options': '
You can generate multiple salary slips based on the selected criteria, submit and mail those to the employee directly from here
' }, # DocField { 'doctype': 'DocField', - 'fieldname': 'employee_type', + 'fieldtype': 'Section Break', + 'idx': 2 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldtype': 'Column Break', + 'idx': 3, + 'width': '50%' + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'company', 'fieldtype': 'Select', - 'idx': 2, - 'label': 'Employment Type', - 'oldfieldname': 'employee_type', - 'oldfieldtype': 'Select', - 'options': 'link:Employment Type' + 'idx': 4, + 'label': 'Company', + 'options': 'link:Company', + 'reqd': 1 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'branch', + 'fieldtype': 'Link', + 'idx': 5, + 'label': 'Branch', + 'options': 'Branch' + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'department', + 'fieldtype': 'Link', + 'idx': 6, + 'label': 'Department', + 'options': 'Department' + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'designation', + 'fieldtype': 'Link', + 'idx': 7, + 'label': 'Designation', + 'options': 'Designation' + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldtype': 'Column Break', + 'idx': 8, + 'width': '50%' }, # DocField @@ -107,180 +156,132 @@ 'doctype': 'DocField', 'fieldname': 'grade', 'fieldtype': 'Select', - 'idx': 3, + 'idx': 9, 'label': 'Grade', - 'oldfieldname': 'grade', - 'oldfieldtype': 'Select', 'options': 'link:Grade' }, # DocField { 'doctype': 'DocField', - 'fieldname': 'branch', + 'fieldname': 'employment_type', 'fieldtype': 'Select', - 'idx': 4, - 'label': 'Branch', - 'oldfieldname': 'branch', - 'oldfieldtype': 'Select', - 'options': 'link:Branch' - }, - - # DocField - { - 'doctype': 'DocField', - 'fieldname': 'department', - 'fieldtype': 'Select', - 'idx': 5, - 'label': 'Department', - 'oldfieldname': 'department', - 'oldfieldtype': 'Select', - 'options': 'link:Department' - }, - - # DocField - { - 'doctype': 'DocField', - 'fieldname': 'designation', - 'fieldtype': 'Select', - 'idx': 6, - 'label': 'Designation', - 'oldfieldname': 'designation', - 'oldfieldtype': 'Select', - 'options': 'link:Designation' + 'idx': 10, + 'label': 'Employment Type', + 'options': 'link:Employment Type' }, # DocField { 'colour': 'White:FFF', - 'doctype': 'DocField', - 'fieldtype': 'Column Break', - 'idx': 7, - 'oldfieldtype': 'Column Break' - }, - - # DocField - { 'doctype': 'DocField', 'fieldname': 'fiscal_year', 'fieldtype': 'Select', - 'idx': 8, - 'in_filter': 1, - 'label': 'Fiscal Year', - 'oldfieldname': 'fiscal_year', - 'oldfieldtype': 'Select', - 'options': 'link:Fiscal Year' - }, - - # DocField - { - 'doctype': 'DocField', - 'fieldname': 'month', - 'fieldtype': 'Select', - 'idx': 9, - 'label': 'Month', - 'oldfieldname': 'month', - 'oldfieldtype': 'Select', - 'options': '\n01\n02\n03\n04\n05\n06\n07\n08\n09\n10\n11\n12' - }, - - # DocField - { - 'doctype': 'DocField', - 'fieldname': 'year', - 'fieldtype': 'Select', - 'idx': 10, - 'label': 'Year', - 'oldfieldname': 'year', - 'oldfieldtype': 'Select', - 'options': '\n2009\n2010\n2011\n2012' - }, - - # DocField - { - 'doctype': 'DocField', - 'fieldname': 'week_off', - 'fieldtype': 'Currency', 'idx': 11, - 'label': 'Week Off', - 'oldfieldname': 'week_off', - 'oldfieldtype': 'Currency' - }, - - # DocField - { - 'doctype': 'DocField', - 'fieldname': 'arrear_amount', - 'fieldtype': 'Currency', - 'idx': 12, - 'label': 'Arrear Amount', - 'oldfieldname': 'arrear_amount', - 'oldfieldtype': 'Currency' + 'label': 'Fiscal Year', + 'options': 'link:Fiscal Year', + 'reqd': 1 }, # DocField { 'colour': 'White:FFF', 'doctype': 'DocField', - 'fieldname': 'email_check', + 'fieldname': 'month', + 'fieldtype': 'Select', + 'idx': 12, + 'label': 'Month', + 'options': '\n01\n02\n03\n04\n05\n06\n07\n08\n09\n10\n11\n12', + 'reqd': 1 + }, + + # DocField + { + 'colour': 'White:FFF', + 'description': 'Check if you want to send salary slip in mail to each employee while submitting salary slip', + 'doctype': 'DocField', + 'fieldname': 'send_email', 'fieldtype': 'Check', 'idx': 13, - 'label': 'Email', - 'oldfieldname': 'email_check', - 'oldfieldtype': 'Check' + 'label': 'Send Email' }, # DocField { 'doctype': 'DocField', 'fieldtype': 'Section Break', - 'idx': 14, - 'oldfieldtype': 'Section Break' - }, - - # DocField - { - 'colour': 'White:FFF', - 'doctype': 'DocField', - 'fieldtype': 'Button', - 'idx': 15, - 'label': 'Process Payroll', - 'oldfieldtype': 'Button', - 'trigger': 'Client' - }, - - # DocField - { - 'doctype': 'DocField', - 'fieldtype': 'HTML', - 'idx': 16, - 'label': 'Salary Slip HTML' + 'idx': 14 }, # DocField { 'doctype': 'DocField', 'fieldtype': 'Column Break', - 'idx': 17 + 'idx': 15, + 'width': '50%' }, # DocField { 'colour': 'White:FFF', + 'description': 'Creates salary slip for above mentioned criteria.', 'doctype': 'DocField', 'fieldtype': 'Button', - 'idx': 18, - 'label': 'Submit Salary Slip', - 'oldfieldtype': 'Button', + 'idx': 16, + 'label': 'Create Salary Slip', 'trigger': 'Client' }, # DocField { + 'doctype': 'DocField', + 'fieldtype': 'Column Break', + 'idx': 17, + 'width': '25%' + }, + + # DocField + { + 'colour': 'White:FFF', + 'description': 'Submit all salary slips for the above selected criteria', 'doctype': 'DocField', 'fieldtype': 'Button', + 'idx': 18, + 'label': 'Submit Salary Slip', + 'trigger': 'Client' + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldtype': 'Column Break', 'idx': 19, + 'width': '25%' + }, + + # DocField + { + 'colour': 'White:FFF', + 'description': 'Create Bank Voucher for the total salary paid for the above selected criteria', + 'doctype': 'DocField', + 'fieldtype': 'Button', + 'idx': 20, 'label': 'Make Bank Voucher', 'trigger': 'Client' + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldtype': 'Section Break', + 'idx': 21 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldtype': 'HTML', + 'idx': 22, + 'label': 'Activity Log' } ] \ No newline at end of file diff --git a/hr/doctype/salary_manager/test_salary_manager.py b/hr/doctype/salary_manager/test_salary_manager.py new file mode 100644 index 00000000000..e3df804b0d2 --- /dev/null +++ b/hr/doctype/salary_manager/test_salary_manager.py @@ -0,0 +1,199 @@ +import unittest +import webnotes + +from webnotes.model.doc import Document +from webnotes.model.code import get_obj +sql = webnotes.conn.sql + +class TestSalarySlip(unittest.TestCase): + def setUp(self): + webnotes.conn.begin() + for rec in [des1, dep1, branch1, grade1, comp1, emp1, emp2]: + rec.save(1) + + ss1[0].employee = emp1.name + for s in ss1: s.save(1) + for s in ss1[1:]: + sql("update `tabEarning Detail` set parent = '%s' where name = '%s'" % (ss1[0].name, s.name)) + sql("update `tabDeduction Detail` set parent = '%s' where name = '%s'" % (ss1[0].name, s.name)) + + + ss2[0].employee = emp2.name + for s in ss2: s.save(1) + for s in ss2[1:]: + sql("update `tabEarning Detail` set parent = '%s' where name = '%s'" % (ss2[0].name, s.name)) + sql("update `tabDeduction Detail` set parent = '%s' where name = '%s'" % (ss2[0].name, s.name)) + + sman.save() + self.sm = get_obj('Salary Manager') + leave.save(1) + self.sm.create_sal_slip() + + def test_creation(self): + ssid = sql(""" + select name, department + from `tabSalary Slip` + where month = '08' and fiscal_year='2011-2012'""") + + self.assertTrue(len(ssid)==1) + self.assertTrue(ssid[0][1] == 'dep1') + + + def test_lwp_calc(self): + ss = sql(""" + select payment_days + from `tabSalary Slip` + where month = '08' and fiscal_year='2011-2012' and employee = '%s' + """ % emp1.name) + + self.assertTrue(ss[0][0]==27) + + def test_net_pay(self): + ss = webnotes.conn.sql(""" + select rounded_total + from `tabSalary Slip` + where month = '08' + and fiscal_year='2011-2012' and employee = '%s'""" % emp1.name) + self.assertTrue(ss[0][0]==67) + + def test_submit(self): + self.sm.submit_salary_slip() + ss = webnotes.conn.sql(""" + select docstatus + from `tabSalary Slip` + where month = '08' + and fiscal_year='2011-2012' and employee = '%s'""" % emp1.name) + self.assertTrue(ss[0][0]==1) + + def tearDown(self): + webnotes.conn.rollback() + +#-------------------------------------------- +# test data +#-------------------------------------------- +des1 = Document(fielddata={ + 'name':'des1', + 'doctype':'Designation', + 'designation_name':'des1' +}) + +dep1 = Document(fielddata={ + 'name':'dep1', + 'doctype':'Department', + 'department_name' : 'dep1' +}) + +branch1 = Document(fielddata={ + 'name':'branch1', + 'doctype':'Branch', + 'branch' : 'branch1' +}) + +comp1 = Document(fielddata={ + 'name':'comp1', + 'doctype':'Company', + 'abbr':'c1', + 'company_name' : 'comp1' +}) + +grade1 = Document(fielddata={ + 'name':'grade1', + 'doctype':'Grade', + 'grade_name' : 'grade1' +}) + +emp1 = Document(fielddata={ + 'doctype':'Employee', + 'employee_number':'emp1', + 'department':'dep1', + 'designation':'des1', + 'branch' : 'branch1', + 'company':'comp1', + 'grade':'grade1', + 'naming_series':'EMP/', + 'status':'Active', + 'docstatus':0, + 'employee_name':'emp1' +}) + +emp2 = Document(fielddata={ + 'doctype':'Employee', + 'employee_number':'emp2', + 'department':'dep1', + 'designation':'des2', + 'branch' : 'branch1', + 'company':'comp1', + 'naming_series':'EMP/', + 'grade':'grade1', + 'status':'Active', + +}) + +ss1 = [ + Document(fielddata={ + 'doctype':'Salary Structure', + 'docstatus':0, + 'employee':'emp1', + 'is_active':'Yes', + 'department': 'dep1', + 'designation' : 'des1', + 'employee_name': 'emp1' + }), + Document(fielddata={ + 'parenttype':'Salary Structure', + 'parentfield':'earning_details', + 'doctype':'Earning Detail', + 'e_type' : 'Basic', + 'depend_on_lwp':1, + 'modified_value':100 + }), + Document(fielddata={ + 'parenttype':'Salary Structure', + 'parentfield':'earning_details', + 'doctype':'Deduction Detail', + 'd_type':'TDS', + 'd_modified_amt':20 + }) +] + +ss2 = [ + Document(fielddata={ + 'doctype':'Salary Structure', + 'is_active':'Yes', + 'docstatus':0, + }), + Document(fielddata={ + 'parenttype':'Salary Structure', + 'parentfield':'deduction_details', + 'doctype':'Earning Detail', + 'e_type' : 'Basic', + 'modified_value':100 + }), + Document(fielddata={ + 'parenttype':'Salary Structure', + 'parentfield':'deduction_details', + 'doctype':'Deduction Detail', + 'd_type':'TDS', + 'd_modified_amt':20 + }) +] + +sman = Document(fielddata={ + 'name':'Salary Manager', + 'doctype':'Salary Manager', + 'company': 'comp1', + 'department':'dep1', + 'designation':'des1', + 'month': '08', + 'fiscal_year':'2011-2012' + }) + +leave = Document(fielddata = { + 'doctype':'Leave Application', + 'employee':'emp1', + 'from_date':'2011-08-12', + 'to_date':'2011-08-15', + 'total_leave_days':'4', + 'leave_type':'Leave Without Pay', + 'docstatus':1 + }) diff --git a/hr/doctype/salary_slip/salary_slip.js b/hr/doctype/salary_slip/salary_slip.js index 8c76b1e7c9b..c6ae27bfd65 100644 --- a/hr/doctype/salary_slip/salary_slip.js +++ b/hr/doctype/salary_slip/salary_slip.js @@ -3,25 +3,25 @@ cur_frm.add_fetch('employee', 'company', 'company'); // On load // ------------------------------------------------------------------- cur_frm.cscript.onload = function(doc,dt,dn){ - if((cint(doc.__islocal) == 1) && !doc.amended_from){ - var today=new Date(); - month = (today.getMonth()+01).toString(); - if(month.length>1) doc.month = month; - else doc.month = '0'+month; + if((cint(doc.__islocal) == 1) && !doc.amended_from){ + var today=new Date(); + month = (today.getMonth()+01).toString(); + if(month.length>1) doc.month = month; + else doc.month = '0'+month; doc.fiscal_year = sys_defaults['fiscal_year']; - refresh_many(['month', 'fiscal_year']); - cur_frm.cscript.fiscal_year(doc, dt, dn); - } + refresh_many(['month', 'fiscal_year']); + cur_frm.cscript.fiscal_year(doc, dt, dn); + } } // Get leave details //--------------------------------------------------------------------- cur_frm.cscript.fiscal_year = function(doc,dt,dn){ - $c_obj(make_doclist(doc.doctype,doc.name), 'get_emp_and_leave_details','',function(r, rt) { - var doc = locals[dt][dn]; - cur_frm.refresh(); - calculate_all(doc, dt, dn); - }); + $c_obj(make_doclist(doc.doctype,doc.name), 'get_emp_and_leave_details','',function(r, rt) { + var doc = locals[dt][dn]; + cur_frm.refresh(); + calculate_all(doc, dt, dn); + }); } cur_frm.cscript.month = cur_frm.cscript.employee = cur_frm.cscript.fiscal_year; @@ -29,24 +29,24 @@ cur_frm.cscript.month = cur_frm.cscript.employee = cur_frm.cscript.fiscal_year; // Calculate total if lwp exists // ------------------------------------------------------------------------ cur_frm.cscript.leave_without_pay = function(doc,dt,dn){ - doc.payment_days = cint(doc.total_days_in_month) - cint(doc.leave_without_pay); - refresh_field('payment_days'); - calculate_all(doc, dt, dn); + doc.payment_days = flt(doc.total_days_in_month) - flt(doc.leave_without_pay); + refresh_field('payment_days'); + calculate_all(doc, dt, dn); } // Calculate all // ------------------------------------------------------------------------ var calculate_all = function(doc, dt, dn) { - calculate_earning_total(doc, dt, dn); - calculate_ded_total(doc, dt, dn); - calculate_net_pay(doc, dt, dn); + calculate_earning_total(doc, dt, dn); + calculate_ded_total(doc, dt, dn); + calculate_net_pay(doc, dt, dn); } // Trigger on earning modified amount and depends on lwp // ------------------------------------------------------------------------ cur_frm.cscript.e_modified_amount = function(doc,dt,dn){ - calculate_earning_total(doc, dt, dn); - calculate_net_pay(doc, dt, dn); + calculate_earning_total(doc, dt, dn); + calculate_net_pay(doc, dt, dn); } cur_frm.cscript.e_depends_on_lwp = cur_frm.cscript.e_modified_amount; @@ -54,8 +54,8 @@ cur_frm.cscript.e_depends_on_lwp = cur_frm.cscript.e_modified_amount; // Trigger on earning modified amount and depends on lwp // ------------------------------------------------------------------------ cur_frm.cscript.d_modified_amount = function(doc,dt,dn){ - calculate_ded_total(doc, dt, dn); - calculate_net_pay(doc, dt, dn); + calculate_ded_total(doc, dt, dn); + calculate_net_pay(doc, dt, dn); } cur_frm.cscript.d_depends_on_lwp = cur_frm.cscript.d_modified_amount; @@ -63,50 +63,50 @@ cur_frm.cscript.d_depends_on_lwp = cur_frm.cscript.d_modified_amount; // Calculate earning total // ------------------------------------------------------------------------ var calculate_earning_total = function(doc, dt, dn) { - var tbl = getchildren('SS Earning Detail', doc.name, 'earning_details', doc.doctype); + var tbl = getchildren('SS Earning Detail', doc.name, 'earning_details', doc.doctype); - var total_earn = 0; - for(var i = 0; i < tbl.length; i++){ - if(cint(tbl[i].e_depends_on_lwp) == 1) { - tbl[i].e_modified_amount = flt(tbl[i].e_amount)*(flt(doc.payment_days)/cint(doc.total_days_in_month)); - refresh_field('e_modified_amount', tbl[i].name, 'earning_details'); - } - total_earn += flt(tbl[i].e_modified_amount); - } - doc.gross_pay = total_earn + flt(doc.arrear_amount) + flt(doc.leave_encashment_amount); - refresh_many(['e_modified_amount', 'gross_pay']); + var total_earn = 0; + for(var i = 0; i < tbl.length; i++){ + if(cint(tbl[i].e_depends_on_lwp) == 1) { + tbl[i].e_modified_amount = Math.round(tbl[i].e_amount)*(flt(doc.payment_days)/cint(doc.total_days_in_month)*100)/100; + refresh_field('e_modified_amount', tbl[i].name, 'earning_details'); + } + total_earn += flt(tbl[i].e_modified_amount); + } + doc.gross_pay = total_earn + flt(doc.arrear_amount) + flt(doc.leave_encashment_amount); + refresh_many(['e_modified_amount', 'gross_pay']); } // Calculate deduction total // ------------------------------------------------------------------------ var calculate_ded_total = function(doc, dt, dn) { - var tbl = getchildren('SS Deduction Detail', doc.name, 'deduction_details', doc.doctype); + var tbl = getchildren('SS Deduction Detail', doc.name, 'deduction_details', doc.doctype); - var total_ded = 0; - for(var i = 0; i < tbl.length; i++){ - if(cint(tbl[i].d_depends_on_lwp) == 1) { - tbl[i].d_modified_amount = flt(tbl[i].d_amount)*(flt(doc.payment_days)/cint(doc.total_days_in_month)); + var total_ded = 0; + for(var i = 0; i < tbl.length; i++){ + if(cint(tbl[i].d_depends_on_lwp) == 1) { + tbl[i].d_modified_amount = Math.round(tbl[i].d_amount)*(flt(doc.payment_days)/cint(doc.total_days_in_month)*100)/100; refresh_field('d_modified_amount', tbl[i].name, 'deduction_details'); - } - total_ded += flt(tbl[i].d_modified_amount); - } - doc.total_deduction = total_ded; - refresh_field('total_deduction'); + } + total_ded += flt(tbl[i].d_modified_amount); + } + doc.total_deduction = total_ded; + refresh_field('total_deduction'); } // Calculate net payable amount // ------------------------------------------------------------------------ var calculate_net_pay = function(doc, dt, dn) { - doc.net_pay = flt(doc.gross_pay) - flt(doc.total_deduction); + doc.net_pay = flt(doc.gross_pay) - flt(doc.total_deduction); doc.rounded_total = Math.round(doc.net_pay); - refresh_many(['net_pay', 'rounded_total']); + refresh_many(['net_pay', 'rounded_total']); } // trigger on arrear // ------------------------------------------------------------------------ cur_frm.cscript.arrear_amount = function(doc,dt,dn){ - calculate_earning_total(doc, dt, dn); - calculate_net_pay(doc, dt, dn); + calculate_earning_total(doc, dt, dn); + calculate_net_pay(doc, dt, dn); } // trigger on encashed amount @@ -116,5 +116,5 @@ cur_frm.cscript.leave_encashment_amount = cur_frm.cscript.arrear_amount; // validate // ------------------------------------------------------------------------ cur_frm.cscript.validate = function(doc, dt, dn) { - calculate_all(doc, dt, dn); + calculate_all(doc, dt, dn); } diff --git a/hr/doctype/salary_slip/salary_slip.py b/hr/doctype/salary_slip/salary_slip.py index 9c948859638..6a1705054ea 100644 --- a/hr/doctype/salary_slip/salary_slip.py +++ b/hr/doctype/salary_slip/salary_slip.py @@ -18,210 +18,249 @@ convert_to_lists = webnotes.conn.convert_to_lists from utilities.transaction_base import TransactionBase class DocType(TransactionBase): - def __init__(self,doc,doclist=[]): - self.doc = doc - self.doclist = doclist - - - # autoname - #======================================================= - def autoname(self): - self.doc.name = make_autoname('Sal Slip/' +self.doc.employee + '/.#####') + def __init__(self,doc,doclist=[]): + self.doc = doc + self.doclist = doclist + + + # autoname + #======================================================= + def autoname(self): + self.doc.name = make_autoname('Sal Slip/' +self.doc.employee + '/.#####') - # Get employee details - #======================================================= - def get_emp_and_leave_details(self): - # Get payment days - if self.doc.fiscal_year and self.doc.month: - self.get_leave_details() + # Get employee details + #======================================================= + def get_emp_and_leave_details(self): + # Get payment days + if self.doc.fiscal_year and self.doc.month: + self.get_leave_details() - # check sal structure - if self.doc.employee: - struct = self.check_sal_struct() - if struct: - self.pull_sal_struct(struct) + # check sal structure + if self.doc.employee: + struct = self.check_sal_struct() + if struct: + self.pull_sal_struct(struct) - # Check sal structure - #======================================================= - def check_sal_struct(self): - struct = sql("select name from `tabSalary Structure` where employee ='%s' and is_active = 'Yes' "%self.doc.employee) - if not struct: - msgprint("Please create Salary Structure for employee '%s'"%self.doc.employee) - self.doc.employee = '' - return struct and struct[0][0] or '' + # Check sal structure + #======================================================= + def check_sal_struct(self): + struct = sql("select name from `tabSalary Structure` where employee ='%s' and is_active = 'Yes' "%self.doc.employee) + if not struct: + msgprint("Please create Salary Structure for employee '%s'"%self.doc.employee) + self.doc.employee = '' + return struct and struct[0][0] or '' - # Pull struct details - #======================================================= - def pull_sal_struct(self, struct): - self.doc.clear_table(self.doclist, 'earning_details') - self.doc.clear_table(self.doclist, 'deduction_details') + # Pull struct details + #======================================================= + def pull_sal_struct(self, struct): + self.doc.clear_table(self.doclist, 'earning_details') + self.doc.clear_table(self.doclist, 'deduction_details') - get_obj('DocType Mapper', 'Salary Structure-Salary Slip').dt_map('Salary Structure', 'Salary Slip', struct, self.doc, self.doclist, "[['Salary Structure', 'Salary Slip'],['Earning Detail', 'SS Earning Detail'],['Deduction Detail','SS Deduction Detail']]") + get_obj('DocType Mapper', 'Salary Structure-Salary Slip').dt_map('Salary Structure', 'Salary Slip', struct, self.doc, self.doclist, "[['Salary Structure', 'Salary Slip'],['Earning Detail', 'SS Earning Detail'],['Deduction Detail','SS Deduction Detail']]") - basic_info = sql("select bank_name, bank_ac_no, esic_card_no, pf_number from `tabEmployee` where name ='%s'" % self.doc.employee) - self.doc.bank_name = basic_info[0][0] - self.doc.bank_account_no = basic_info[0][1] - self.doc.esic_no = basic_info[0][2] - self.doc.pf_no = basic_info[0][3] + basic_info = sql("select bank_name, bank_ac_no, esic_card_no, pf_number from `tabEmployee` where name ='%s'" % self.doc.employee) + self.doc.bank_name = basic_info[0][0] + self.doc.bank_account_no = basic_info[0][1] + self.doc.esic_no = basic_info[0][2] + self.doc.pf_no = basic_info[0][3] - # Get leave details - #======================================================= - def get_leave_details(self): - m = self.get_month_details() - lwp = self.calculate_lwp(m) - self.doc.total_days_in_month = m[3] - self.doc.leave_without_pay = lwp - self.doc.payment_days = flt(m[3]) - flt(lwp) + # Get leave details + #======================================================= + def get_leave_details(self): + m = self.get_month_details() + lwp = self.calculate_lwp(m) + self.doc.total_days_in_month = m[3] + self.doc.leave_without_pay = lwp + self.doc.payment_days = flt(m[3]) - flt(lwp) - # Get month details - #======================================================= - def get_month_details(self): - ysd = sql("select year_start_date from `tabFiscal Year` where name ='%s'"%self.doc.fiscal_year)[0][0] - if ysd: - from dateutil.relativedelta import relativedelta - import calendar, datetime - mnt = int(self.doc.month) - diff_mnt = int(mnt)-int(ysd.month) - if diff_mnt<0: - diff_mnt = 12-int(ysd.month)+int(mnt) - msd = ysd + relativedelta(months=diff_mnt) # month start date - month_days = cint(calendar.monthrange(cint(msd.year) ,cint(self.doc.month))[1]) # days in month - med = datetime.date(msd.year, cint(self.doc.month), month_days) # month end date - return msd.year, msd, med, month_days + # Get month details + #======================================================= + def get_month_details(self): + ysd = sql("select year_start_date from `tabFiscal Year` where name ='%s'"%self.doc.fiscal_year)[0][0] + if ysd: + from dateutil.relativedelta import relativedelta + import calendar, datetime + mnt = int(self.doc.month) + diff_mnt = int(mnt)-int(ysd.month) + if diff_mnt<0: + diff_mnt = 12-int(ysd.month)+int(mnt) + msd = ysd + relativedelta(months=diff_mnt) # month start date + month_days = cint(calendar.monthrange(cint(msd.year) ,cint(self.doc.month))[1]) # days in month + med = datetime.date(msd.year, cint(self.doc.month), month_days) # month end date + return msd.year, msd, med, month_days - # Calculate LWP - #======================================================= - def calculate_lwp(self, m): - holidays = sql("select t1.holiday_date from `tabHoliday List Detail` t1, tabEmployee t2 where t1.parent = t2.holiday_list and t2.name = '%s' and t1.holiday_date between '%s' and '%s'" % (self.doc.employee, m[1], m[2])) - if not holidays: - holidays = sql("select t1.holiday_date from `tabHoliday List Detail` t1, `tabHoliday List` t2 where t1.parent = t2.name and ifnull(t2.is_default, 0) = 1 and t2.fiscal_year = '%s'" % self.doc.fiscal_year) - holidays = [cstr(i[0]) for i in holidays] - lwp = 0 - for d in range(m[3]): - dt = add_days(cstr(m[1]), d) - if dt not in holidays: - if sql("select t1.name from `tabLeave Application` t1, `tabLeave Type` t2 where t2.name = t1.leave_type and ifnull(t2.is_lwp, 0) = 1 and t1.docstatus = 1 and t1.employee = '%s' and '%s' between from_date and to_date"%(self.doc.employee, dt)): - lwp += 1 - return lwp - - # Check existing - #======================================================= - def check_existing(self): - ret_exist = sql("select name from `tabSalary Slip` where month = '%s' and fiscal_year = '%s' and docstatus != 2 and employee = '%s' and name !='%s'" % (self.doc.month,self.doc.fiscal_year,self.doc.employee,self.doc.name)) - if ret_exist: - msgprint("Salary Slip of employee '%s' already created for this month" % self.doc.employee) - self.doc.employee = '' - raise Exception + # Calculate LWP + #======================================================= + def calculate_lwp(self, m): + holidays = sql("select t1.holiday_date from `tabHoliday List Detail` t1, tabEmployee t2 where t1.parent = t2.holiday_list and t2.name = '%s' and t1.holiday_date between '%s' and '%s'" % (self.doc.employee, m[1], m[2])) + if not holidays: + holidays = sql("select t1.holiday_date from `tabHoliday List Detail` t1, `tabHoliday List` t2 where t1.parent = t2.name and ifnull(t2.is_default, 0) = 1 and t2.fiscal_year = '%s'" % self.doc.fiscal_year) + holidays = [cstr(i[0]) for i in holidays] + lwp = 0 + for d in range(m[3]): + dt = add_days(cstr(m[1]), d) + if dt not in holidays: + leave = sql(""" + select t1.name, t1.half_day + from `tabLeave Application` t1, `tabLeave Type` t2 + where t2.name = t1.leave_type + and ifnull(t2.is_lwp, 0) = 1 + and t1.docstatus = 1 + and t1.employee = '%s' + and '%s' between from_date and to_date + """%(self.doc.employee, dt)) + if leave: + lwp = cint(leave[0][1]) and lwp + 0.5 or lwp + 1 + return lwp + + # Check existing + #======================================================= + def check_existing(self): + ret_exist = sql("select name from `tabSalary Slip` where month = '%s' and fiscal_year = '%s' and docstatus != 2 and employee = '%s' and name !='%s'" % (self.doc.month,self.doc.fiscal_year,self.doc.employee,self.doc.name)) + if ret_exist: + msgprint("Salary Slip of employee '%s' already created for this month" % self.doc.employee) + self.doc.employee = '' + raise Exception - # Validate - #======================================================= - def validate(self): - self.check_existing() - dcc = TransactionBase().get_company_currency(self.doc.company) - self.doc.total_in_words = get_obj('Sales Common').get_total_in_words(dcc, self.doc.rounded_total) - - # ON SUBMIT - #======================================================= - def on_submit(self): - if(self.doc.email_check == 1): - self.send_mail_funct() + # Validate + #======================================================= + def validate(self): + self.check_existing() + dcc = TransactionBase().get_company_currency(self.doc.company) + self.doc.total_in_words = get_obj('Sales Common').get_total_in_words(dcc, self.doc.rounded_total) - # Send mail - #======================================================= - def send_mail_funct(self): - emailid_ret=sql("select company_email from `tabEmployee` where name = '%s'"%self.doc.employee) - if emailid_ret: - receiver = cstr(emailid_ret[0][0]) - subj = 'Salary Slip ' + cstr(self.doc.month) +' '+cstr(self.doc.year) - earn_ret=sql("select e_type,e_amount from `tabSS Earning Detail` where parent = '%s'"%self.doc.name) - ded_ret=sql("select d_type,d_amount from `tabSS Deduction Detail` where parent = '%s'"%self.doc.name) - - earn_table = '' - ded_table = '' - if earn_ret: - - earn_table += "" - - for e in earn_ret: - if not e[1]: - earn_table +=''%(cstr(e[0])) - else: - earn_table +=''%(cstr(e[0]),cstr(e[1])) - earn_table += '
%s0.00
%s%s
' - - if ded_ret: - - ded_table += "" - - for d in ded_ret: - if not d[1]: - ded_table +=''%(cstr(d[0])) - else: - ded_table +=''%(cstr(d[0]),cstr(d[1])) - ded_table += '
%s0.00
%s%s
' - - letter_head = sql("select value from `tabSingles` where field = 'letter_head' and doctype = 'Control Panel'") - - if not letter_head: - letter_head = '' - - msg = ''' %s
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

- - - - - - - - -
- - - - - - - - -

Salary Slip

Employee Code : %sEmployee Name : %s
Month : %sYear : %sFiscal Year : %s
Department : %sBranch : %sDesignation : %s
Grade : %sBank Account No. : %sBank Name : %s
PF No. : %sESIC No. : %sArrear Amount : %s
Total days in month : %sLeave Without Pay : %sPayment days : %s
EarningDeduction
%s%s
Gross Pay : %sTotal Deduction : %s
Net Pay : %sNet Pay (in words) : %s
'''%(cstr(letter_head[0][0]),cstr(self.doc.employee),self.doc.employee_name,cstr(self.doc.month),cstr(self.doc.year),cstr(self.doc.fiscal_year),self.doc.department,self.doc.branch,self.doc.designation,self.doc.grade,cstr(self.doc.bank_account_no),self.doc.bank_name,cstr(self.doc.pf_no),cstr(self.doc.esic_no),cstr(self.doc.arrear_amount),cstr(self.doc.total_days_in_month),cstr(self.doc.leave_without_pay),cstr(self.doc.payment_days),earn_table,ded_table,cstr(self.doc.gross_pay),cstr(self.doc.total_deduction),cstr(self.doc.net_pay),cstr(self.doc.net_pay_in_words)) - sendmail([receiver], sender='automail@webnotestech.com', subject=subj, parts=[['text/plain', msg]]) - else: - msgprint("Company Email ID not found.") + + def calculate_earning_total(self): + """ + Calculates total earnings considering lwp + """ + self.doc.gross_pay = flt(self.doc.arrear_amount) + flt(self.doc.leave_encashment_amount) + for d in getlist(self.doclist, 'earning_details'): + if cint(d.e_depends_on_lwp) == 1: + d.e_modified_amount = round(flt(d.e_amount)*flt(self.doc.payment_days)/cint(self.doc.total_days_in_month), 2) + self.doc.gross_pay += d.e_modified_amount + + def calculate_ded_total(self): + """ + Calculates total deduction considering lwp + """ + self.doc.total_deduction = 0 + for d in getlist(self.doclist, 'deduction_details'): + if cint(d.d_depends_on_lwp) == 1: + d.d_modified_amount = round(flt(d.d_amount)*flt(self.doc.payment_days)/cint(self.doc.total_days_in_month), 2) + self.doc.total_deduction += d.d_modified_amount + + def calculate_net_pay(self): + """ + Calculate net payment + """ + self.calculate_earning_total() + self.calculate_ded_total() + self.doc.net_pay = flt(self.doc.gross_pay) - flt(self.doc.total_deduction) + self.doc.rounded_total = round(self.doc.net_pay) + + # ON SUBMIT + #======================================================= + def on_submit(self): + if(self.doc.email_check == 1): + self.send_mail_funct() + + + + + # Send mail + #======================================================= + def send_mail_funct(self): + emailid_ret=sql("select company_email from `tabEmployee` where name = '%s'"%self.doc.employee) + if emailid_ret: + receiver = cstr(emailid_ret[0][0]) + subj = 'Salary Slip - ' + cstr(self.doc.month) +'/'+cstr(self.doc.fiscal_year) + earn_ret=sql("select e_type,e_modified_amount from `tabSS Earning Detail` where parent = '%s'"%self.doc.name) + ded_ret=sql("select d_type,d_modified_amount from `tabSS Deduction Detail` where parent = '%s'"%self.doc.name) + + earn_table = '' + ded_table = '' + if earn_ret: + earn_table += "" + + for e in earn_ret: + if not e[1]: + earn_table +=''%(cstr(e[0])) + else: + earn_table +=''%(cstr(e[0]),cstr(e[1])) + earn_table += '
%s0.00
%s%s
' + + if ded_ret: + + ded_table += "" + + for d in ded_ret: + if not d[1]: + ded_table +=''%(cstr(d[0])) + else: + ded_table +=''%(cstr(d[0]),cstr(d[1])) + ded_table += '
%s0.00
%s%s
' + + letter_head = sql("select value from `tabSingles` where field = 'letter_head' and doctype = 'Control Panel'") + + if not letter_head: + letter_head = '' + + msg = '''
%s
+ + + + + + + + + + + + +

Salary Slip

Employee Code : %sEmployee Name : %s
Month : %sFiscal Year : %s
+ + + + + + + + + + + + + + + + + +
Department : %sBranch : %sDesignation : %s
Grade : %sBank Account No. : %sBank Name : %s
Arrear Amount : %sPayment days : %s
+ + + + + + + + + +
EarningDeduction
%s%s
+ + + + + + + + + + + +
Gross Pay : %sTotal Deduction : %s
Net Pay : %s
Net Pay(in words) : %s
'''%(cstr(letter_head[0][0]),cstr(self.doc.employee), cstr(self.doc.employee_name), cstr(self.doc.month), cstr(self.doc.fiscal_year), cstr(self.doc.department), cstr(self.doc.branch), cstr(self.doc.designation), cstr(self.doc.grade), cstr(self.doc.bank_account_no), cstr(self.doc.bank_name), cstr(self.doc.arrear_amount), cstr(self.doc.payment_days), earn_table, ded_table, cstr(self.doc.gross_pay), cstr(self.doc.total_deduction), cstr(self.doc.net_pay), cstr(self.doc.total_in_words)) + sendmail([receiver], sender='automail@erpnext.com', subject=subj, parts=[['text/plain', msg]]) + else: + msgprint("Company Email ID not found.") diff --git a/hr/doctype/salary_slip_control_panel/salary_slip_control_panel.js b/hr/doctype/salary_slip_control_panel/salary_slip_control_panel.js deleted file mode 100644 index 5fd80cbd953..00000000000 --- a/hr/doctype/salary_slip_control_panel/salary_slip_control_panel.js +++ /dev/null @@ -1,71 +0,0 @@ -cur_frm.cscript.onload = function(doc, cdt, cdn) { - alert("Salary Slip Control Panel is currently under re-development. It will take around a week time."); - hide_field(['Process Payroll', 'Submit Salary Slip', 'Make Bank Voucher']); -} - -cur_frm.cscript['Process Payroll'] = function(doc,cdt,cdn){ - $c('runserverobj', args={'method':'process_payroll','docs':compress_doclist (make_doclist (doc.doctype,doc.name))},function(r,rt){ - - if(!pscript.ss_html) - pscript.ss_html = $a(cur_frm.fields_dict['Salary Slip HTML'].wrapper,'span','',{border:'1px solid #CCC', backgroundColor:'#DDD'}); - pscript.ss_html.innerHTML = ''; - pscript.ss_html.innerHTML = r.message; - - - }); - -} - -cur_frm.cscript['Submit Salary Slip'] = function(doc,cdt,cdn){ - if(doc.month && doc.fiscal_year && doc.year){ - var check = confirm("DO you really want to Submit all Salary Slip for month : " + doc.month+" and year : "+doc.year); - if(check){ - $c('runserverobj', args={'method':'submit_sal_slip','docs':compress_doclist (make_doclist (doc.doctype,doc.name))},function(r,rt){ - - if(!pscript.ss_html) - pscript.ss_html = $a(cur_frm.fields_dict['Salary Slip HTML'].wrapper,'span','',{border:'1px solid #CCC', backgroundColor:'#DDD'}); - pscript.ss_html.innerHTML = ''; - pscript.ss_html.innerHTML = r.message; - - - }); - } - } - else - alert("Please select month, fiscal year and year"); -} - -// Make JV -// -------- -cur_frm.cscript.make_jv = function(doc, dt, dn) { - var call_back = function(r,rt){ - var jv = LocalDB.create('Journal Voucher'); - jv = locals['Journal Voucher'][jv]; - jv.voucher_type = 'Bank Voucher'; - jv.remark = 'Salary - Bank Voucher'; - jv.fiscal_year = doc.fiscal_year; - jv.company = doc.company; - - // credit to bank - var d1 = LocalDB.add_child(jv, 'Journal Voucher Detail', 'entries'); - d1.account = r.message['default_bank_account']; - - // debit to salary account - var d1 = LocalDB.add_child(jv, 'Journal Voucher Detail', 'entries'); - d1.account = r.message['default_salary_account']; - if(!r.message['default_salary_account'] && !r.message['default_bank_account']) alert("To debit salary amount in salary head and credit amount from bank, you need to specify default salary account and default bank account in Global Defaults.\nGo to Setup, click on Company. Select a company.\nSelect Default Salary Account, Default Bank Account from Accounting tab."); - else if(!r.message['default_salary_account']) alert("To debit salary amount you need to specify default salary account in Global Defaults.\nGo to Setup, click on Company. Select a company.\nSelect Default Salary Account from Accounting tab."); - else if(!r.message['default_bank_account']) alert("To credit salary amount you need to specify default bank account in Global Defaults.\nGo to Setup, click on Company. Select a company.\nSelect Default Bank Account from Accounting tab."); - loaddoc('Journal Voucher', jv.name); - } - $c_obj(make_doclist(dt,dn),'get_acct_dtl','',call_back); - -} - - - -// Make Journal Voucher -// -------------------- -cur_frm.cscript['Make Bank Voucher'] = function(doc, dt, dn) { - cur_frm.cscript.make_jv(doc,dt,dn); -} diff --git a/hr/doctype/salary_slip_control_panel/salary_slip_control_panel.py b/hr/doctype/salary_slip_control_panel/salary_slip_control_panel.py deleted file mode 100644 index 3a4fadf4cf7..00000000000 --- a/hr/doctype/salary_slip_control_panel/salary_slip_control_panel.py +++ /dev/null @@ -1,137 +0,0 @@ -# Please edit this list and import only required elements -import webnotes - -from webnotes.utils import add_days, add_months, add_years, cint, cstr, date_diff, default_fields, flt, fmt_money, formatdate, generate_hash, getTraceback, get_defaults, get_first_day, get_last_day, getdate, has_common, month_name, now, nowdate, replace_newlines, sendmail, set_default, str_esc_quote, user_format, validate_email_add -from webnotes.model import db_exists -from webnotes.model.doc import Document, addchild, removechild, getchildren, make_autoname, SuperDocType -from webnotes.model.doclist import getlist, copy_doclist -from webnotes.model.code import get_obj, get_server_obj, run_server_obj, updatedb, check_syntax -from webnotes import session, form, is_testing, msgprint, errprint - -set = webnotes.conn.set -sql = webnotes.conn.sql -get_value = webnotes.conn.get_value -in_transaction = webnotes.conn.in_transaction -convert_to_lists = webnotes.conn.convert_to_lists - -# ----------------------------------------------------------------------------------------- - - -class DocType: - def __init__(self, doc, doclist): - self.doc = doc - self.doclist = doclist - - # Get Employees - # ********************************************************************** - def get_employee(self): - e1 = self.emp_fr_memp() #get employee list from employee where employee is active - e2 = self.emp_fr_salstr(e1) #get employee list from salary structure whose salary structure is created and is active - e3 = self.emp_fr_salslip(e2) #get employee list from salary slip whose salary slip not yet created for this month and year - return e3 - - # ********************************************************************** - def emp_fr_memp(self): - lst1 = [[self.doc.employee_type,"employment_type"],[self.doc.branch,"branch"],[self.doc.designation,"designation"],[self.doc.department, "department"],[self.doc.grade,"grade"]] - - condition = "" - #flag = 0 - for l in lst1: - - if(l[0]): - #if flag == 0: - # condition += l[1] + "= '" + l[0] +"'" - #else: - condition += " and " + l[1]+ "= '" +l[0] +"'" - #flag = 1 - - emp_query = "select name from `tabEmployee` where status = 'Active'" - #if flag == 1: - emp_query += condition - - e = sql(emp_query) - return e - - # ********************************************************************** - def emp_fr_salstr(self,e1): - lst = [] - for r in e1: - lst.append(r[0]) - - - e_lst = "%s"%lst - e_lst=e_lst.replace("[","(") - e_lst=e_lst.replace("]",")") - cond = '' - - if e1: - cond = " and employee in %s"%e_lst - - el=sql("select employee from `tabSalary Structure` where is_active = 'Yes'"+cond) - - return el - - # ********************************************************************** - def emp_fr_salslip(self,e2): - e3 = [] - for i in e2: - ret = sql("select name from `tabSalary Slip` where month = '%s' and year = '%s' and employee = '%s' and docstatus !=2 "%(self.doc.month,self.doc.year,i[0])) - - if not ret: - e3.append(i[0]) - return e3 - - # ********************************************************************** - def process_payroll(self): - sal_slip_str = '' - if self.doc.month and self.doc.fiscal_year and self.doc.year: - e = self.get_employee() - if e: - self.doc.emp_lst=e - sal_slip_str += 'Sucessfully created following salary slips:' - for i in e: - ss = Document('Salary Slip') - ss.fiscal_year = self.doc.fiscal_year - ss.employee = i - ss.month = self.doc.month - ss.year= self.doc.year - ss.arrear_amount = self.doc.arrear_amount - ss.email_check = self.doc.email_check - ss.save(1) - salary_obj=get_obj("Salary Slip",ss.name,with_children=1) - salary_obj.process_payroll_all() - sal_slip_str += "
"+ss.name - - else: - - msgprint("For Process Payroll Fiscal Year, Month, Year fields are mandatory.") - if not sal_slip_str: - - sal_slip_str = "No record found." - return cstr(sal_slip_str) - - # ********************************************************************** - def submit_sal_slip(self): - - sal_slip_str = '' - r = sql("select name from `tabSalary Slip` where month='%s' and year = '%s' and fiscal_year = '%s' and docstatus = 0"%(self.doc.month,self.doc.year,self.doc.fiscal_year)) - - - ret = sql("update `tabSalary Slip` set docstatus = 1 where month='%s' and year = '%s' and fiscal_year = '%s' and docstatus = 0"%(self.doc.month,self.doc.year,self.doc.fiscal_year)) - if r: - sal_slip_str += 'Sucessfully updated following salary slips:' - for i in r: - - salary_obj=get_obj("Salary Slip",i[0],with_children=1) - salary_obj.on_submit() - sal_slip_str += "
"+cstr(i[0]) - if not sal_slip_str: - - sal_slip_str = "No record found." - return cstr(sal_slip_str) - - # ********************************************************************** - #get default bank account,default salary acount from company. - def get_acct_dtl(self): - res = sql("select default_bank_account,default_salary_acount from `tabCompany` where name = '%s'"%get_defaults()['company'], as_dict=1) - return res[0] diff --git a/hr/doctype/salary_structure/salary_structure.py b/hr/doctype/salary_structure/salary_structure.py index fd295ea743b..36a1855d6bc 100644 --- a/hr/doctype/salary_structure/salary_structure.py +++ b/hr/doctype/salary_structure/salary_structure.py @@ -42,7 +42,7 @@ class DocType: 'grade' : cstr(det[0][4]), 'backup_employee': cstr(self.doc.employee) } - return cstr(ret) + return ret # Set Salary structure field values @@ -53,7 +53,7 @@ class DocType: 'bank_ac_no' : basic_info and basic_info[0][1] or '', 'esic_no' : basic_info and basic_info[0][2] or '', 'pf_no' : basic_info and basic_info[0][3] or ''} - return cstr(ret) + return ret # Make earning and deduction table #--------------------------------------------------------- diff --git a/hr/doctype/salary_structure/salary_structure.txt b/hr/doctype/salary_structure/salary_structure.txt index 3dcb8f91046..d9a9acd37ab 100644 --- a/hr/doctype/salary_structure/salary_structure.txt +++ b/hr/doctype/salary_structure/salary_structure.txt @@ -5,14 +5,14 @@ { 'creation': '2010-12-14 16:50:05', 'docstatus': 0, - 'modified': '2011-06-27 14:39:11', + 'modified': '2011-08-11 16:56:38', 'modified_by': 'Administrator', 'owner': 'Administrator' }, # These values are common for all DocType { - '_last_update': '1308808105', + '_last_update': '1311621379', 'colour': 'White:FFF', 'doctype': 'DocType', 'module': 'HR', @@ -21,7 +21,7 @@ 'server_code_error': ' ', 'show_in_menu': 0, 'subject': 'For %(employee_name)s', - 'version': 586 + 'version': 587 }, # These values are common for all DocField @@ -39,7 +39,8 @@ 'name': '__common__', 'parent': 'Salary Structure', 'parentfield': 'permissions', - 'parenttype': 'DocType' + 'parenttype': 'DocType', + 'read': 1 }, # DocType, Salary Structure @@ -54,9 +55,9 @@ 'cancel': 0, 'create': 0, 'doctype': 'DocPerm', - 'match': 'owner', + 'idx': 1, 'permlevel': 0, - 'read': 1, + 'role': 'Employee', 'submit': 0, 'write': 0 }, @@ -66,97 +67,40 @@ 'amend': 0, 'cancel': 0, 'create': 0, - 'doctype': 'DocPerm', - 'match': 'owner', - 'permlevel': 0, - 'read': 1, - 'submit': 0, - 'write': 0 - }, - - # DocPerm - { - 'amend': 0, - 'cancel': 0, - 'create': 0, - 'doctype': 'DocPerm', - 'match': 'owner', - 'permlevel': 0, - 'read': 1, - 'submit': 0, - 'write': 0 - }, - - # DocPerm - { - 'amend': 0, - 'cancel': 0, - 'create': 0, - 'doctype': 'DocPerm', - 'match': 'owner', - 'permlevel': 0, - 'read': 1, - 'submit': 0, - 'write': 0 - }, - - # DocPerm - { - 'doctype': 'DocPerm', - 'permlevel': 0, - 'role': 'Sales User' - }, - - # DocPerm - { 'doctype': 'DocPerm', 'idx': 2, 'permlevel': 1, - 'read': 1, 'role': 'All', + 'submit': 0, 'write': 0 }, # DocPerm { - 'create': 1, + 'amend': 0, + 'cancel': 0, + 'create': 0, 'doctype': 'DocPerm', 'idx': 3, 'permlevel': 0, - 'read': 1, 'role': 'HR User', - 'write': 1 + 'submit': 0, + 'write': 0 }, # DocPerm { + 'amend': 1, + 'cancel': 1, 'create': 1, 'doctype': 'DocPerm', 'idx': 4, 'permlevel': 0, - 'read': 1, 'role': 'HR Manager', + 'submit': 1, 'write': 1 }, - # DocPerm - { - 'doctype': 'DocPerm', - 'idx': 5, - 'permlevel': 1, - 'read': 1, - 'role': 'HR Manager' - }, - - # DocPerm - { - 'doctype': 'DocPerm', - 'idx': 6, - 'permlevel': 1, - 'read': 1, - 'role': 'HR User' - }, - # DocField { 'doctype': 'DocField', diff --git a/knowledge_base/page/question_view/question_view.js b/knowledge_base/page/question_view/question_view.js index 895c6f7bcf8..ed11efce8b6 100644 --- a/knowledge_base/page/question_view/question_view.js +++ b/knowledge_base/page/question_view/question_view.js @@ -174,4 +174,4 @@ KBAnswer = function(body, data) { } -$import(knowledge_base.kb_common); \ No newline at end of file +$import(knowledge_base/page/kb_common/kb_common.js); \ No newline at end of file diff --git a/knowledge_base/page/questions/questions.js b/knowledge_base/page/questions/questions.js index 993a38e6422..f268d0bbf0b 100644 --- a/knowledge_base/page/questions/questions.js +++ b/knowledge_base/page/questions/questions.js @@ -203,4 +203,4 @@ KBQuestion = function(parent, det, kb) { this.make() } -$import(knowledge_base.kb_common); \ No newline at end of file +$import(knowledge_base/page/kb_common/kb_common.js); \ No newline at end of file diff --git a/knowledge_base/page/questions/questions.txt b/knowledge_base/page/questions/questions.txt index d71225a7a00..b45c7dde596 100644 --- a/knowledge_base/page/questions/questions.txt +++ b/knowledge_base/page/questions/questions.txt @@ -15,7 +15,7 @@ 'doctype': 'Page', 'module': 'Knowledge Base', 'name': '__common__', - 'page_name': 'Questions', + 'page_name': 'questions', 'standard': 'Yes' }, diff --git a/accounts/search_criteria/lease_receipt_summary_year_to_date/__init__.py b/patches/old_patches/__init__.py similarity index 100% rename from accounts/search_criteria/lease_receipt_summary_year_to_date/__init__.py rename to patches/old_patches/__init__.py diff --git a/patches/old_patches/customer_address.py b/patches/old_patches/customer_address.py index 6a031c4d308..41c97b8e5d8 100644 --- a/patches/old_patches/customer_address.py +++ b/patches/old_patches/customer_address.py @@ -6,7 +6,7 @@ from webnotes import msgprint, errprint def make_address(): from webnotes.modules.module_manager import reload_doc - reload_doc('tools','doctype','address') + reload_doc('utilities','doctype','address') from webnotes.model.db_schema import updatedb updatedb('Address') @@ -113,24 +113,24 @@ def delete_unwanted_fields(): def reload_doc_files(): from webnotes.modules.module_manager import reload_doc - reload_doc('tools', 'doctype', 'contact') - reload_doc('crm', 'doctype', 'customer') - reload_doc('maintenance', 'doctype', 'customer_issue') - reload_doc('material_management', 'doctype', 'delivery_note') - reload_doc('crm', 'doctype', 'enquiry') - reload_doc('crm', 'doctype', 'installation_note') - reload_doc('crm', 'doctype', 'lead') - reload_doc('maintenance', 'doctype', 'maintenance_schedule') - reload_doc('maintenance', 'doctype', 'maintenance_visit') - reload_doc('srm', 'doctype', 'purchase_order') - reload_doc('material_management', 'doctype', 'purchase_receipt') - reload_doc('crm', 'doctype', 'quotation') + reload_doc('utilities', 'doctype', 'contact') + reload_doc('selling', 'doctype', 'customer') + reload_doc('support', 'doctype', 'customer_issue') + reload_doc('stock', 'doctype', 'delivery_note') + reload_doc('selling', 'doctype', 'enquiry') + reload_doc('selling', 'doctype', 'installation_note') + reload_doc('selling', 'doctype', 'lead') + reload_doc('support', 'doctype', 'maintenance_schedule') + reload_doc('support', 'doctype', 'maintenance_visit') + reload_doc('buying', 'doctype', 'purchase_order') + reload_doc('stock', 'doctype', 'purchase_receipt') + reload_doc('selling', 'doctype', 'quotation') reload_doc('accounts', 'doctype', 'receivable_voucher') reload_doc('accounts', 'doctype', 'payable_voucher') - reload_doc('crm', 'doctype', 'sales_order') + reload_doc('selling', 'doctype', 'sales_order') reload_doc('setup', 'doctype', 'sales_partner') - reload_doc('material_management', 'doctype', 'serial_no') - reload_doc('srm', 'doctype', 'supplier') + reload_doc('stock', 'doctype', 'serial_no') + reload_doc('buying', 'doctype', 'supplier') def reload_mapper_files(): from webnotes.modules.module_manager import reload_doc diff --git a/patches/old_patches/feed_patch.py b/patches/old_patches/feed_patch.py index d368aa00c9a..9d8ab0b4dd2 100644 --- a/patches/old_patches/feed_patch.py +++ b/patches/old_patches/feed_patch.py @@ -98,6 +98,5 @@ def support_patch(): webnotes.model.delete_doc('DocType','Support Ticket') reload_doc('setup','doctype','support_email_settings') - reload_doc('maintenance','doctype','support_ticket') - reload_doc('maintenance','doctype','support_ticket_response') - + reload_doc('support','doctype','support_ticket') + reload_doc('support','doctype','support_ticket_response') diff --git a/patches/old_patches/patch_1.py b/patches/old_patches/patch_1.py new file mode 100644 index 00000000000..9173ca5d2f7 --- /dev/null +++ b/patches/old_patches/patch_1.py @@ -0,0 +1,1180 @@ +""" + Old patches for reference +""" + +if patch_no==33: + pass +elif patch_no==34: + webnotes.conn.sql("update `tabDocField` set options = 'Letter Head', print_hide = 1 where fieldname = 'letter_head' and fieldtype = 'Link'") +elif patch_no==35: + webnotes.conn.sql("update tabDocType set module = 'Event Updates' where name = 'Feed Control'") +elif patch_no==36: + # remove delivery note foreign key in Serial Number + from webnotes.model.db_schema import DbTable + t = DbTable('Serial No') + fk_list = t.get_foreign_keys() + for f in fk_list: + if f[0]=='delivery_note_no': + webnotes.conn.commit() + webnotes.conn.sql("alter table `tabSerial No` drop foreign key `%s`" % f[1]) + webnotes.conn.begin() + webnotes.conn.sql("update tabDocField set fieldtype='Data' where fieldname='delivery_note_no' and parent='Serial No' limit 1") +elif patch_no==37: + import os + mod_path = webnotes.defs.modules_path + path_list = [] + for m in os.listdir(mod_path): + for t in ['doctype', 'page', 'search_criteria']: + dt_path = os.path.join(mod_path, m, t) + if os.path.exists(dt_path): + for dt in os.listdir(dt_path): + if '.' not in dt and os.path.exists(os.path.join(dt_path, dt, dt+ '.txt')): + path_list.append(os.path.join(dt_path, dt, dt+ '.txt')) + + for d in path_list: + doclist = eval(open(d,'r').read()) + webnotes.conn.sql("update `tab%s` set module = '%s' where name = '%s'" % (doclist[0]['doctype'], doclist[0]['module'], doclist[0]['name'])) + +elif patch_no==38: + import webnotes + webnotes.conn.set_global("system_message", "System Updates: Hello! You would have noticed some changes on the Home Page. As a part of our commitment to make the system more friendly and social, we have re-designed the feed so that now you will only see feed that is relevant to you (either you have created something or you have been mentioned in the document).

On the individual listings, you can add tags and also color them!

You will also get time-to-time updates from our side here. Do keep sending your feedback at support@erpnext.com.") + webnotes.conn.set_global("system_message_id", "1") + +elif patch_no == 39: + pass + +elif patch_no == 40: + import_from_files(record_list=[['material_management','doctype','item']]) + +elif patch_no == 42: + acc = sql("select name, lft, rgt from tabAccount where account_name in ('Incomes', 'Expenses')") + for d in acc: + sql("update tabAccount set is_pl_account = 'Yes' where lft >= '%s' and rgt <= '%s'" % (d[1], d[2])) +elif patch_no == 43: + import webnotes.model + webnotes.model.delete_doc('Page', 'Module Manager') + +# cleanup of Service, Customer Support, Utilities Modules +# ------------------------------------------------------- +elif patch_no == 44: + from webnotes.model import delete_doc + + for dt in sql("select name from tabDocType where module in ('Customer Support')"): + delete_doc('DocType', dt[0]) + + for dt in sql("select name from `tabSearch Criteria` where module in ('Customer Support')"): + delete_doc('Search Criteria', dt[0]) + + for dt in sql("select name from tabPage where module in ('Customer Support')"): + delete_doc('Page', dt[0]) + + # move a couple + webnotes.conn.sql("update `tab%s` set module=%s where name=%s" % ('DocType', '%s', '%s'), ('Application Internal', 'Patch Util')) + webnotes.conn.sql("update `tab%s` set module=%s where name=%s" % ('DocType', '%s', '%s'), ('Application Internal', 'DocType Property Setter')) + + # remove utilities + webnotes.conn.sql('delete from `tabModule Def` where name in ("Customer Support", "Utilities")') + +elif patch_no == 45: + webnotes.conn.sql('delete from tabDocField where options="Ticket Response Detail"') + +elif patch_no == 46: + import webnotes + webnotes.conn.set_global("system_message", "SYSTEM DOWNTIME: Hello! As part of our commitment to keep improving the service, we are planning a scheduled maintenance on our servers for 4 hrs on 16-Jan-2011(Sunday), from 10AM to 2PM. Do keep sending your feedback at support@erpnext.com.") + webnotes.conn.set_global("system_message_id", "2") + +elif patch_no == 47: + import webnotes + webnotes.conn.set_global("system_message", "") + webnotes.conn.set_global("system_message_id", "3") + +elif patch_no == 48: + webnotes.conn.sql("update tabDocField set options = 'Print Heading' where fieldname = 'select_print_heading'") + +elif patch_no == 49: + webnotes.conn.sql("update tabDocType set autoname = '' where name = 'Search Criteria'") +elif patch_no == 50: + sql("update tabDocField set in_filter = 1 where fieldname in ('cost_center', 'income_account', 'Item Group') and parent = 'RV Detail'") +elif patch_no == 51: + sql("update tabDocField set options = 'link:Print Heading' where fieldtype = 'Select' and fieldname = 'select_print_heading' and parent = 'POS Setting'") +elif patch_no == 52: + sql("update tabDocField set print_hide = 1 where fieldname = 'letter_head'") +elif patch_no == 53: + sql("update tabDocType set search_fields = 'lead_name,lead_owner,status,contact_by,contact_date' where name = 'Lead'") +elif patch_no == 54: + sql("delete from tabDocField where parent = 'Supplier' and label = 'Supplier Contacts' and fieldtype = 'Section Break'") +elif patch_no == 55: + sql("commit") + try: + sql("alter table tabFeed add column `_user_tags` varchar(180)") + except Exception, e: + if e.args[0]!=1060: + raise e +elif patch_no == 56: + sql("delete from `tabModule Def Item` where parent = 'CRM' and doc_type = 'Reports' and doc_name = 'Delivery Note' and display_name = 'Territory, Item Group wise GP'") +elif patch_no == 57: + import_from_files(record_list=[['selling','doctype','sales_order_detail']]) + +elif patch_no == 58: + # module def patches + sql("update `tabModule Def` set module_page = NULL where name not in ('Event Updates', 'Setup', 'My Company')") + sql("delete from `tabModule Def Item` where doc_type in ('Separator', 'Setup Forms', 'More Reports')") + sql("delete from `tabModule Def Item` where doc_name = 'Project Activity'") + sql("update `tabModule Def` set module_label = 'People', disabled='No', is_hidden='No' where name = 'My Company'") + + # insert new module items + from webnotes.model.doc import make_autoname + if not sql("select name from `tabModule Def Item` where parent='Projects' and doc_name='Ticket'"): + sql("""insert into `tabModule Def Item` + (name, parent, parenttype, parentfield, docstatus, doc_type, doc_name, display_name, idx) values + (%s, 'Projects', 'Module Def', 'items', 0, 'Forms', 'Ticket', 'Task', 1)""", make_autoname('MDI.#####')) + + if not sql("select name from `tabModule Def Item` where parent='Projects' and doc_name='Timesheet'"): + sql("""insert into `tabModule Def Item` + (name, parent, parenttype, parentfield, docstatus, doc_type, doc_name, display_name, idx) values + (%s, 'Projects', 'Module Def', 'items', 0, 'Forms', 'Timesheet', 'Timesheet', 2)""", make_autoname('MDI.#####')) + + if not sql("select name from `tabModule Def Item` where parent='Projects' and doc_name='Projects'"): + sql("""insert into `tabModule Def Item` + (name, parent, parenttype, parentfield, docstatus, doc_type, doc_name, display_name, idx) values + (%s, 'Projects', 'Module Def', 'items', 0, 'Pages', 'Projects', 'Gantt Chart', 1)""", make_autoname('MDI.#####')) + +elif patch_no == 59: + webnotes.conn.set_value('Control Panel',None,'mail_footer','') + webnotes.conn.set_global('global_mail_footer','
Sent via ERPNext
') +elif patch_no == 60: + sql("delete from `tabModule Def Item` where display_name = 'Point of Sales'") +elif patch_no == 61: + sql("delete from `tabTDS Category Account` where company not in (select name from tabCompany)") +elif patch_no == 62: + # Import Supplier Quotation + import_from_files(record_list=[['srm','doctype','supplier_quotation']]) + + # Adding Status Filter + sql("update tabDocType set search_fields = concat('status,',search_fields) where name IN ('Delivery Note','Leave Transaction')") + # Import Other Charges + + import_from_files(record_list=[['setup','doctype','other_charges']]) +elif patch_no == 63: + sql("update `tabDocField` set permlevel = 1 where fieldname in ('return_date', 'return_details') and parent = 'Sales and Purchase Return Wizard'") + import_from_files(record_list = [['accounts', 'doctype', 'rv_detail'], ['material_management', 'doctype', 'sales_and_purchase_return_wizard'], ['material_management', 'doctype', 'stock_entry']]) + +elif patch_no == 64: + sql("update tabDocField set `hidden` = 1, `print_hide` = 1, `report_hide` = 1 where options in ('RFQ','Supplier Quotation')") + sql("update tabDocType set `read_only` = 1, in_create = 1 where name in ('RFQ','Supplier Quotation')") + sql("update tabDocField set `report_hide` = 0 where fieldname in ('email_id','phone_1','fax_1') and parent = 'Customer'") +elif patch_no == 65: + # Monthly Trend Analyzer <-> Trend Analyzer + sql("update `tabSearch Criteria` set criteria_name = 'Trend Analyzer' where criteria_name = 'Monthly Trend Analyzer' and name = 'SRCH/00159'") + sql("update `tabModule Def Item` set display_name = 'Trend Analyzer' where parent = 'Analysis' and display_name = 'Monthly Trend Analyzer'") +elif patch_no == 66: + import webnotes + webnotes.conn.set_global("system_message", """

UI Updates

Based on user feedback, we have made a couple of changes in the UI:
  • Sidebar menus are now collapsable
  • Forms are now scrollable (we removed the confusing tabs)
  • Feed is a lot more descriptive
Do send us your feedback!""") + webnotes.conn.set_global("system_message_id", "4") + + sql("update `tabModule Def Item` set doc_type = 'Setup Forms' where doc_name in ('TDS Payment', 'TDS Return Acknowledgement', 'Form 16A', 'Period Closing Voucher', 'IT Checklist')") + from webnotes.session_cache import clear_cache + clear_cache(webnotes.session['user']) +elif patch_no == 67: + sql("update `tabDocField` set in_filter = 1 where fieldname = 'brand' and parent = 'RV Detail'") + sql("delete from `tabModule Def Item` where (display_name = 'Sales Invoice' and parent = 'CRM') or (display_name = 'Purchase Invoice' and parent = 'SRM')") +elif patch_no == 68: + from webnotes.modules.import_module import import_from_files + import_from_files(record_list=[['hr','doctype','employee'],['roles','Role','Employee']]) +elif patch_no == 69: + # delete flds from employee master + p = get_obj('Patch Util') + emp_del_flds = ['month_of_birth'] + for f in emp_del_flds: + p.delete_field('Employee', f) + + sql("Update tabDocField set `default` = 'Active' where fieldname = 'status' and parent = 'Employee'") + + # map parent flds + fld_map = ['cell_number', 'personal_email', 'person_to_be_contacted', 'relation', 'emergency_phone_number', 'pan_number', 'passport_number', 'date_of_issue', 'valid_upto', 'place_of_issue', 'marital_status', 'blood_group', 'permanent_accommodation_type'] + + emp_prof = sql("select t1.name, t1.employee, t1.permanent_address_line_1, t1.permanent_address_line_2, t1.city1, t1.state1, t1.country1, t1.pin_code1, t1.phn_no1, t1.present_address_line_1, t1.present_address_line_2, t1.city2, t1.state2, t1.country2, t1.pin_code2, t1.phn_no2, t1.fathers_name, t1.fathers_occupation, t1.mothers_name, t1.mothers_occupation, t1.spouses_name, t1.spouses_occupation, t1.height_cms, t1.weight_kgs, t1.allergies, t1.other_medical_concerns, t1.physical_handicap from `tabEmployee Profile` t1, `tabEmployee` t2 where t1.employee = t2.name") + for e in emp_prof: + prof_obj = get_obj('Employee Profile', e[0]) + emp_obj = get_obj('Employee', e[1]) + for d in fld_map: + emp_obj.doc.fields[d] = prof_obj.doc.fields[d] + emp_obj.doc.current_accommodation_type = prof_obj.doc.present_accommodation_type + + # address + per_addr = cstr(e[2]) + '\n' + cstr(e[3]) + '\n' + cstr(e[4]) + '\n' + cstr(e[5]) + ', ' + cstr(e[6]) + '\n' + 'PIN - ' + cstr(e[7]) + '\n' + 'Ph. No' + cstr(e[8]) + cur_addr = cstr(e[9]) + '\n' + cstr(e[10]) + '\n' + cstr(e[11]) + '\n' + cstr(e[12]) + ', ' + cstr(e[13]) + '\n' + 'PIN - ' + cstr(e[14]) + '\n' + 'Ph. No' + cstr(e[15]) + emp_obj.doc.permanent_address = per_addr + emp_obj.doc.current_address = cur_addr + #family + fam = "Father's Name: " + cstr(e[16]) + '\n' + "Father's Occupation: " + cstr(e[17]) + '\n' + "Mother's Name: " + cstr(e[18]) + '\n' + "Mother's Occupation: " + cstr(e[19]) + '\n' + "Spouse's Name: " + cstr(e[20]) + '\n' + "Spouse's Occupation: " + cstr(e[21]) + emp_obj.doc.family_background = fam + # health + health = 'Height(cms): ' + cstr(e[22]) + '\n' + 'Weight(kgs): ' + cstr(e[23]) + '\n' + 'Allergies: ' +cstr( e[24]) + '\n' + 'Other Medical Concern: ' + cstr(e[25]) + '\n' + 'Physically Handicapped(if any): ' + cstr(e[26]) + emp_obj.doc.health_details = health + emp_obj.doc.save() + + + # map tables + tbl_list = ['Experience In Company Detail', 'Previous Experience Detail', 'Educational Qualifications Detail'] + for t in tbl_list: + sql("update `tab%s` t1, `tabEmployee Profile` t2 set t1.parent = t2.employee, t1.parenttype = 'Employee' where t1.parent = t2.name" % t) + + + # overwrite idx????????? + + + # delete emp profile + webnotes.model.delete_doc('DocType', 'Employee Profile') + for e in emp_prof: + webnotes.model.delete_doc('Employee Profile', e[0]) + +elif patch_no == 70: + # update search criteria module -> System + sql("update tabDocType set module='System' where name='Search Criteria'") + + # Cleanups to Contact + sql("update tabDocField set fieldtype='Data' where options='Designation' and parent='Contact'") + sql("update tabDocField set fieldtype='Data' where options='Department' and parent='Contact'") + sql("update tabDocField set depends_on='eval:(cint(doc.is_customer) || cint(doc.is_supplier) || cint(doc.is_sales_partner))' where fieldname='is_primary_contact' and parent='Contact'") + + # import Contact, Employee + from webnotes.modules.import_module import import_from_files + import_from_files(record_list=[['utilities','doctype','contact']]) + + + # remove last_contact_date from Lead + sql("delete from tabDocField where fieldname='last_contact_date' and parent='Lead'") + +elif patch_no == 71: + # Make Stock Qty and Conversion Factor field editable. Also no need to mention Conversion factor in table can do it directly + sql("update `tabDocField` set `permlevel` = 0, `width` = '100px', `trigger` = 'Client' where parent IN ('PO Detail','Purchase Receipt Detail') and fieldname in ('stock_qty','conversion_factor')") + sql("update `tabDocField` set `width` = '100px' where parent IN ('PO Detail','Purchase Receipt Detail') and fieldname = 'stock_uom'") + +elif patch_no == 72: + # Core Patch + # ---------- + + from webnotes.modules.import_module import import_from_files + + # import module def + import_from_files(record_list = [['core', 'Module Def', 'Core']]) +elif patch_no == 73: + # set module in DocTypes + sql("update tabDocType set module='Core' where name in ('DocType', 'DocField', 'DocPerm', 'Role', 'UserRole', 'Profile', 'Print Format', 'DocFormat', 'Control Panel', 'Event', 'Event Role', 'Event User', 'DefaultValue', 'Default Home Page', 'File', 'File Group', 'File Data', 'Letter Head', 'Module Def', 'Module Def Item', 'Module Def Role', 'Page', 'Page Role', 'Search Criteria', 'DocType Label', 'DocType Mapper', 'Field Mapper Detail', 'Table Mapper Detail')") + + # set module in Page + sql("update tabPage set module='Core' where name='Login Page'") + + # move file browser to Tools + sql("update tabPage set module='Tools' where name='File Browser'") + sql("update tabDocType set module='Tools' where name='File Browser Control'") + sql("update tabDocType set module='Application Internal' where name='Profile Control'") +elif patch_no == 74: + p = get_obj('Patch Util') + # permission + p.delete_permission('Employee', 'Administrator', 0) + p.delete_permission('Employee', 'Administrator', 1) + p.add_permission('Employee', 'Employee', 0, read = 1, match = 'owner') + p.add_permission('Employee', 'Employee', 1, read = 1, match = 'owner') + sql("delete from `tabDocField` where parent = 'Employee' and label = 'Payroll Rule'") +elif patch_no == 75: + #sal structure patch + # import + from webnotes.modules.import_module import import_from_files + import_from_files(record_list=[['hr','doctype','salary_structure'], ['hr','doctype','earning_detail'],['hr','doctype','deduction_detail']]) +elif patch_no == 76: + # property + p = get_obj('Patch Util') + p.set_field_property('Salary Structure', 'is_active', 'default', 'Yes') + p.set_field_property('Salary Structure', 'ctc', 'reqd', '1') + p.set_field_property('Earning Detail', 'modified_value', 'width', '') + p.set_field_property('Earning Detail', 'modified_value', 'trigger', 'Client') + p.set_field_property('Deduction Detail', 'd_modified_amt', 'width', '') + p.set_field_property('Earning Detail', 'd_modified_amt', 'trigger', 'Client') + sql("Update tabDocField set `description` = 'You can create more earning and deduction type from Setup --> HR' where label = 'Earning & Deduction' and parent = 'Salary Structure' and fieldtype = 'Section Break'") + + # delete + sql("update `tabSalary Structure` set net_pay = total") + sql("delete from tabDocField where label in ('LWP Help', 'Calculate Total', 'Total') and parent = 'Salary Structure'") + sql("delete from tabDocPerm where parent in ('Earning Detail', 'Deduction Detail')") + + + # permission + p.delete_permission('Salary Structure', 'Administrator', 0) + p.delete_permission('Salary Structure', 'Administrator', 1) + p.add_permission('Salary Structure', 'Employee', 0, read = 1, match = 'owner') + p.add_permission('Salary Structure', 'Employee', 1, read = 1, match = 'owner') +elif patch_no == 77: + # sal slip patch + # import + from webnotes.modules.import_module import import_from_files + import_from_files(record_list=[['hr','doctype','salary_slip'], ['hr','doctype','ss_earning_detail'],['hr','doctype','ss_deduction_detail'], ['mapper', 'DocType Mapper', 'Salary Structure-Salary Slip']]) +elif patch_no == 78: + p = get_obj('Patch Util') + # delete + sql("update `tabSalary Slip` set leave_encashment_amount = encashment_amount") + p.delete_field('Salary Slip', 'encashment_amount') + p.delete_field('Salary Slip', 'year') + p.delete_field('Salary Slip', 'flag') + sql("delete from tabDocField where label = 'Process Payroll' and parent = 'Salary Slip'") + + # field property + p.set_field_property('Salary Slip', 'bank_name', 'permlevel', '1') + p.set_field_property('Salary Slip', 'leave_without_pay', 'permlevel', '0') + p.set_field_property('Salary Slip', 'leave_without_pay', 'trigger', 'Client') + p.set_field_property('SS Earning Detail', 'e_type', 'permlevel', '0') + p.set_field_property('SS Earning Detail', 'e_type', 'fieldtype', 'Link') + p.set_field_property('SS Earning Detail', 'e_type', 'options', 'Earning Type') + p.set_field_property('SS Deduction Detail', 'd_type', 'permlevel', '0') + p.set_field_property('SS Deduction Detail', 'd_type', 'fieldtype', 'Link') + p.set_field_property('SS Deduction Detail', 'd_type', 'options', 'Deduction Type') + sql("update `tabSS Earning Detail` set e_modified_amount = e_amount") + sql("update `tabSS Deduction Detail` set d_modified_amount = d_amount") + + # permission + p.delete_permission('Salary Slip', 'Administrator', 0) + p.delete_permission('Salary Slip', 'Administrator', 1) + p.add_permission('Salary Slip', 'Employee', 0, read = 1, match = 'owner') + p.add_permission('Salary Slip', 'Employee', 1, read = 1, match = 'owner') +elif patch_no == 79: + # Import Modules + import_from_files(record_list=[['hr','doctype','leave_application'],['hr','doctype','leave_allocation'],['hr','doctype','leave_control_panel'],['hr','doctype','holiday_list'],['hr','doctype','holiday_list_detail'],['hr','Module Def','HR']]) +elif patch_no == 80: + # Holiday List + sql("update `tabHoliday List Detail` set description = holiday_name") + sql("delete from tabDocField where parent = 'Holiday List Detail' and fieldname = 'holiday_name'") + sql("update tabDocField set fieldtype = 'Select', options = 'link:Fiscal Year' where parent = 'Holiday List' and fieldname = 'fiscal_year'") + sql("delete from tabDocPerm where role in ('Administrator','HR User') and parent = 'Holiday List'") + + # Leave Control Panel + # -------------------- + sql("delete from `tabDocField` where parent = 'Leave Control Panel' and label in ('Leave Control Panel','Allocation Details') and fieldtype = 'Section Break'") + sql("delete from tabDocField where parent = 'Leave Control Panel' and fieldname in ('col_brk3','allocation_type','col_brk2','from_date','to_date','leave_transaction_type','posting_date')") + sql("update tabDocField set fieldtype = 'Select', options = 'link:Fiscal Year' where parent = 'Leave Control Panel' and fieldname = 'fiscal_year'") + sql("update tabDocField set fieldtype = 'Select', options = 'link:Leave Type' where parent = 'Leave Control Panel' and fieldname = 'leave_type'") + sql("update tabDocField set reqd = 1 where parent = 'Leave Control Panel' and fieldname = 'no_of_days'") + + # Leave Application + # ------------------ + for d in sql("select * from `tabLeave Transaction` where leave_transaction_type = 'Deduction' and ifnull(deduction_type, '') = 'Leave'", as_dict = 1): + lp = Document('Leave Application') + lp.employee = d['employee'] + lp.leave_type = d['leave_type'] + lp.posting_date = d['date'] + lp.fiscal_year = d['fiscal_year'] + lp.leave_balance = d['pre_balance'] + lp.half_day = d['half_day'] + lp.from_date = d['from_date'] + lp.to_date = d['to_date'] + lp.total_leave_days = d['total_leave'] + lp.description = d['reason'] + lp.docstatus = cint(d['docstatus']) + lp.save(1) + + # Leave Allocation + # ----------------- + for d in sql("select * from `tabLeave Transaction` where leave_transaction_type = 'Allocation'", as_dict = 1): + la = Document('Leave Allocation') + la.employee = d['employee'] + la.leave_type = d['leave_type'] + la.posting_date = d['date'] + la.fiscal_year = d['fiscal_year'] + la.new_leaves_allocated = d['total_leave'] + la.total_leaves_allocated = d['total_leave'] + la.description = d['reason'] + la.docstatus = cint(d['docstatus']) + la.save(1) + + # Payroll Module Def + # ------------------- + sql("delete from `tabModule Def Item` where doc_name = 'Leave Transaction' and display_name = 'Leave Transaction' and parent = 'Payroll' and doc_type = 'Forms'") + +elif patch_no == 81: + # Import Modules + import_from_files(record_list=[['hr','Module Def','HR']]) +elif patch_no == 82: + sql("update tabDocType set search_fields = 'employee,leave_type,total_leaves_allocated,fiscal_year' where name = 'Leave Allocation'") + sql("update tabDocType set search_fields = 'employee,leave_type,from_date,to_date,total_leave_days,fiscal_year' where name = 'Leave Application'") +elif patch_no == 83: + # delete leave transaction + webnotes.conn.sql("set foreign_key_checks=0") + sql("delete from `tabLeave Transaction`") + import webnotes.model + webnotes.model.delete_doc('DocType','Badge Settings Detail') + webnotes.model.delete_doc('DocType','Leave Transaction') + webnotes.conn.sql("set foreign_key_checks=1") +elif patch_no == 84: + p = get_obj('Patch Util') + p.set_field_property('SS Earning Detail', 'e_amount', 'permlevel', '1') + p.set_field_property('SS Deduction Detail', 'd_amount', 'permlevel', '1') +elif patch_no == 85: + # permission + p = get_obj('Patch Util') + p.add_permission('Leave Application', 'Employee', 0, read = 1, write = 1, create = 1, submit = 1, cancel = 1, amend = 1, match = 'owner') + p.add_permission('Leave Application', 'Employee', 1, read = 1, match = 'owner') + p.add_permission('Leave Allocation', 'HR User', 0, read = 1, write = 1, create = 1, submit = 1, cancel = 1, amend = 1, match = 'owner') + p.add_permission('Leave Allocation', 'HR User', 1, read = 1) + sql("update tabDocPerm set `match` = '' where parent = 'Leave Application' and role = 'HR User'") +elif patch_no == 86: + # Import Modules + import_from_files(record_list=[['hr','doctype','leave_type']]) +elif patch_no == 87: + sql("update `tabLeave Type` set is_lwp = 1 where name = 'Leave Without Pay'") +elif patch_no == 88: + # Import Modules + import_from_files(record_list=[['hr','doctype','leave_allocation']]) + +elif patch_no == 89: + sql("delete from `tabModule Def Item` where doc_type = 'Setup Forms' and doc_name in ('Payroll Rule', 'IT Checklist', 'Employee Profile') and parent = 'Payroll'") + sql("update `tabDocField` set `hidden` = 1, `print_hide` = 1, `report_hide` = 1 where parent = 'Leave Type' and fieldname = 'is_encash'") +elif patch_no == 90: + sql("update `tabLeave Allocation` set docstatus = 1") +elif patch_no == 91: + import webnotes + webnotes.conn.set_global("system_message", """

System Updates

Based on user feedback, we have cleaned up HR module (Partly):
  • Employee and Employee Profile are merged into a single document
  • Salary Structure and Salary Slip are now more user friendly
  • Leave Transaction document is now divided into 2 documents Leave Application and Leave Allocation
We will work on Reports, Attendance and other documents of Payroll module next week

Do send us your feedback!""") + webnotes.conn.set_global("system_message_id", "5") +elif patch_no == 92: + sql("update tabDocField set label = 'Get Charges' where parent IN ('Sales Order','Delivery Note','Receivable Voucher') and label = 'Get Other Charges' and fieldtype = 'Button'") + # Automated Other Charges Calculation basis + sql("update tabDocField set options = '', `trigger` = 'Client' where parent IN ('Quotation','Sales Order','Delivery Note','Receivable Voucher') and label = 'Get Charges' and fieldtype = 'Button'") +elif patch_no == 93: + sql("update `tabTable Mapper Detail` set validation_logic = 'qty > ifnull(billed_qty,0) and docstatus = 1' where parent = 'Sales Order-Receivable Voucher' and from_table = 'Sales Order Detail'") + sql("update `tabField Mapper Detail` set from_field = 'customer' where to_field = 'customer' and parent = 'Sales Order-Receivable Voucher'") +elif patch_no == 94: + import_from_files(record_list=[['selling','doctype','sms_center']]) +elif patch_no == 95: + import_from_files(record_list=[['mapper','DocType Mapper','Sales Order-Receivable Voucher'], ['mapper','DocType Mapper','Delivery Note-Receivable Voucher']]) +elif patch_no == 96: + sql("delete from `tabModule Def Item` where doc_type = 'Reports' and display_name = 'Cenvat Credit - Input or Capital Goods' and parent = 'Accounts'") +elif patch_no == 97: + sql("update tabFeed set doc_label = 'Feed', doc_name = name where ifnull(doc_name,'') = '' and ifnull(doc_label,'') = ''") +elif patch_no == 98: + import_from_files(record_list=[['accounts','doctype','payable_voucher']]) +elif patch_no == 99: + import_from_files(record_list=[['accounts','doctype','account']]) +elif patch_no == 100: + p = get_obj('Patch Util') + p.set_field_property('Account', 'level', 'hidden', '1') + p.set_field_property('Account', 'level', 'print_hide', '1') + p.set_field_property('Account', 'account_type', 'search_index', '0') + p.set_field_property('TDS Detail', 'tds_category', 'width', '150px') + p.set_field_property('TDS Detail', 'special_tds_rate_applicable', 'width', '150px') + p.set_field_property('TDS Detail', 'special_tds_rate', 'width', '150px') + p.set_field_property('TDS Detail', 'special_tds_limit', 'width', '150px') +elif patch_no == 101: + # Leave Application Details and Leave Allocation Details + sql("update tabDocField set search_index = 1, in_filter = 1 where fieldname in ('employee','leave_type','fiscal_year') and parent in ('Leave Application','Leave Allocation')") + get_obj('DocType','Leave Application').doc.save() + get_obj('DocType','Leave Allocation').doc.save() +elif patch_no == 102: + # make item description field editable in production order + sql("update tabDocField set permlevel = 0 where fieldname = 'description' and parent = 'Production Order'") +elif patch_no == 103: + sql("update tabDocField set fieldname = '' where fieldtype = 'HTML'") +elif patch_no == 104: + import_from_files(record_list=[['hr','search_criteria','stdsrch_00001'],['hr','search_criteria','stdsrch_00002'],['hr','search_criteria','stdsrch_00003'],['hr','Module Def','HR'],['hr','doctype','leave_application'],['hr','doctype','leave_allocation']]) + +elif patch_no == 105: + # Employee Leave Balance + sql("delete from `tabModule Def Item` where parent = 'Payroll' and doc_type = 'Reports' and display_name IN ('Employeewise Leave Transaction Details','Employeewise Balance Leave Report')") + # Update Search Fields + sql("update tabDocType set search_fields = 'employee,employee_name,leave_type,from_date,to_date,total_leave_days,fiscal_year' where name = 'Leave Application'") + sql("update tabDocType set search_fields = 'employee,employee_name,leave_type,total_leaves_allocated,fiscal_year' where name = 'Leave Allocation'") +elif patch_no == 106: + for d in sql("select name,employee,employee_name from `tabLeave Allocation`"): + if not cstr(d[2]): + sql("update `tabLeave Allocation` set employee_name = '%s' where name = '%s'" % (webnotes.conn.get_value('Employee',cstr(d[1]),'employee_name'), cstr(d[0]))) + for d in sql("select name,employee,employee_name from `tabLeave Application`"): + if not cstr(d[2]): + sql("update `tabLeave Application` set employee_name = '%s' where name = '%s'" % (webnotes.conn.get_value('Employee',cstr(d[1]),'employee_name'), cstr(d[0]))) +elif patch_no == 107: + sql("delete from `tabDocField` where fieldname = 'fiscal_year' and parent = 'Employee'") +elif patch_no == 108: + import_from_files(record_list=[['hr','search_criteria','srch_std_00013']]) +elif patch_no == 109: + import_from_files(record_list=[['hr','search_criteria','srch_std_00015']]) +elif patch_no == 110: + import_from_files(record_list=[['hr','doctype','salary_structure'], ['hr', 'doctype', 'salary_slip']]) +elif patch_no == 111: + sql("update tabDocType set search_fields = 'transfer_date, from_warehouse, to_warehouse, purpose, remarks' where name = 'Stock Entry'") +elif patch_no == 112: + sql("delete from tabDocField where label = 'Get Other Charges' and fieldtype = 'Button' and parent = 'Receivable Voucher'") +elif patch_no == 113: + sql("update tabDocField set reqd = 1 where parent = 'Customer' and fieldname = 'phone_1'") +elif patch_no == 114: + for d in sql("select name, master_name, credit_days, credit_limit from tabAccount where master_type = 'Customer'"): + if cstr(d[1]): + days, limit = cint(d[2]), flt(d[3]) + cust_det = sql("select credit_days, credit_limit from tabCustomer where name = '%s'" % (cstr(d[1]))) + if not days: days = cust_det and cint(cust_det[0][0]) or 0 + if not limit: limit = cust_det and flt(cust_det[0][1]) or 0 + sql("COMMIT") + sql("START TRANSACTION") + sql("update tabAccount set credit_days = '%s', credit_limit = '%s' where name = '%s'" % (days, limit, cstr(d[0]))) + sql("COMMIT") + +elif patch_no == 115: + # patch for timesheet cleanup + from webnotes.model import delete_doc + delete_doc('DocType', 'Timesheet Detail') + + from webnotes.modules.import_module import import_from_files + import_from_files(record_list = [['Projects', 'DocType', 'Timesheet'], ['Projects', 'DocType', 'Timesheet Detail'], ['Projects', 'DocType', 'Activity Type']]) + +elif patch_no == 116: + # again! + from webnotes.model import delete_doc + delete_doc('DocType', 'Timesheet Detail') + + from webnotes.modules.import_module import import_from_files + import_from_files(record_list = [['Projects', 'DocType', 'Timesheet Detail']]) +elif patch_no == 117: + op = '\n' + 'Walk In' + sql("update `tabDocField` set `options` = concat(options, %s) where parent = 'Enquiry' and fieldname = 'source' and options not like '%%Walk%%'", op) +elif patch_no == 118: + from webnotes.utils import get_defaults + ss = sql("select name, net_pay from `tabSalary Slip`") + for d in ss: + if d[1]: + w = get_obj('Sales Common').get_total_in_words(get_defaults()['currency'], d[1]) + sql("update `tabSalary Slip` set net_pay_in_words = '%s' where name = '%s'" % (w, d[0])) +elif patch_no == 119: + sql("update tabDocType set in_create = 1 where name = 'Profile'") +elif patch_no == 120: + sql("update tabDocField set permlevel = 0 where parent = 'Sales and Purchase Return Wizard' and fieldname = 'return_date'") +elif patch_no == 121: + import_from_files(record_list = [['CRM', 'DocType', 'Return Detail'], ['Material Management', 'DocType', 'Sales and Purchase Return Wizard']]) +elif patch_no == 122: + sql("delete from tabDocField where (fieldname = 'serial_no' or label = 'Warrany Status') and parent = 'Sales Order'") +elif patch_no == 123: + import_from_files(record_list = [['CRM', 'Module Def', 'CRM'], ['CRM', 'Search Criteria', 'STDSRCH/00004']]) +elif patch_no == 124: + import webnotes + webnotes.conn.set_global("system_message", """

Updates(New)

We have added a new report in the Selling Module.

Sales Personwise Transaction Summary: In this report you can see sales person's contribution in a particular order, delivery or invoice. You can select voucher type in "Based On" filter.

Do send us your feedback!""") + webnotes.conn.set_global("system_message_id", "5") +elif patch_no == 125: + import_from_files(record_list = [['Material Management', 'DocType', 'Delivery Note']]) +elif patch_no == 126: + sql("delete from tabDocField where parent = 'Delivery Note' and label in ('Make Sales Invoice', 'Make Installation Note', 'Intro Note')") +elif patch_no == 127: + sql("delete from tabDocPerm where role = 'All' and parent = 'Expense Voucher' and (permlevel = 0 or permlevel = 2)") + p = get_obj('Patch Util') + p.add_permission('Expense Voucher', 'Employee', 0, read = 1, write = 1, create = 1, submit = 1, cancel = 1, amend = 1, match = 'owner') + p.add_permission('Expense Voucher', 'HR Manager', 0, read = 1, write = 1, create = 1, submit = 1, cancel = 1, amend = 1) + p.add_permission('Expense Voucher', 'HR User', 0, read = 1, write = 1, create = 1, submit = 1, cancel = 1, amend = 1) +elif patch_no == 128: + from webnotes.modules import import_module + import_module.import_from_files(record_list=[['selling','doctype','sales_order'], ['selling','doctype','sales_order_detail'], ['stock','doctype','delivery_note'], ['stock','doctype','delivery_note_detail']]) +elif patch_no == 129: + sql("update `tabTable Mapper Detail` set validation_logic = '(qty > ifnull(billed_qty, 0) or amount > ifnull(billed_amt, 0)) and docstatus = 1' where parent = 'Sales Order-Receivable Voucher' and from_table = 'Sales Order Detail' and to_table = 'RV Detail'") + sql("update `tabTable Mapper Detail` set validation_logic = '(qty > ifnull(billed_qty, 0) or amount > ifnull(billed_amt, 0)) and docstatus = 1' where parent = 'Delivery Note-Receivable Voucher' and from_table = 'Delivery Note Detail' and to_table = 'RV Detail'") +elif patch_no == 130: + # update from rv + from webnotes.model.code import get_obj + from webnotes.utils import cstr + for d in sql("select name, docstatus from `tabReceivable Voucher` where ifnull(docstatus,0) != 0"): + sql("COMMIT") + sql("START TRANSACTION") + try: + obj = get_obj('Receivable Voucher', cstr(d[0]), with_children = 1) + is_submit = 1 + if cint(d[1]) == 2: is_submit = 0 + get_obj('Sales Common').update_prevdoc_detail(is_submit, obj) + except: + pass + sql("COMMIT") + + # update from dn + from webnotes.model.code import get_obj + for d in sql("select name, docstatus from `tabDelivery Note` where ifnull(docstatus,0) != 0"): + sql("COMMIT") + sql("START TRANSACTION") + try: + obj = get_obj('Delivery Note', cstr(d[0]), with_children = 1) + is_submit = 1 + if cint(d[1]) == 2: is_submit = 0 + get_obj('Sales Common').update_prevdoc_detail(is_submit, obj) + except: + pass + sql("COMMIT") +elif patch_no == 131: + sql("update `tabDocType` set allow_trash = 1 where name = 'Purchase Other Charges'") + sql("update tabDocPerm set `cancel` = 1 where parent = 'Purchase Other Charges' and permlevel = 0 and `read` = 1 and `write` = 1") +elif patch_no == 132: + sql("update tabDocField set no_copy = 0 where parent = 'Receivable Voucher' and fieldname = 'customer'") +elif patch_no == 133: + from webnotes.modules import import_module + import_module.import_from_files(record_list=[['accounts','doctype','receivable_voucher']]) +elif patch_no == 134: + sql("update tabDocField set no_copy = 1 where parent = 'Receivable Voucher' and fieldname = 'posting_time'") +elif patch_no == 135: + sql("update tabDocField set `default` = 'Today' where parent = 'Receivable Voucher' and fieldname = 'due_date'") +elif patch_no == 136: + from webnotes.modules import import_module + import_module.import_from_files(record_list=[['accounts','doctype','rv_detail']]) +elif patch_no == 137: + from webnotes.modules import import_module + import_module.import_from_files(record_list=[['setup','doctype','price_list']]) +elif patch_no == 138: + sql("update `tabDocType` set allow_attach = 1 where name = 'Price List'") +elif patch_no == 139: + from webnotes.modules import import_module + import_module.import_from_files(record_list=[['mapper','DocType Mapper','Sales Order-Receivable Voucher'], ['mapper','DocType Mapper','Delivery Note-Receivable Voucher']]) +elif patch_no == 140: + from webnotes.modules import import_module + import_module.import_from_files(record_list=[['accounts','doctype','rv_detail']]) +elif patch_no == 141: + sql("delete from tabDocField where (fieldname = 'letter_head' or label = 'Letter Head') and parent = 'Company'") +elif patch_no == 142: + # fixes to letter head and personalize + from webnotes.model import delete_doc + + delete_doc('DocType', 'Batch Settings') + delete_doc('DocType', 'Batch Settings Detail') + delete_doc('DocType', 'Social Badge') + delete_doc('Page', 'Personalize Page') + delete_doc('DocType', 'Personalize Page Control') + + import_from_files(record_list=[['core','doctype','letter_head'], ['setup','doctype','personalize']]) +elif patch_no == 144: + webnotes.conn.sql("update tabDocField set fieldtype='Code' where parent='Letter Head' and fieldname='content'") +elif patch_no == 145: + sql("update `tabDocField` set permlevel=1 where fieldname = 'group_or_ledger' and parent = 'Account'") +elif patch_no == 146: + import_from_files(record_list=[['accounts','doctype','account']]) +elif patch_no == 147: + import_from_files(record_list=[['mapper', 'DocType Mapper', 'Purchase Order-Payable Voucher'], ['mapper', 'DocType Mapper', 'Purchase Receipt-Payable Voucher'], ['mapper', 'DocType Mapper', 'Purchase Order-Purchase Receipt']]) +elif patch_no == 148: + sql("delete from `tabDocField` where (fieldname = 'account_balances' or label = 'Balances') and parent = 'Account'") + sql("update tabDocType set istable = 0, section_style = 'Simple', search_fields = 'account, period, fiscal_year, balance' where name = 'Account Balance'") + sql("update tabDocField set permlevel = 0 where parent = 'Account Balance'") + p = get_obj('Patch Util') + p.add_permission('Account Balance', 'Accounts User', 0, read = 1) + p.add_permission('Account Balance', 'Accounts Manager', 0, read = 1) + import_from_files(record_list=[['accounts','doctype','account_balance']]) +elif patch_no == 149: + sql("update `tabAccount Balance` set account = parent") +elif patch_no == 150: + sql("update tabDocField set in_filter = 1, search_index = 1 where parent = 'Account Balance' and fieldname in ('account', 'period', 'fiscal_year', 'start_date', 'end_date')") + ac_bal = Document("DocType", "Account Balance") + ac_bal.save() +elif patch_no == 151: + sql("delete from tabDocField where label = 'Add / Manage Contacts' and fieldtype = 'Button' and parent = 'Customer'") + sql("delete from `tabField Mapper Detail` where parent = 'Sales Order-Delivery Note' and from_field = 'note' and to_field = 'note'") +elif patch_no == 152: + import_from_files(record_list=[['selling','doctype','sales_order'], ['stock','doctype','delivery_note'], ['selling','doctype','customer'], ['selling','doctype','shipping_address'], ['mapper', 'DocType Mapper', 'Sales Order-Delivery Note']]) +elif patch_no == 153: + sql("delete from `tabDocField` where fieldname = 'sales_person' and parent = 'Customer'") +elif patch_no == 154: + import_from_files(record_list=[['stock','doctype','serial_no'], ['support','doctype','customer_issue']]) +elif patch_no == 155: + for d in sql("select name, item_code from `tabSerial No`"): + sql("COMMIT") + sql("START TRANSACTION") + sql("update `tabSerial No` set item_name = '%s' where name = '%s'" % (webnotes.conn.get_value('Item',cstr(d[1]),'item_name'), cstr(d[0]))) + sql("COMMIT") +elif patch_no == 156: + sql("update tabDocField set fieldtype = 'Code' where fieldname = 'html' and parent = 'Print Format'") +elif patch_no == 157: + import_from_files(record_list=[['accounts', 'doctype', 'journal_voucher'], ['accounts', 'Print Format', 'Payment Receipt Voucher'], ['accounts', 'Print Format', 'Cheque Printing Format']]) +elif patch_no == 158: + from webnotes.model.doc import addchild + sql("delete from tabDocField where parent = 'Customer Issue' and fieldname = 'customer_group'") +elif patch_no == 159: + sql("update tabAccount set account_type = 'Chargeable' where account_name in ('Advertising and Publicity', 'Freight & Forwarding Charges', 'Miscellaneous Expenses', 'Sales Promotion Expenses')") +elif patch_no == 160: + sql("update `tabDocType` set search_fields = 'posting_date, due_date, debit_to, fiscal_year, grand_total, outstanding_amount' where name = 'Receivable Voucher'") + sql("update `tabDocType` set search_fields = 'posting_date, credit_to, fiscal_year, bill_no, grand_total, outstanding_amount' where name = 'Payable Voucher'") +elif patch_no == 161: + sql("update tabDocType set autoname = 'field:batch_id' where name = 'Batch'") + sql("update tabDocField set no_copy = 1 where parent = 'Batch' and fieldname = 'batch_id'") +elif patch_no == 162: + import_from_files(record_list=[['selling', 'search_criteria', 'sales_order_pending_items1']]) +elif patch_no == 163: + sql("delete from `tabModule Def Item` where display_name = 'Sales Orderwise Pending Packing Item Summary' and parent = 'CRM'") + import_from_files(record_list=[['selling', 'search_criteria', 'sales_orderwise_pending_qty_to_deliver'], ['selling', 'search_criteria', 'sales_orderwise_pending_amount_to_bill'], ['selling', 'search_criteria', 'delivered_items_to_be_install']]) +elif patch_no == 164: + import_from_files(record_list=[['buying', 'search_criteria', 'pending_po_items_to_receive'], ['buying', 'search_criteria', 'pending_po_items_to_bill']]) +elif patch_no == 165: + pass +elif patch_no == 166: + import_from_files(record_list=[['buying', 'doctype', 'purchase_order']]) +elif patch_no == 167: + if webnotes.conn.get_value('Control Panel', None, 'account_id') not in ['ax0000956', 'ax0001338']: + sql("delete from tabDocField where parent = 'Purchase Order' and fieldname in ('test_certificate_required', 'estimated_cost', 'transport', 'vendor_reference', 'transportation_required', 'mode_of_dispatch', 'octroi')") +elif patch_no == 168: + sql("update tabDocField set fieldtype = 'Data', options = 'Suggest' where fieldname = 'bank_name' and parent = 'Employee'") +elif patch_no == 169: + import_from_files(record_list=[['accounts', 'doctype', 'pv_detail'], ['accounts', 'doctype', 'rv_detail']]) +elif patch_no == 170: + import_from_files(record_list=[['mapper', 'DocType Mapper', 'Delivery Note-Receivable Voucher']]) +elif patch_no == 171: + import_from_files(record_list=[['buying', 'doctype', 'supplier']]) +elif patch_no == 172: + import webnotes + webnotes.conn.set_global("system_message", """Welcome to the new financial year 2011-2012 !!!

So obvious question in your mind is how to start Entries in the New Fiscal Year in ERPNext? What are the changes you have to make in the system?
We have made some guidelines regarding the basic steps you should follow. Please click on link How to start Entries in the New Fiscal Year in ERPNext?""") + webnotes.conn.set_global("system_message_id", "6") +elif patch_no == 173: + sql("delete from tabDocField where label = 'Get Other Charges' and parent = 'Delivery Note'") + sql("update tabDocField set reqd = 0 where fieldname = 'posting_time' and parent = 'Serial No'") +elif patch_no == 174: + c = sql("select count(name) from `tabField Mapper Detail` where parent = 'Delivery Note-Receivable Voucher' and from_field = 'description' and to_field = 'description' and match_id = 2") + if c and cint(c[0][0]) > 1: + sql("update `tabField Mapper Detail` set match_id = 1 where parent = 'Delivery Note-Receivable Voucher' and from_field = 'description' and to_field = 'description' limit 1") +elif patch_no == 175: + import webnotes + webnotes.conn.set_global("system_message", """If your financial year starts on 1st April then you have make some changes in the system to start entry in the new year.
We have made some guidelines regarding the basic steps you should follow. Please click on link How to start Entries in the New Fiscal Year in ERPNext?""") + webnotes.conn.set_global("system_message_id", "6") +elif patch_no == 176: + sql("update tabDocPerm set role='Guest', `write`=0, `create`=0 where role='Administrator' and parent='Notification Control' limit 1") +elif patch_no == 177: + sql("delete from `tabDocField` where label = 'Next Steps' and parent = 'Purchase Order'") + sql("update tabDocField set options = 'Material Issue\nMaterial Receipt\nMaterial Transfer\nSales Return\nPurchase Return\nSubcontracting\nProduction Order' where parent = 'Stock Entry' and fieldname = 'purpose'") +elif patch_no == 178: + import_from_files(record_list = [['hr', 'doctype', 'salary_slip']]) +elif patch_no == 179: + from webnotes.utils import get_defaults + sl = sql("select name, net_pay from `tabSalary Slip`") + for d in sl: + in_words = get_obj('Sales Common').get_total_in_words(get_defaults()['currency'], round(flt(d[1]))) + sql("update `tabSalary Slip` set rounded_total = '%s', total_in_words = '%s' where name = '%s'" % (round(flt(d[1])), in_words, d[0])) +elif patch_no == 180: + sql("delete from tabDocField where parent = 'Salary Slip' and fieldname = 'net_pay_in_words'") +elif patch_no == 181: + import_from_files(record_list = [['accounts', 'doctype', 'journal_voucher']]) +elif patch_no == 182: + sql("update tabDocField set options = CONCAT(options, '\nWrite Off Voucher') where fieldname = 'voucher_type' and parent = 'Journal Voucher'") +elif patch_no == 183: + sql("delete from tabDocField where label = 'SMS' and fieldtype = 'Section Break' and parent in ('Enquiry', 'Lead', 'Sales Order', 'Delivery Note')") +elif patch_no == 184: + from webnotes.model import delete_doc + delete_doc('DocType', 'Feed') + delete_doc('DocType', 'Feed List') + delete_doc('DocType', 'Feed Control') + + # add trigger + from webnotes.model.triggers import add_trigger + add_trigger('*','*','*','event_updates.update_feed') + + webnotes.conn.commit() + + try: + sql("drop table tabFeed") + sql("drop table `tabFeed List`") + except: pass + + # import + from webnotes.modules.module_manager import reload_doc + reload_doc('event_updates','doctype','feed') +elif patch_no==185: + sql("delete from tabDocTrigger where method = 'webnotes.widgets.follow.on_docsave'") +elif patch_no==186: + from webnotes.modules.module_manager import reload_doc + reload_doc('event_updates','doctype','feed') +elif patch_no == 187: + sql("update tabDocType set autoname = '' where name = 'QA Inspection Report'") +elif patch_no == 188: + import_from_files(record_list = [['buying', 'doctype', 'qa_inspection_report']]) +elif patch_no == 189: + sql("update `tabDocField` set allow_on_submit = 1 where fieldname in ('entries', 'other_charges') and parent = 'Receivable Voucher'") +elif patch_no == 190: + sql("update tabDocField set permlevel=0 where fieldname = 'fiscal_year' and parent = 'Stock Entry'") +elif patch_no == 191: + import_from_files(record_list = [['support', 'doctype', 'customer_issue']]) +elif patch_no == 192: + sql("delete from `tabModule Def Item` where parent = 'Material Management' and doc_name = 'Landed Cost Wizard' and display_name = 'Landed Cost Wizard'") + import_from_files(record_list = [['buying', 'Module Def', 'SRM']]) +elif patch_no == 193: + sql("update tabDocField set fieldtype='Button', `trigger`='Client' where parent='Letter Head' and fieldname='set_from_image'") +elif patch_no == 194: + sql("delete from `tabModule Def Item` where parent = 'SRM' and doc_name = 'Landed Cost Wizard' and display_name = 'Landed Cost Wizard'") + import_from_files(record_list = [['stock', 'Module Def', 'Material Management']]) +elif patch_no == 195: + from webnotes.modules.module_manager import reload_doc + reload_doc('setup','doctype','manage_account') +elif patch_no == 196: + sql("update `tabModule Def` set module_page = null where name = 'Material Management'") +elif patch_no == 197: + sql("update `tabDocField` set permlevel = 0, in_filter = 1 where fieldname = 'warranty_amc_status' and parent = 'Customer Issue'") + import_from_files(record_list = [['support', 'doctype', 'customer_issue']]) +elif patch_no == 198: + sql("delete from `tabDocField` where (label in ('SMS', 'Send SMS') or fieldname in ('message', 'customer_mobile_no')) and parent in ('Quoattion', 'Sales Order', 'Delivery Note', 'Receivable Voucher')") + sql("delete from `tabDocField` where label in ('SMS', 'Send SMS') and parent = 'Purchase Order'") + sql("delete from `tabDocField` where (label in ('Send SMS', 'SMS Html') or fieldname in ('sms_message', 'lead_sms_detail', 'enquiry_sms_detail')) and parent in ('Lead', 'Enquiry')") + from webnotes.model import delete_doc + delete_doc('DocType', 'Lead SMS Detail') + delete_doc('DocType', 'Enquiry SMS Detail') +elif patch_no == 199: + sql("update tabDocField set reqd = 0 where parent = 'Attendance' and fieldname = 'shifts'") +elif patch_no == 200: + reload_doc('event_updates','page','profile_settings') +elif patch_no == 201: + reload_doc('setup','doctype','price_list') +elif patch_no == 202: + name1 = sql("select name from tabDocField where parent='Price List' and label='Clear Prices' limit 1,1") + name2 = sql("select name from tabDocField where parent='Price List' and label='Update Prices' limit 1,1") + if name1: + sql("delete from tabDocField where name=%s limit 1", name1[0][0]) + if name2: + sql("delete from tabDocField where name=%s limit 1", name2[0][0]) +elif patch_no == 203: + sql("delete from tabDocField where parent = 'Company' and fieldname = 'default_salary_account' limit 1") +elif patch_no == 204: + sql("delete from tabDocField where parent = 'Company' and fieldname = 'default_salary_acount' limit 1") +elif patch_no == 205: + sql("update `tabDocField` set `default` = '' where fieldname = 'naming_series' and parent = 'Installation Note'") +elif patch_no == 206: + reload_doc('selling','doctype','installation_note') +elif patch_no == 207: + import_from_files(record_list = [['setup', 'doctype', 'company']]) +elif patch_no == 208: + sql("delete from `tabDocField` where (label in ('SMS', 'Send SMS') or fieldname in ('message', 'customer_mobile_no')) and parent ='Quotation'") + default_currency = get_obj('Manage Account').doc.default_currency + sql("update tabCompany set default_currency = '%s'" % default_currency) +elif patch_no == 209: + import_from_files(record_list = [['setup', 'doctype', 'company']]) +elif patch_no == 210: + sql("delete FROM `tabDocField` WHERE parent = 'Lead' AND label in ('CC:','Attachment Html','Create New File','Attachment')") +elif patch_no == 212: + # reload company because of disturbed UI + import_from_files(record_list = [['setup', 'doctype', 'company']]) +elif patch_no == 213: + reload_doc('selling','doctype','lead') + reload_doc('setup','doctype','company') +elif patch_no == 214: + reload_doc('selling','doctype','sales_order') +elif patch_no == 215: + # patch for item and image in description + sql("update tabDocField set width = '300px' where fieldname='description'") + reload_doc('stock', 'doctype', 'item') + sql("delete from __DocTypeCache") +elif patch_no == 216: + import_from_files(record_list = [['stock', 'doctype', 'serial_no'], ['stock', 'doctype', 'stock_ledger_entry']]) +elif patch_no == 217: + sql("update tabDocField set options = '\nIn Store\nDelivered\nNot in Use' where fieldname = 'status' and parent = 'Serial No'") + sql("update tabDocField set no_copy = 1 where fieldname = 'serial_no' and parent = 'Delivery Note Detail'") + sql("update tabDocField set no_copy = 1 where fieldname = 'serial_no' and parent = 'Stock Entry Detail'") +elif patch_no == 218: + for d in sql("select name from `tabSerial No`"): + sql("Commit") + sql("Start Transaction") + s = Document('Serial No', d[0]) + if s.pr_no: + s.purchase_document_type = 'Purchase Receipt' + s.purchase_document_no = s.pr_no + if s.delivery_note_no: + s.delivery_document_type = 'Delivery Note' + s.delivery_document_no = s.delivery_note_no + if s.notes: + s.delivery_note_no = s.notes + s.company = webnotes.utils.get_defaults()['company'] + s.fiscal_year = webnotes.utils.get_defaults()['fiscal_year'] + s.save() +elif patch_no == 219: + sql("delete from tabDocField where fieldname in ('pr_no', 'make', 'label', 'delivery_note_no', 'notes') and parent = 'Serial No'") +elif patch_no == 220: + sql("update tabDocField set label = 'Incoming Rate' where fieldname = 'purchase_rate' and parent = 'Serial No'") + sql("update tabDocField set label = 'Incoming Time' where fieldname = 'purchase_time' and parent = 'Serial No'") +elif patch_no == 221: + sql("update tabDocField set reqd = 1 where fieldname in ('purchase_rate', 'warehouse') and parent = 'Serial No'") +elif patch_no == 222: + sql("update tabDocField set options = '\nDelivery Note\nReceivable Voucher\nStock Entry' where fieldname = 'delivery_document_type' and parent = 'Serial No'") +elif patch_no == 223: + sql("update tabDocField set hidden = 0 where fieldname in ('pay_to_recd_from', 'total_amount', 'total_amount_in_words') and parent = 'Journal Voucher'") + sql("update tabDocField set permlevel = 0 where fieldname = 'pay_to_recd_from' and parent = 'Journal Voucher'") +elif patch_no == 224: + import_from_files(record_list = [['stock', 'doctype', 'delivery_note_packing_detail'], ['accounts', 'Print Format', 'Payment Receipt Voucher']]) +elif patch_no == 225: + import_from_files(record_list = [['stock', 'doctype', 'delivery_note_packing_detail']]) +elif patch_no == 226: + import_from_files(record_list = [['stock', 'doctype', 'delivery_note_packing_detail']]) +elif patch_no == 227: + reload_doc('stock', 'doctype', 'item') + if webnotes.conn.get_value('Control Panel', None, 'account_id') != 'axjanak2011': + sql("delete from tabDocField where parent = 'Item' and fieldname='alternate_description' limit 1") +elif patch_no == 228: + # knowledge base patch + reload_doc('knowledge_base', 'doctype', 'question') + reload_doc('knowledge_base', 'doctype', 'answer') + reload_doc('knowledge_base', 'page', 'questions') + reload_doc('knowledge_base', 'Module Def', 'Knowledge Base') + sql("update `tabModule Def` set disabled='No' where name='Knowledge Base'") +elif patch_no == 229: + reload_doc('knowledge_base', 'page', 'question_view') +elif patch_no == 230: + reload_doc('buying', 'doctype', 'indent') + reload_doc('buying', 'doctype', 'indent_detail') + reload_doc('Mapper', 'DocType Mapper', 'Sales Order-Indent') +elif patch_no == 231: + reload_doc('Mapper', 'DocType Mapper', 'Sales Order-Indent') +elif patch_no == 232: + sql("update `tabDocField` set options = 'Sales Order' where fieldname = 'sales_order_no' and parent = 'Indent'") +elif patch_no == 233: + reload_doc('Mapper', 'DocType Mapper', 'Sales Order-Receivable Voucher') + reload_doc('Mapper', 'DocType Mapper', 'Delivery Note-Receivable Voucher') +elif patch_no == 234: + sql("update `tabTable Mapper Detail` set validation_logic = 'docstatus=1' where parent = 'Sales Order-Indent' and from_table = 'Sales Order Detail'") +elif patch_no == 235: + for sc in sql("""select name from `tabSearch Criteria` where ifnull(name,'') + like 'srch%' or ifnull(name,'') like '%stdsrch'"""): + try: + get_obj('Search Criteria', sc[0]).rename() + except AttributeError, e: + pass + reload_doc('core', 'doctype', 'system_console') +elif patch_no == 236: + # warehouse not mandatory for delivered serial nos + sql("update tabDocField set reqd=0 where parent='Serial No' and fieldname='warehouse'") +elif patch_no == 237: + sql("update tabDocField set depends_on = 'eval:doc.is_pos==1' where fieldname = 'cash_bank_account' and parent = 'Receivable Voucher'") +elif patch_no == 238: + reload_doc('accounts', 'doctype', 'receivable_voucher') + reload_doc('accounts', 'GL Mapper', 'POS with write off') +elif patch_no == 239: + reload_doc('core', 'doctype', 'docfield') + reload_doc('core', 'doctype', 'doctype') + from patches.old_patches.feed_patch import set_subjects_and_tagfields + + set_subjects_and_tagfields() +elif patch_no == 240: + # again for sales order (status) + from patches.old_patches.feed_patch import set_subjects_and_tagfields + set_subjects_and_tagfields() +elif patch_no == 241: + sql("update `tabDocField` set fieldtype = 'Text', options = '', in_filter = '' where fieldname = 'serial_no' and parent = 'Stock Ledger Entry'") +elif patch_no == 242: + if webnotes.conn.get_value('Control Panel', None, 'account_id') not in ['axjanak2011']: + sql("commit") + try: + sql("alter table `tabStock Ledger Entry` drop index serial_no") + except: + pass + + sql("alter table `tabStock Ledger Entry` change serial_no serial_no text") +elif patch_no == 243: + # moving custom script and custom fields to framework + webnotes.conn.set_value('DocType', 'Custom Script', 'module', 'Core') + webnotes.conn.set_value('DocType', 'Custom Field', 'module', 'Core') + reload_doc('setup', 'doctype', 'company') +elif patch_no == 244: + reload_doc('stock', 'search_criteria', 'shortage_to_indent') +elif patch_no == 245: + from patches.old_patches.doctype_permission_patch import set_doctype_permissions + set_doctype_permissions() + + from patches.old_patches.feed_patch import set_subjects_and_tagfields + set_subjects_and_tagfields() +elif patch_no == 246: + webnotes.conn.set_value('DocType','Stock Entry','tag_fields','purpose') + webnotes.conn.set_value('DocType','Stock Entry','subject','%(remarks)s') +elif patch_no == 247: + webnotes.conn.set_value('DocType','Stock Entry','subject','%(remarks)s') +elif patch_no == 248: + reload_doc('setup', 'doctype', 'manage_account') +elif patch_no == 249: + sql("update `tabDocPerm` t1, `tabDocType` t2 set t1.role = 'System Manager' where t1.role = 'Administrator' and t1.parent = t2.name and t2.module != 'Core'") +elif patch_no == 250: + from patches.old_patches.feed_patch import support_patch + support_patch() +elif patch_no == 251: + from webnotes.model import db_schema + db_schema.remove_all_foreign_keys() + from patches.old_patches.customer_address import run_patch + run_patch() +elif patch_no == 252: + reload_doc('support','doctype','support_ticket') + reload_doc('support','doctype','support_ticket_response') +elif patch_no == 253: + reload_doc('accounts','doctype','ledger_balance_export') + reload_doc('accounts','doctype','ledger_detail') + reload_doc('accounts', 'Module Def', 'Accounts') + + from webnotes.model.db_schema import updatedb + updatedb('Ledger Balance Export') + updatedb('Ledger Detail') +elif patch_no == 254: + reload_doc('setup', 'doctype', 'sms_settings') + reload_doc('setup', 'doctype', 'static_parameter_detail') + + from webnotes.model.db_schema import updatedb + updatedb('SMS Settings') + updatedb('Static Parameter Detail') +elif patch_no == 255: + from patches.old_patches.customer_address import run_old_data_sync_patch + run_old_data_sync_patch() +elif patch_no == 256: + sql("update `tabLetter Head` set content = replace(content, 'http://46.4.50.84/v170-test/', '')") + sql("update `tabSingles` set value = replace(value, 'http://46.4.50.84/v170-test/', '') where field in ('letter_head', 'client_name') and doctype = 'Control Panel'") + sql("update `tabItem` set description_html = replace(description_html, 'http://46.4.50.84/v170-test/', '')") +elif patch_no == 257: + from patches.old_patches.customer_address import run_old_data_sync_patch + run_old_data_sync_patch() +elif patch_no == 258: + sql("update tabDocField set `default`=NULL where fieldname = 'naming_series'") +elif patch_no == 259: + sql("update `tabQuotation Detail` set description = replace(description, 'http://46.4.50.84/v170-test/', '')") + sql("update `tabSales Order Detail` set description = replace(description, 'http://46.4.50.84/v170-test/', '')") + sql("update `tabRV Detail` set description = replace(description, 'http://46.4.50.84/v170-test/', '')") + sql("update `tabDelivery Note Detail` set description = replace(description, 'http://46.4.50.84/v170-test/', '')") +elif patch_no == 260: + sql("update `tabLetter Head` set content = replace(content, 'http://46.4.50.84/v170/', '')") + sql("update `tabSingles` set value = replace(value, 'http://46.4.50.84/v170/', '') where field in ('letter_head', 'client_name') and doctype = 'Control Panel'") + sql("update `tabItem` set description_html = replace(description_html, 'http://46.4.50.84/v170/', '')") + sql("update `tabQuotation Detail` set description = replace(description, 'http://46.4.50.84/v170/', '')") + sql("update `tabSales Order Detail` set description = replace(description, 'http://46.4.50.84/v170/', '')") + sql("update `tabRV Detail` set description = replace(description, 'http://46.4.50.84/v170/', '')") + sql("update `tabDelivery Note Detail` set description = replace(description, 'http://46.4.50.84/v170/', '')") +elif patch_no == 261: + sql("update `tabPrint Format` set html = replace(html, 'customer_address', 'address_display')") +elif patch_no == 262: + from patches.old_patches.customer_address import sync_lead_phone + sync_lead_phone() +elif patch_no == 263: + ol = ['','Open','To Reply','Waiting for Customer','Hold','Closed'] + sql("update tabDocField set options=%s where parent=%s and fieldname=%s", ('\n'.join(ol), 'Support Ticket', 'status')) +elif patch_no == 264: + sql("delete from tabDocField where parent = 'Customer Issue' and (fieldname = 'issue_in' or fieldname = 'issue_category')") + sql("update tabDocField set options=NULL where parent='Support Ticket' and label = 'Send'") +elif patch_no == 266: + reload_doc('setup','doctype','support_email_settings') +elif patch_no == 267: + sql("update `tabPrint Format` set html = replace(html, 'supplier_address', 'address_display')") +elif patch_no == 268: + sql("update `tabDocPerm` set permlevel = 0 where permlevel is null") +elif patch_no == 269: + p = get_obj('Patch Util') + p.add_permission('GL Entry', 'Accounts User', 0, read = 1) +elif patch_no == 270: + pages = ['Accounts Setup', 'Accounts', 'Accounting Reports','GeneralLedger','How do I - Accounts','Making Opening Entries',\ + 'Analysis','How do I - CRM','How do I - Inventory','Inventory Setup', 'Stock','HR','HR & Payroll Setup',\ + 'Payroll Setup','Production Setup','Production','Buying','SRM Setup','Contact Page','Forum','Messages','Test Toolbar',\ + 'Trend Analyzer'] + from webnotes.model import delete_doc + sql("delete from `tabPage Visit`") + for p in pages: + try: delete_doc('Page', p) + except: pass +elif patch_no == 271: + # tags patch + reload_doc('selling','doctype','sales_order') + reload_doc('stock','doctype','delivery_note') + sql("delete from tabDocField where fieldname='per_amt_billed' and parent in ('Sales Order', 'Delivery Note')") + + sql("""update `tabSales Order` set delivery_status = if(ifnull(per_delivered,0) < 0.001, 'Not Delivered', + if(per_delivered >= 99.99, 'Fully Delivered', 'Partly Delivered'))""") + sql("""update `tabSales Order` set billing_status = if(ifnull(per_billed,0) < 0.001, 'Not Billed', + if(per_billed >= 99.99, 'Fully Billed', 'Partly Billed'))""") + sql("""update `tabDelivery Note` set billing_status = if(ifnull(per_billed,0) < 0.001, 'Not Billed', + if(per_billed >= 99.99, 'Fully Billed', 'Partly Billed'))""") +elif patch_no == 272: + from webnotes.model import delete_doc + try: + delete_doc('Search Criteria', '_SRCH00003') + except: + pass + reload_doc('accounts', 'search_criteria', 'purchase_register') +elif patch_no == 276: + from webnotes.model import delete_doc + sn = sql("select name from `tabSearch Criteria` where criteria_name = 'Sales Personwise Transaction Summary'") + for d in sn: + delete_doc('Search Criteria', d[0]) + reload_doc('selling', 'search_criteria', 'sales_personwise_transaction_summary') +elif patch_no == 277: + webnotes.model.delete_doc('DocType','HomePage Settings') + webnotes.model.delete_doc('DocType','Badge Settings') + sql("update tabDocType set module='Home' where module in ('Event Updates', 'My Company')") + sql("update tabPage set module='Home' where module in ('Event Updates', 'My Company')") + sql("update `tabSearch Criteria` set module='Home' where module in ('Event Updates', 'My Company')") + + + delete_pages = ('Chat User Gallery', 'Badge Info', 'Home', 'Website Setup', 'Test Page', 'Setup Masters', 'Service', 'Selling', 'Sales Reports', 'Organize','My Cart', 'My Activity', 'Manage Users', 'Maintenance', 'Getting Started', 'Gantt Test', 'Custom Reports - Stock', 'Custom Reports - Selling', 'Custom Reports - Production', 'Custom Reports - Payroll', 'Custom Reports - Maintenance', 'Custom Reports - Buying', 'Custom Reports - Accounts', 'CRM Setup', 'CRM Reports') + for p in delete_pages: + webnotes.model.delete_doc('Page',p) +elif patch_no == 278: + sql("update tabDocTrigger set method = 'home.update_feed' where method = 'event_updates.update_feed'") +elif patch_no == 279: + dt = ['GL Entry', 'Stock Ledger Entry'] + for t in dt: + rec = sql("select voucher_type, voucher_no, ifnull(is_cancelled, 'No') from `tab%s` where modified >= '2011-06-15 01:00:00' group by voucher_no" % t) + for d in rec: + sql("update `tab%s` set docstatus = %s where name = '%s'" % (d[0], d[2]=='No' and 1 or 2, d[1])) + + other_dt = ['Enquiry', 'Quotation', 'Sales Order', 'Indent', 'Purchase Order', 'Production Order', 'Customer Issue', 'Installation Note'] + for dt in other_dt: + rec = sql("select name, status from `tab%s` where modified >= '2011-06-15 01:00:00'" % dt) + for r in rec: + sql("update `tab%s` set docstatus = %s where name = '%s'" % (dt, (r[1] in ['Submitted', 'Closed'] and 1 or r[1]=='Cancelled' and 2 or 0), r[0])) +elif patch_no == 280: + reload_doc('accounts', 'doctype', 'form_16a') +elif patch_no == 281: + dt_list = ['Delivery Note', 'Purchase Receipt'] + for dt in dt_list: + sql("update `tab%s` set status = 'Submitted' where docstatus = 1 and modified >='2011-06-15 01:00:00'" % dt) + sql("update `tab%s` set status = 'Cancelled' where docstatus = 2 and modified >='2011-06-15 01:00:00'" % dt) +elif patch_no == 282: + dt_list = ['Enquiry', 'Quotation', 'Sales Order', 'Indent', 'Purchase Order', 'Production Order', 'Customer Issue', 'Installation Note', 'Receivable Voucher', 'Payable Voucher', 'Delivery Note', 'Purchase Receipt', 'Journal Voucher', 'Stock Entry'] + for d in dt_list: + tbl = sql("select options from `tabDocField` where fieldtype = 'Table' and parent = '%s'" % d) + for t in tbl: + sql("update `tab%s` t1, `tab%s` t2 set t1.docstatus = t2.docstatus where t1.parent = t2.name" % (t[0], d)) +elif patch_no == 283: + rec = sql("select voucher_type, voucher_no, ifnull(is_cancelled, 'No') from `tabGL Entry` where modified >= '2011-06-15 01:00:00' order by name ASC") + for d in rec: + sql("update `tab%s` set docstatus = %s where name = '%s'" % (d[0], d[2]=='No' and 1 or 2, d[1])) +elif patch_no == 284: + reload_doc('support', 'doctype', 'support_ticket') + sql("update `tabDocField` set in_filter = 1 where fieldname in ('raised_by', 'subject') and parent = 'Support Ticket'") +elif patch_no == 286: + reload_doc('accounts', 'search_criteria', 'itemwise_sales_register') + reload_doc('accounts', 'search_criteria', 'itemwise_purchase_register') +elif patch_no == 287: + sql("update `tabDocField` set no_copy = 1 where fieldname in ('per_received', 'per_billed', 'per_delivered') and parent in ('Purchase Order', 'Purchase Receipt', 'Sales Order', 'Delivery Note')") +elif patch_no == 288: + reload_doc('accounts', 'doctype', 'payable_voucher') +elif patch_no == 289: + sql("update `tabDocType` set subject = 'From %(supplier_name)s worth %(grand_total)s due on %(due_date)s | %(outstanding_amount)s outstanding' where name = 'Payable Voucher'") + sql("update `tabDocType` set search_fields = 'status,transaction_date,customer,lead,order_type' where name = 'Quotation'") +elif patch_no == 290: + count = sql("""SELECT * FROM `tabModule Def` + WHERE `module_name` LIKE 'Home'""") + if not count: + md = Document('Module Def') + md.module_name = 'Home' + md.module_label = 'Home' + md.save(1) +elif patch_no == 291: + reload_doc('utilities','doctype','rename_tool') +elif patch_no == 292: + reload_doc('accounts', 'search_criteria', 'trial_balance') +elif patch_no == 293: + sql("delete from tabDocField where parent='Account' and fieldname='address'") + reload_doc('accounts', 'doctype', 'account') +elif patch_no == 294: + # new account profile fix + ul = sql("select name from tabProfile where ifnull(name,'') not in ('Administrator', 'Guest', '')") + # if one user and one user has no roles + if len(ul)==1 and not sql("select parent from tabUserRole where role='System Manager' and parent=%s", ul[0][0]): + get_obj('Setup Control').add_roles(Document('Profile', ul[0][0])) +elif patch_no == 295: + sql("update `tabDocField` set options = 'Delivered\nNot Delivered\nPartly Delivered\nClosed\nNot Applicable' where parent = 'Sales Order' and fieldname = 'delivery_status'") + sql("update `tabDocField` set options = 'Billed\nNot Billed\nPartly Billed\nClosed' where parent = 'Sales Order' and fieldname = 'billing_status'") +elif patch_no == 296: + sql("delete from tabDocField where parent='Support Ticket' and fieldname='contact_no'") + reload_doc('support', 'doctype', 'support_ticket') +elif patch_no == 297: + reload_doc('hr', 'doctype', 'employee') + reload_doc('hr', 'doctype', 'attendance') + reload_doc('hr', 'doctype', 'expense_voucher') + reload_doc('hr', 'doctype', 'appraisal') + reload_doc('hr', 'doctype', 'salary_structure') + reload_doc('hr', 'doctype', 'salary_slip') +elif patch_no == 298: + sql("update `tabDocField` set options = 'link:Company' where parent = 'Attendance' and fieldname = 'company'") + sql("update `tabDocField` set options = 'link:Company' where parent = 'Expense Voucher' and fieldname = 'company'") + sql("update `tabDocField` set options = 'link:Company' where parent = 'Appraisal' and fieldname = 'company'") +elif patch_no == 299: + sql("update `tabDocPerm` set `match` = NULL where parent = 'Employee' and role = 'Employee'") +elif patch_no == 300: + sql("""DELETE FROM `tabSearch Criteria` WHERE name IN + ('sales_register1', 'sales_register2', 'purchase_register1')""") \ No newline at end of file diff --git a/patches/patch.py b/patches/patch.py index 13da883f313..616be63f767 100644 --- a/patches/patch.py +++ b/patches/patch.py @@ -1,8 +1,7 @@ # REMEMBER to update this # ======================== -last_patch = 332 - +last_patch = 346 #------------------------------------------- def execute(patch_no): @@ -13,1189 +12,9 @@ def execute(patch_no): sql = webnotes.conn.sql from webnotes.utils import cint, cstr, flt from webnotes.model.doc import Document + from webnotes.model import delete_doc - if patch_no==33: - pass - elif patch_no==34: - webnotes.conn.sql("update `tabDocField` set options = 'Letter Head', print_hide = 1 where fieldname = 'letter_head' and fieldtype = 'Link'") - elif patch_no==35: - webnotes.conn.sql("update tabDocType set module = 'Event Updates' where name = 'Feed Control'") - elif patch_no==36: - # remove delivery note foreign key in Serial Number - from webnotes.model.db_schema import DbTable - t = DbTable('Serial No') - fk_list = t.get_foreign_keys() - for f in fk_list: - if f[0]=='delivery_note_no': - webnotes.conn.commit() - webnotes.conn.sql("alter table `tabSerial No` drop foreign key `%s`" % f[1]) - webnotes.conn.begin() - webnotes.conn.sql("update tabDocField set fieldtype='Data' where fieldname='delivery_note_no' and parent='Serial No' limit 1") - elif patch_no==37: - import os - mod_path = webnotes.defs.modules_path - path_list = [] - for m in os.listdir(mod_path): - for t in ['doctype', 'page', 'search_criteria']: - dt_path = os.path.join(mod_path, m, t) - if os.path.exists(dt_path): - for dt in os.listdir(dt_path): - if '.' not in dt and os.path.exists(os.path.join(dt_path, dt, dt+ '.txt')): - path_list.append(os.path.join(dt_path, dt, dt+ '.txt')) - - for d in path_list: - doclist = eval(open(d,'r').read()) - webnotes.conn.sql("update `tab%s` set module = '%s' where name = '%s'" % (doclist[0]['doctype'], doclist[0]['module'], doclist[0]['name'])) - - elif patch_no==38: - import webnotes - webnotes.conn.set_global("system_message", "System Updates: Hello! You would have noticed some changes on the Home Page. As a part of our commitment to make the system more friendly and social, we have re-designed the feed so that now you will only see feed that is relevant to you (either you have created something or you have been mentioned in the document).

On the individual listings, you can add tags and also color them!

You will also get time-to-time updates from our side here. Do keep sending your feedback at support@erpnext.com.") - webnotes.conn.set_global("system_message_id", "1") - - elif patch_no == 39: - pass - - elif patch_no == 40: - - import_from_files(record_list=[['material_management','doctype','item']]) - elif patch_no == 42: - acc = sql("select name, lft, rgt from tabAccount where account_name in ('Incomes', 'Expenses')") - for d in acc: - sql("update tabAccount set is_pl_account = 'Yes' where lft >= '%s' and rgt <= '%s'" % (d[1], d[2])) - elif patch_no == 43: - import webnotes.model - webnotes.model.delete_doc('Page', 'Module Manager') - - # cleanup of Service, Customer Support, Utilities Modules - # ------------------------------------------------------- - elif patch_no == 44: - from webnotes.model import delete_doc - - for dt in sql("select name from tabDocType where module in ('Customer Support')"): - delete_doc('DocType', dt[0]) - - for dt in sql("select name from `tabSearch Criteria` where module in ('Customer Support')"): - delete_doc('Search Criteria', dt[0]) - - for dt in sql("select name from tabPage where module in ('Customer Support')"): - delete_doc('Page', dt[0]) - - # move a couple - webnotes.conn.sql("update `tab%s` set module=%s where name=%s" % ('DocType', '%s', '%s'), ('Application Internal', 'Patch Util')) - webnotes.conn.sql("update `tab%s` set module=%s where name=%s" % ('DocType', '%s', '%s'), ('Application Internal', 'DocType Property Setter')) - - # remove utilities - webnotes.conn.sql('delete from `tabModule Def` where name in ("Customer Support", "Utilities")') - - elif patch_no == 45: - webnotes.conn.sql('delete from tabDocField where options="Ticket Response Detail"') - - elif patch_no == 46: - import webnotes - webnotes.conn.set_global("system_message", "SYSTEM DOWNTIME: Hello! As part of our commitment to keep improving the service, we are planning a scheduled maintenance on our servers for 4 hrs on 16-Jan-2011(Sunday), from 10AM to 2PM. Do keep sending your feedback at support@erpnext.com.") - webnotes.conn.set_global("system_message_id", "2") - - elif patch_no == 47: - import webnotes - webnotes.conn.set_global("system_message", "") - webnotes.conn.set_global("system_message_id", "3") - - elif patch_no == 48: - webnotes.conn.sql("update tabDocField set options = 'Print Heading' where fieldname = 'select_print_heading'") - - elif patch_no == 49: - webnotes.conn.sql("update tabDocType set autoname = '' where name = 'Search Criteria'") - elif patch_no == 50: - sql("update tabDocField set in_filter = 1 where fieldname in ('cost_center', 'income_account', 'Item Group') and parent = 'RV Detail'") - elif patch_no == 51: - sql("update tabDocField set options = 'link:Print Heading' where fieldtype = 'Select' and fieldname = 'select_print_heading' and parent = 'POS Setting'") - elif patch_no == 52: - sql("update tabDocField set print_hide = 1 where fieldname = 'letter_head'") - elif patch_no == 53: - sql("update tabDocType set search_fields = 'lead_name,lead_owner,status,contact_by,contact_date' where name = 'Lead'") - elif patch_no == 54: - sql("delete from tabDocField where parent = 'Supplier' and label = 'Supplier Contacts' and fieldtype = 'Section Break'") - elif patch_no == 55: - sql("commit") - try: - sql("alter table tabFeed add column `_user_tags` varchar(180)") - except Exception, e: - if e.args[0]!=1060: - raise e - elif patch_no == 56: - sql("delete from `tabModule Def Item` where parent = 'CRM' and doc_type = 'Reports' and doc_name = 'Delivery Note' and display_name = 'Territory, Item Group wise GP'") - elif patch_no == 57: - - import_from_files(record_list=[['crm','doctype','sales_order_detail']]) - elif patch_no == 58: - # module def patches - sql("update `tabModule Def` set module_page = NULL where name not in ('Event Updates', 'Setup', 'My Company')") - sql("delete from `tabModule Def Item` where doc_type in ('Separator', 'Setup Forms', 'More Reports')") - sql("delete from `tabModule Def Item` where doc_name = 'Project Activity'") - sql("update `tabModule Def` set module_label = 'People', disabled='No', is_hidden='No' where name = 'My Company'") - - # insert new module items - from webnotes.model.doc import make_autoname - if not sql("select name from `tabModule Def Item` where parent='Projects' and doc_name='Ticket'"): - sql("""insert into `tabModule Def Item` - (name, parent, parenttype, parentfield, docstatus, doc_type, doc_name, display_name, idx) values - (%s, 'Projects', 'Module Def', 'items', 0, 'Forms', 'Ticket', 'Task', 1)""", make_autoname('MDI.#####')) - - if not sql("select name from `tabModule Def Item` where parent='Projects' and doc_name='Timesheet'"): - sql("""insert into `tabModule Def Item` - (name, parent, parenttype, parentfield, docstatus, doc_type, doc_name, display_name, idx) values - (%s, 'Projects', 'Module Def', 'items', 0, 'Forms', 'Timesheet', 'Timesheet', 2)""", make_autoname('MDI.#####')) - - if not sql("select name from `tabModule Def Item` where parent='Projects' and doc_name='Projects'"): - sql("""insert into `tabModule Def Item` - (name, parent, parenttype, parentfield, docstatus, doc_type, doc_name, display_name, idx) values - (%s, 'Projects', 'Module Def', 'items', 0, 'Pages', 'Projects', 'Gantt Chart', 1)""", make_autoname('MDI.#####')) - - elif patch_no == 59: - webnotes.conn.set_value('Control Panel',None,'mail_footer','') - webnotes.conn.set_global('global_mail_footer','
Sent via ERPNext
') - elif patch_no == 60: - sql("delete from `tabModule Def Item` where display_name = 'Point of Sales'") - elif patch_no == 61: - sql("delete from `tabTDS Category Account` where company not in (select name from tabCompany)") - elif patch_no == 62: - # Import Supplier Quotation - - import_from_files(record_list=[['srm','doctype','supplier_quotation']]) - # Adding Status Filter - sql("update tabDocType set search_fields = concat('status,',search_fields) where name IN ('Delivery Note','Leave Transaction')") - # Import Other Charges - - import_from_files(record_list=[['setup','doctype','other_charges']]) - elif patch_no == 63: - sql("update `tabDocField` set permlevel = 1 where fieldname in ('return_date', 'return_details') and parent = 'Sales and Purchase Return Wizard'") - - import_from_files(record_list = [['accounts', 'doctype', 'rv_detail'], ['material_management', 'doctype', 'sales_and_purchase_return_wizard'], ['material_management', 'doctype', 'stock_entry']]) - elif patch_no == 64: - sql("update tabDocField set `hidden` = 1, `print_hide` = 1, `report_hide` = 1 where options in ('RFQ','Supplier Quotation')") - sql("update tabDocType set `read_only` = 1, in_create = 1 where name in ('RFQ','Supplier Quotation')") - sql("update tabDocField set `report_hide` = 0 where fieldname in ('email_id','phone_1','fax_1') and parent = 'Customer'") - elif patch_no == 65: - # Monthly Trend Analyzer <-> Trend Analyzer - sql("update `tabSearch Criteria` set criteria_name = 'Trend Analyzer' where criteria_name = 'Monthly Trend Analyzer' and name = 'SRCH/00159'") - sql("update `tabModule Def Item` set display_name = 'Trend Analyzer' where parent = 'Analysis' and display_name = 'Monthly Trend Analyzer'") - elif patch_no == 66: - import webnotes - webnotes.conn.set_global("system_message", """

UI Updates

Based on user feedback, we have made a couple of changes in the UI:
  • Sidebar menus are now collapsable
  • Forms are now scrollable (we removed the confusing tabs)
  • Feed is a lot more descriptive
Do send us your feedback!""") - webnotes.conn.set_global("system_message_id", "4") - - sql("update `tabModule Def Item` set doc_type = 'Setup Forms' where doc_name in ('TDS Payment', 'TDS Return Acknowledgement', 'Form 16A', 'Period Closing Voucher', 'IT Checklist')") - from webnotes.session_cache import clear_cache - clear_cache(webnotes.session['user']) - elif patch_no == 67: - sql("update `tabDocField` set in_filter = 1 where fieldname = 'brand' and parent = 'RV Detail'") - sql("delete from `tabModule Def Item` where (display_name = 'Sales Invoice' and parent = 'CRM') or (display_name = 'Purchase Invoice' and parent = 'SRM')") - elif patch_no == 68: - from webnotes.modules.import_module import import_from_files - import_from_files(record_list=[['payroll','doctype','employee'],['roles','Role','Employee']]) - elif patch_no == 69: - # delete flds from employee master - p = get_obj('Patch Util') - emp_del_flds = ['month_of_birth'] - for f in emp_del_flds: - p.delete_field('Employee', f) - - sql("Update tabDocField set `default` = 'Active' where fieldname = 'status' and parent = 'Employee'") - - # map parent flds - fld_map = ['cell_number', 'personal_email', 'person_to_be_contacted', 'relation', 'emergency_phone_number', 'pan_number', 'passport_number', 'date_of_issue', 'valid_upto', 'place_of_issue', 'marital_status', 'blood_group', 'permanent_accommodation_type'] - - emp_prof = sql("select t1.name, t1.employee, t1.permanent_address_line_1, t1.permanent_address_line_2, t1.city1, t1.state1, t1.country1, t1.pin_code1, t1.phn_no1, t1.present_address_line_1, t1.present_address_line_2, t1.city2, t1.state2, t1.country2, t1.pin_code2, t1.phn_no2, t1.fathers_name, t1.fathers_occupation, t1.mothers_name, t1.mothers_occupation, t1.spouses_name, t1.spouses_occupation, t1.height_cms, t1.weight_kgs, t1.allergies, t1.other_medical_concerns, t1.physical_handicap from `tabEmployee Profile` t1, `tabEmployee` t2 where t1.employee = t2.name") - for e in emp_prof: - prof_obj = get_obj('Employee Profile', e[0]) - emp_obj = get_obj('Employee', e[1]) - for d in fld_map: - emp_obj.doc.fields[d] = prof_obj.doc.fields[d] - emp_obj.doc.current_accommodation_type = prof_obj.doc.present_accommodation_type - - # address - per_addr = cstr(e[2]) + '\n' + cstr(e[3]) + '\n' + cstr(e[4]) + '\n' + cstr(e[5]) + ', ' + cstr(e[6]) + '\n' + 'PIN - ' + cstr(e[7]) + '\n' + 'Ph. No' + cstr(e[8]) - cur_addr = cstr(e[9]) + '\n' + cstr(e[10]) + '\n' + cstr(e[11]) + '\n' + cstr(e[12]) + ', ' + cstr(e[13]) + '\n' + 'PIN - ' + cstr(e[14]) + '\n' + 'Ph. No' + cstr(e[15]) - emp_obj.doc.permanent_address = per_addr - emp_obj.doc.current_address = cur_addr - #family - fam = "Father's Name: " + cstr(e[16]) + '\n' + "Father's Occupation: " + cstr(e[17]) + '\n' + "Mother's Name: " + cstr(e[18]) + '\n' + "Mother's Occupation: " + cstr(e[19]) + '\n' + "Spouse's Name: " + cstr(e[20]) + '\n' + "Spouse's Occupation: " + cstr(e[21]) - emp_obj.doc.family_background = fam - # health - health = 'Height(cms): ' + cstr(e[22]) + '\n' + 'Weight(kgs): ' + cstr(e[23]) + '\n' + 'Allergies: ' +cstr( e[24]) + '\n' + 'Other Medical Concern: ' + cstr(e[25]) + '\n' + 'Physically Handicapped(if any): ' + cstr(e[26]) - emp_obj.doc.health_details = health - emp_obj.doc.save() - - - # map tables - tbl_list = ['Experience In Company Detail', 'Previous Experience Detail', 'Educational Qualifications Detail'] - for t in tbl_list: - sql("update `tab%s` t1, `tabEmployee Profile` t2 set t1.parent = t2.employee, t1.parenttype = 'Employee' where t1.parent = t2.name" % t) - - - # overwrite idx????????? - - - # delete emp profile - webnotes.model.delete_doc('DocType', 'Employee Profile') - for e in emp_prof: - webnotes.model.delete_doc('Employee Profile', e[0]) - - elif patch_no == 70: - # update search criteria module -> System - sql("update tabDocType set module='System' where name='Search Criteria'") - - # Cleanups to Contact - sql("update tabDocField set fieldtype='Data' where options='Designation' and parent='Contact'") - sql("update tabDocField set fieldtype='Data' where options='Department' and parent='Contact'") - sql("update tabDocField set depends_on='eval:(cint(doc.is_customer) || cint(doc.is_supplier) || cint(doc.is_sales_partner))' where fieldname='is_primary_contact' and parent='Contact'") - - # import Contact, Employee - from webnotes.modules.import_module import import_from_files - import_from_files(record_list=[['tools','doctype','contact']]) - - - # remove last_contact_date from Lead - sql("delete from tabDocField where fieldname='last_contact_date' and parent='Lead'") - - elif patch_no == 71: - # Make Stock Qty and Conversion Factor field editable. Also no need to mention Conversion factor in table can do it directly - sql("update `tabDocField` set `permlevel` = 0, `width` = '100px', `trigger` = 'Client' where parent IN ('PO Detail','Purchase Receipt Detail') and fieldname in ('stock_qty','conversion_factor')") - sql("update `tabDocField` set `width` = '100px' where parent IN ('PO Detail','Purchase Receipt Detail') and fieldname = 'stock_uom'") - - elif patch_no == 72: - # Core Patch - # ---------- - - from webnotes.modules.import_module import import_from_files - - # import module def - import_from_files(record_list = [['core', 'Module Def', 'Core']]) - elif patch_no == 73: - # set module in DocTypes - sql("update tabDocType set module='Core' where name in ('DocType', 'DocField', 'DocPerm', 'Role', 'UserRole', 'Profile', 'Print Format', 'DocFormat', 'Control Panel', 'Event', 'Event Role', 'Event User', 'DefaultValue', 'Default Home Page', 'File', 'File Group', 'File Data', 'Letter Head', 'Module Def', 'Module Def Item', 'Module Def Role', 'Page', 'Page Role', 'Search Criteria', 'DocType Label', 'DocType Mapper', 'Field Mapper Detail', 'Table Mapper Detail')") - - # set module in Page - sql("update tabPage set module='Core' where name='Login Page'") - - # move file browser to Tools - sql("update tabPage set module='Tools' where name='File Browser'") - sql("update tabDocType set module='Tools' where name='File Browser Control'") - sql("update tabDocType set module='Application Internal' where name='Profile Control'") - elif patch_no == 74: - p = get_obj('Patch Util') - # permission - p.delete_permission('Employee', 'Administrator', 0) - p.delete_permission('Employee', 'Administrator', 1) - p.add_permission('Employee', 'Employee', 0, read = 1, match = 'owner') - p.add_permission('Employee', 'Employee', 1, read = 1, match = 'owner') - sql("delete from `tabDocField` where parent = 'Employee' and label = 'Payroll Rule'") - elif patch_no == 75: - #sal structure patch - # import - from webnotes.modules.import_module import import_from_files - import_from_files(record_list=[['payroll','doctype','salary_structure'], ['payroll','doctype','earning_detail'],['payroll','doctype','deduction_detail']]) - elif patch_no == 76: - # property - p = get_obj('Patch Util') - p.set_field_property('Salary Structure', 'is_active', 'default', 'Yes') - p.set_field_property('Salary Structure', 'ctc', 'reqd', '1') - p.set_field_property('Earning Detail', 'modified_value', 'width', '') - p.set_field_property('Earning Detail', 'modified_value', 'trigger', 'Client') - p.set_field_property('Deduction Detail', 'd_modified_amt', 'width', '') - p.set_field_property('Earning Detail', 'd_modified_amt', 'trigger', 'Client') - sql("Update tabDocField set `description` = 'You can create more earning and deduction type from Setup --> HR' where label = 'Earning & Deduction' and parent = 'Salary Structure' and fieldtype = 'Section Break'") - - # delete - sql("update `tabSalary Structure` set net_pay = total") - sql("delete from tabDocField where label in ('LWP Help', 'Calculate Total', 'Total') and parent = 'Salary Structure'") - sql("delete from tabDocPerm where parent in ('Earning Detail', 'Deduction Detail')") - - - # permission - p.delete_permission('Salary Structure', 'Administrator', 0) - p.delete_permission('Salary Structure', 'Administrator', 1) - p.add_permission('Salary Structure', 'Employee', 0, read = 1, match = 'owner') - p.add_permission('Salary Structure', 'Employee', 1, read = 1, match = 'owner') - elif patch_no == 77: - # sal slip patch - # import - from webnotes.modules.import_module import import_from_files - import_from_files(record_list=[['payroll','doctype','salary_slip'], ['payroll','doctype','ss_earning_detail'],['payroll','doctype','ss_deduction_detail'], ['mapper', 'DocType Mapper', 'Salary Structure-Salary Slip']]) - elif patch_no == 78: - p = get_obj('Patch Util') - # delete - sql("update `tabSalary Slip` set leave_encashment_amount = encashment_amount") - p.delete_field('Salary Slip', 'encashment_amount') - p.delete_field('Salary Slip', 'year') - p.delete_field('Salary Slip', 'flag') - sql("delete from tabDocField where label = 'Process Payroll' and parent = 'Salary Slip'") - - # field property - p.set_field_property('Salary Slip', 'bank_name', 'permlevel', '1') - p.set_field_property('Salary Slip', 'leave_without_pay', 'permlevel', '0') - p.set_field_property('Salary Slip', 'leave_without_pay', 'trigger', 'Client') - p.set_field_property('SS Earning Detail', 'e_type', 'permlevel', '0') - p.set_field_property('SS Earning Detail', 'e_type', 'fieldtype', 'Link') - p.set_field_property('SS Earning Detail', 'e_type', 'options', 'Earning Type') - p.set_field_property('SS Deduction Detail', 'd_type', 'permlevel', '0') - p.set_field_property('SS Deduction Detail', 'd_type', 'fieldtype', 'Link') - p.set_field_property('SS Deduction Detail', 'd_type', 'options', 'Deduction Type') - sql("update `tabSS Earning Detail` set e_modified_amount = e_amount") - sql("update `tabSS Deduction Detail` set d_modified_amount = d_amount") - - # permission - p.delete_permission('Salary Slip', 'Administrator', 0) - p.delete_permission('Salary Slip', 'Administrator', 1) - p.add_permission('Salary Slip', 'Employee', 0, read = 1, match = 'owner') - p.add_permission('Salary Slip', 'Employee', 1, read = 1, match = 'owner') - elif patch_no == 79: - # Import Modules - - import_from_files(record_list=[['payroll','doctype','leave_application'],['payroll','doctype','leave_allocation'],['payroll','doctype','leave_control_panel'],['payroll','doctype','holiday_list'],['payroll','doctype','holiday_list_detail'],['payroll','Module Def','Payroll']]) - elif patch_no == 80: - # Holiday List - sql("update `tabHoliday List Detail` set description = holiday_name") - sql("delete from tabDocField where parent = 'Holiday List Detail' and fieldname = 'holiday_name'") - sql("update tabDocField set fieldtype = 'Select', options = 'link:Fiscal Year' where parent = 'Holiday List' and fieldname = 'fiscal_year'") - sql("delete from tabDocPerm where role in ('Administrator','HR User') and parent = 'Holiday List'") - - # Leave Control Panel - # -------------------- - sql("delete from `tabDocField` where parent = 'Leave Control Panel' and label in ('Leave Control Panel','Allocation Details') and fieldtype = 'Section Break'") - sql("delete from tabDocField where parent = 'Leave Control Panel' and fieldname in ('col_brk3','allocation_type','col_brk2','from_date','to_date','leave_transaction_type','posting_date')") - sql("update tabDocField set fieldtype = 'Select', options = 'link:Fiscal Year' where parent = 'Leave Control Panel' and fieldname = 'fiscal_year'") - sql("update tabDocField set fieldtype = 'Select', options = 'link:Leave Type' where parent = 'Leave Control Panel' and fieldname = 'leave_type'") - sql("update tabDocField set reqd = 1 where parent = 'Leave Control Panel' and fieldname = 'no_of_days'") - - # Leave Application - # ------------------ - for d in sql("select * from `tabLeave Transaction` where leave_transaction_type = 'Deduction' and ifnull(deduction_type, '') = 'Leave'", as_dict = 1): - lp = Document('Leave Application') - lp.employee = d['employee'] - lp.leave_type = d['leave_type'] - lp.posting_date = d['date'] - lp.fiscal_year = d['fiscal_year'] - lp.leave_balance = d['pre_balance'] - lp.half_day = d['half_day'] - lp.from_date = d['from_date'] - lp.to_date = d['to_date'] - lp.total_leave_days = d['total_leave'] - lp.description = d['reason'] - lp.docstatus = cint(d['docstatus']) - lp.save(1) - - # Leave Allocation - # ----------------- - for d in sql("select * from `tabLeave Transaction` where leave_transaction_type = 'Allocation'", as_dict = 1): - la = Document('Leave Allocation') - la.employee = d['employee'] - la.leave_type = d['leave_type'] - la.posting_date = d['date'] - la.fiscal_year = d['fiscal_year'] - la.new_leaves_allocated = d['total_leave'] - la.total_leaves_allocated = d['total_leave'] - la.description = d['reason'] - la.docstatus = cint(d['docstatus']) - la.save(1) - - # Payroll Module Def - # ------------------- - sql("delete from `tabModule Def Item` where doc_name = 'Leave Transaction' and display_name = 'Leave Transaction' and parent = 'Payroll' and doc_type = 'Forms'") - - elif patch_no == 81: - # Import Modules - - import_from_files(record_list=[['payroll','Module Def','Payroll']]) - elif patch_no == 82: - sql("update tabDocType set search_fields = 'employee,leave_type,total_leaves_allocated,fiscal_year' where name = 'Leave Allocation'") - sql("update tabDocType set search_fields = 'employee,leave_type,from_date,to_date,total_leave_days,fiscal_year' where name = 'Leave Application'") - elif patch_no == 83: - # delete leave transaction - webnotes.conn.sql("set foreign_key_checks=0") - sql("delete from `tabLeave Transaction`") - import webnotes.model - webnotes.model.delete_doc('DocType','Badge Settings Detail') - webnotes.model.delete_doc('DocType','Leave Transaction') - webnotes.conn.sql("set foreign_key_checks=1") - elif patch_no == 84: - p = get_obj('Patch Util') - p.set_field_property('SS Earning Detail', 'e_amount', 'permlevel', '1') - p.set_field_property('SS Deduction Detail', 'd_amount', 'permlevel', '1') - elif patch_no == 85: - # permission - p = get_obj('Patch Util') - p.add_permission('Leave Application', 'Employee', 0, read = 1, write = 1, create = 1, submit = 1, cancel = 1, amend = 1, match = 'owner') - p.add_permission('Leave Application', 'Employee', 1, read = 1, match = 'owner') - p.add_permission('Leave Allocation', 'HR User', 0, read = 1, write = 1, create = 1, submit = 1, cancel = 1, amend = 1, match = 'owner') - p.add_permission('Leave Allocation', 'HR User', 1, read = 1) - sql("update tabDocPerm set `match` = '' where parent = 'Leave Application' and role = 'HR User'") - elif patch_no == 86: - # Import Modules - - import_from_files(record_list=[['payroll','doctype','leave_type']]) - elif patch_no == 87: - sql("update `tabLeave Type` set is_lwp = 1 where name = 'Leave Without Pay'") - elif patch_no == 88: - # Import Modules - - import_from_files(record_list=[['payroll','doctype','leave_allocation']]) - elif patch_no == 89: - sql("delete from `tabModule Def Item` where doc_type = 'Setup Forms' and doc_name in ('Payroll Rule', 'IT Checklist', 'Employee Profile') and parent = 'Payroll'") - sql("update `tabDocField` set `hidden` = 1, `print_hide` = 1, `report_hide` = 1 where parent = 'Leave Type' and fieldname = 'is_encash'") - elif patch_no == 90: - sql("update `tabLeave Allocation` set docstatus = 1") - elif patch_no == 91: - import webnotes - webnotes.conn.set_global("system_message", """

System Updates

Based on user feedback, we have cleaned up HR module (Partly):
  • Employee and Employee Profile are merged into a single document
  • Salary Structure and Salary Slip are now more user friendly
  • Leave Transaction document is now divided into 2 documents Leave Application and Leave Allocation
We will work on Reports, Attendance and other documents of Payroll module next week

Do send us your feedback!""") - webnotes.conn.set_global("system_message_id", "5") - elif patch_no == 92: - sql("update tabDocField set label = 'Get Charges' where parent IN ('Sales Order','Delivery Note','Receivable Voucher') and label = 'Get Other Charges' and fieldtype = 'Button'") - # Automated Other Charges Calculation basis - sql("update tabDocField set options = '', `trigger` = 'Client' where parent IN ('Quotation','Sales Order','Delivery Note','Receivable Voucher') and label = 'Get Charges' and fieldtype = 'Button'") - elif patch_no == 93: - sql("update `tabTable Mapper Detail` set validation_logic = 'qty > ifnull(billed_qty,0) and docstatus = 1' where parent = 'Sales Order-Receivable Voucher' and from_table = 'Sales Order Detail'") - sql("update `tabField Mapper Detail` set from_field = 'customer' where to_field = 'customer' and parent = 'Sales Order-Receivable Voucher'") - elif patch_no == 94: - - import_from_files(record_list=[['crm','doctype','sms_center']]) - elif patch_no == 95: - - import_from_files(record_list=[['mapper','DocType Mapper','Sales Order-Receivable Voucher'], ['mapper','DocType Mapper','Delivery Note-Receivable Voucher']]) - elif patch_no == 96: - sql("delete from `tabModule Def Item` where doc_type = 'Reports' and display_name = 'Cenvat Credit - Input or Capital Goods' and parent = 'Accounts'") - elif patch_no == 97: - sql("update tabFeed set doc_label = 'Feed', doc_name = name where ifnull(doc_name,'') = '' and ifnull(doc_label,'') = ''") - elif patch_no == 98: - import_from_files(record_list=[['accounts','doctype','payable_voucher']]) - elif patch_no == 99: - import_from_files(record_list=[['accounts','doctype','account']]) - elif patch_no == 100: - p = get_obj('Patch Util') - p.set_field_property('Account', 'level', 'hidden', '1') - p.set_field_property('Account', 'level', 'print_hide', '1') - p.set_field_property('Account', 'account_type', 'search_index', '0') - p.set_field_property('TDS Detail', 'tds_category', 'width', '150px') - p.set_field_property('TDS Detail', 'special_tds_rate_applicable', 'width', '150px') - p.set_field_property('TDS Detail', 'special_tds_rate', 'width', '150px') - p.set_field_property('TDS Detail', 'special_tds_limit', 'width', '150px') - elif patch_no == 101: - # Leave Application Details and Leave Allocation Details - sql("update tabDocField set search_index = 1, in_filter = 1 where fieldname in ('employee','leave_type','fiscal_year') and parent in ('Leave Application','Leave Allocation')") - get_obj('DocType','Leave Application').doc.save() - get_obj('DocType','Leave Allocation').doc.save() - elif patch_no == 102: - # make item description field editable in production order - sql("update tabDocField set permlevel = 0 where fieldname = 'description' and parent = 'Production Order'") - elif patch_no == 103: - sql("update tabDocField set fieldname = '' where fieldtype = 'HTML'") - elif patch_no == 104: - - import_from_files(record_list=[['payroll','search_criteria','stdsrch_00001'],['payroll','search_criteria','stdsrch_00002'],['payroll','search_criteria','stdsrch_00003'],['payroll','Module Def','Payroll'],['payroll','doctype','leave_application'],['payroll','doctype','leave_allocation']]) - elif patch_no == 105: - # Employee Leave Balance - sql("delete from `tabModule Def Item` where parent = 'Payroll' and doc_type = 'Reports' and display_name IN ('Employeewise Leave Transaction Details','Employeewise Balance Leave Report')") - # Update Search Fields - sql("update tabDocType set search_fields = 'employee,employee_name,leave_type,from_date,to_date,total_leave_days,fiscal_year' where name = 'Leave Application'") - sql("update tabDocType set search_fields = 'employee,employee_name,leave_type,total_leaves_allocated,fiscal_year' where name = 'Leave Allocation'") - elif patch_no == 106: - for d in sql("select name,employee,employee_name from `tabLeave Allocation`"): - if not cstr(d[2]): - sql("update `tabLeave Allocation` set employee_name = '%s' where name = '%s'" % (webnotes.conn.get_value('Employee',cstr(d[1]),'employee_name'), cstr(d[0]))) - for d in sql("select name,employee,employee_name from `tabLeave Application`"): - if not cstr(d[2]): - sql("update `tabLeave Application` set employee_name = '%s' where name = '%s'" % (webnotes.conn.get_value('Employee',cstr(d[1]),'employee_name'), cstr(d[0]))) - elif patch_no == 107: - sql("delete from `tabDocField` where fieldname = 'fiscal_year' and parent = 'Employee'") - elif patch_no == 108: - import_from_files(record_list=[['payroll','search_criteria','srch_std_00013']]) - elif patch_no == 109: - import_from_files(record_list=[['payroll','search_criteria','srch_std_00015']]) - elif patch_no == 110: - import_from_files(record_list=[['payroll','doctype','salary_structure'], ['payroll', 'doctype', 'salary_slip']]) - elif patch_no == 111: - sql("update tabDocType set search_fields = 'transfer_date, from_warehouse, to_warehouse, purpose, remarks' where name = 'Stock Entry'") - elif patch_no == 112: - sql("delete from tabDocField where label = 'Get Other Charges' and fieldtype = 'Button' and parent = 'Receivable Voucher'") - elif patch_no == 113: - sql("update tabDocField set reqd = 1 where parent = 'Customer' and fieldname = 'phone_1'") - elif patch_no == 114: - for d in sql("select name, master_name, credit_days, credit_limit from tabAccount where master_type = 'Customer'"): - if cstr(d[1]): - days, limit = cint(d[2]), flt(d[3]) - cust_det = sql("select credit_days, credit_limit from tabCustomer where name = '%s'" % (cstr(d[1]))) - if not days: days = cust_det and cint(cust_det[0][0]) or 0 - if not limit: limit = cust_det and flt(cust_det[0][1]) or 0 - sql("COMMIT") - sql("START TRANSACTION") - sql("update tabAccount set credit_days = '%s', credit_limit = '%s' where name = '%s'" % (days, limit, cstr(d[0]))) - sql("COMMIT") - - elif patch_no == 115: - # patch for timesheet cleanup - from webnotes.model import delete_doc - delete_doc('DocType', 'Timesheet Detail') - - from webnotes.modules.import_module import import_from_files - import_from_files(record_list = [['Projects', 'DocType', 'Timesheet'], ['Projects', 'DocType', 'Timesheet Detail'], ['Projects', 'DocType', 'Activity Type']]) - - elif patch_no == 116: - # again! - from webnotes.model import delete_doc - delete_doc('DocType', 'Timesheet Detail') - - from webnotes.modules.import_module import import_from_files - import_from_files(record_list = [['Projects', 'DocType', 'Timesheet Detail']]) - elif patch_no == 117: - op = '\n' + 'Walk In' - sql("update `tabDocField` set `options` = concat(options, %s) where parent = 'Enquiry' and fieldname = 'source' and options not like '%%Walk%%'", op) - elif patch_no == 118: - from webnotes.utils import get_defaults - ss = sql("select name, net_pay from `tabSalary Slip`") - for d in ss: - if d[1]: - w = get_obj('Sales Common').get_total_in_words(get_defaults()['currency'], d[1]) - sql("update `tabSalary Slip` set net_pay_in_words = '%s' where name = '%s'" % (w, d[0])) - elif patch_no == 119: - sql("update tabDocType set in_create = 1 where name = 'Profile'") - elif patch_no == 120: - sql("update tabDocField set permlevel = 0 where parent = 'Sales and Purchase Return Wizard' and fieldname = 'return_date'") - elif patch_no == 121: - import_from_files(record_list = [['CRM', 'DocType', 'Return Detail'], ['Material Management', 'DocType', 'Sales and Purchase Return Wizard']]) - elif patch_no == 122: - sql("delete from tabDocField where (fieldname = 'serial_no' or label = 'Warrany Status') and parent = 'Sales Order'") - elif patch_no == 123: - import_from_files(record_list = [['CRM', 'Module Def', 'CRM'], ['CRM', 'Search Criteria', 'STDSRCH/00004']]) - elif patch_no == 124: - import webnotes - webnotes.conn.set_global("system_message", """

Updates(New)

We have added a new report in the Selling Module.

Sales Personwise Transaction Summary: In this report you can see sales person's contribution in a particular order, delivery or invoice. You can select voucher type in "Based On" filter.

Do send us your feedback!""") - webnotes.conn.set_global("system_message_id", "5") - elif patch_no == 125: - import_from_files(record_list = [['Material Management', 'DocType', 'Delivery Note']]) - elif patch_no == 126: - sql("delete from tabDocField where parent = 'Delivery Note' and label in ('Make Sales Invoice', 'Make Installation Note', 'Intro Note')") - elif patch_no == 127: - sql("delete from tabDocPerm where role = 'All' and parent = 'Expense Voucher' and (permlevel = 0 or permlevel = 2)") - p = get_obj('Patch Util') - p.add_permission('Expense Voucher', 'Employee', 0, read = 1, write = 1, create = 1, submit = 1, cancel = 1, amend = 1, match = 'owner') - p.add_permission('Expense Voucher', 'HR Manager', 0, read = 1, write = 1, create = 1, submit = 1, cancel = 1, amend = 1) - p.add_permission('Expense Voucher', 'HR User', 0, read = 1, write = 1, create = 1, submit = 1, cancel = 1, amend = 1) - elif patch_no == 128: - from webnotes.modules import import_module - import_module.import_from_files(record_list=[['crm','doctype','sales_order'], ['crm','doctype','sales_order_detail'], ['material_management','doctype','delivery_note'], ['material_management','doctype','delivery_note_detail']]) - elif patch_no == 129: - sql("update `tabTable Mapper Detail` set validation_logic = '(qty > ifnull(billed_qty, 0) or amount > ifnull(billed_amt, 0)) and docstatus = 1' where parent = 'Sales Order-Receivable Voucher' and from_table = 'Sales Order Detail' and to_table = 'RV Detail'") - sql("update `tabTable Mapper Detail` set validation_logic = '(qty > ifnull(billed_qty, 0) or amount > ifnull(billed_amt, 0)) and docstatus = 1' where parent = 'Delivery Note-Receivable Voucher' and from_table = 'Delivery Note Detail' and to_table = 'RV Detail'") - elif patch_no == 130: - # update from rv - from webnotes.model.code import get_obj - from webnotes.utils import cstr - for d in sql("select name, docstatus from `tabReceivable Voucher` where ifnull(docstatus,0) != 0"): - sql("COMMIT") - sql("START TRANSACTION") - try: - obj = get_obj('Receivable Voucher', cstr(d[0]), with_children = 1) - is_submit = 1 - if cint(d[1]) == 2: is_submit = 0 - get_obj('Sales Common').update_prevdoc_detail(is_submit, obj) - except: - pass - sql("COMMIT") - - # update from dn - from webnotes.model.code import get_obj - for d in sql("select name, docstatus from `tabDelivery Note` where ifnull(docstatus,0) != 0"): - sql("COMMIT") - sql("START TRANSACTION") - try: - obj = get_obj('Delivery Note', cstr(d[0]), with_children = 1) - is_submit = 1 - if cint(d[1]) == 2: is_submit = 0 - get_obj('Sales Common').update_prevdoc_detail(is_submit, obj) - except: - pass - sql("COMMIT") - elif patch_no == 131: - sql("update `tabDocType` set allow_trash = 1 where name = 'Purchase Other Charges'") - sql("update tabDocPerm set `cancel` = 1 where parent = 'Purchase Other Charges' and permlevel = 0 and `read` = 1 and `write` = 1") - elif patch_no == 132: - sql("update tabDocField set no_copy = 0 where parent = 'Receivable Voucher' and fieldname = 'customer'") - elif patch_no == 133: - from webnotes.modules import import_module - import_module.import_from_files(record_list=[['accounts','doctype','receivable_voucher']]) - elif patch_no == 134: - sql("update tabDocField set no_copy = 1 where parent = 'Receivable Voucher' and fieldname = 'posting_time'") - elif patch_no == 135: - sql("update tabDocField set `default` = 'Today' where parent = 'Receivable Voucher' and fieldname = 'due_date'") - elif patch_no == 136: - from webnotes.modules import import_module - import_module.import_from_files(record_list=[['accounts','doctype','rv_detail']]) - elif patch_no == 137: - from webnotes.modules import import_module - import_module.import_from_files(record_list=[['setup','doctype','price_list']]) - elif patch_no == 138: - sql("update `tabDocType` set allow_attach = 1 where name = 'Price List'") - elif patch_no == 139: - from webnotes.modules import import_module - import_module.import_from_files(record_list=[['mapper','DocType Mapper','Sales Order-Receivable Voucher'], ['mapper','DocType Mapper','Delivery Note-Receivable Voucher']]) - elif patch_no == 140: - from webnotes.modules import import_module - import_module.import_from_files(record_list=[['accounts','doctype','rv_detail']]) - elif patch_no == 141: - sql("delete from tabDocField where (fieldname = 'letter_head' or label = 'Letter Head') and parent = 'Company'") - elif patch_no == 142: - # fixes to letter head and personalize - from webnotes.model import delete_doc - - delete_doc('DocType', 'Batch Settings') - delete_doc('DocType', 'Batch Settings Detail') - delete_doc('DocType', 'Social Badge') - delete_doc('Page', 'Personalize Page') - delete_doc('DocType', 'Personalize Page Control') - - import_from_files(record_list=[['core','doctype','letter_head'], ['setup','doctype','personalize']]) - elif patch_no == 144: - webnotes.conn.sql("update tabDocField set fieldtype='Code' where parent='Letter Head' and fieldname='content'") - elif patch_no == 145: - sql("update `tabDocField` set permlevel=1 where fieldname = 'group_or_ledger' and parent = 'Account'") - elif patch_no == 146: - import_from_files(record_list=[['accounts','doctype','account']]) - elif patch_no == 147: - import_from_files(record_list=[['mapper', 'DocType Mapper', 'Purchase Order-Payable Voucher'], ['mapper', 'DocType Mapper', 'Purchase Receipt-Payable Voucher'], ['mapper', 'DocType Mapper', 'Purchase Order-Purchase Receipt']]) - elif patch_no == 148: - sql("delete from `tabDocField` where (fieldname = 'account_balances' or label = 'Balances') and parent = 'Account'") - sql("update tabDocType set istable = 0, section_style = 'Simple', search_fields = 'account, period, fiscal_year, balance' where name = 'Account Balance'") - sql("update tabDocField set permlevel = 0 where parent = 'Account Balance'") - p = get_obj('Patch Util') - p.add_permission('Account Balance', 'Accounts User', 0, read = 1) - p.add_permission('Account Balance', 'Accounts Manager', 0, read = 1) - import_from_files(record_list=[['accounts','doctype','account_balance']]) - elif patch_no == 149: - sql("update `tabAccount Balance` set account = parent") - elif patch_no == 150: - sql("update tabDocField set in_filter = 1, search_index = 1 where parent = 'Account Balance' and fieldname in ('account', 'period', 'fiscal_year', 'start_date', 'end_date')") - ac_bal = Document("DocType", "Account Balance") - ac_bal.save() - elif patch_no == 151: - sql("delete from tabDocField where label = 'Add / Manage Contacts' and fieldtype = 'Button' and parent = 'Customer'") - sql("delete from `tabField Mapper Detail` where parent = 'Sales Order-Delivery Note' and from_field = 'note' and to_field = 'note'") - elif patch_no == 152: - import_from_files(record_list=[['crm','doctype','sales_order'], ['material_management','doctype','delivery_note'], ['crm','doctype','customer'], ['crm','doctype','shipping_address'], ['mapper', 'DocType Mapper', 'Sales Order-Delivery Note']]) - elif patch_no == 153: - sql("delete from `tabDocField` where fieldname = 'sales_person' and parent = 'Customer'") - elif patch_no == 154: - import_from_files(record_list=[['material_management','doctype','serial_no'], ['maintenance','doctype','customer_issue']]) - elif patch_no == 155: - for d in sql("select name, item_code from `tabSerial No`"): - sql("COMMIT") - sql("START TRANSACTION") - sql("update `tabSerial No` set item_name = '%s' where name = '%s'" % (webnotes.conn.get_value('Item',cstr(d[1]),'item_name'), cstr(d[0]))) - sql("COMMIT") - elif patch_no == 156: - sql("update tabDocField set fieldtype = 'Code' where fieldname = 'html' and parent = 'Print Format'") - elif patch_no == 157: - import_from_files(record_list=[['accounts', 'doctype', 'journal_voucher'], ['accounts', 'Print Format', 'Payment Receipt Voucher'], ['accounts', 'Print Format', 'Cheque Printing Format']]) - elif patch_no == 158: - from webnotes.model.doc import addchild - sql("delete from tabDocField where parent = 'Customer Issue' and fieldname = 'customer_group'") - elif patch_no == 159: - sql("update tabAccount set account_type = 'Chargeable' where account_name in ('Advertising and Publicity', 'Freight & Forwarding Charges', 'Miscellaneous Expenses', 'Sales Promotion Expenses')") - elif patch_no == 160: - sql("update `tabDocType` set search_fields = 'posting_date, due_date, debit_to, fiscal_year, grand_total, outstanding_amount' where name = 'Receivable Voucher'") - sql("update `tabDocType` set search_fields = 'posting_date, credit_to, fiscal_year, bill_no, grand_total, outstanding_amount' where name = 'Payable Voucher'") - elif patch_no == 161: - sql("update tabDocType set autoname = 'field:batch_id' where name = 'Batch'") - sql("update tabDocField set no_copy = 1 where parent = 'Batch' and fieldname = 'batch_id'") - elif patch_no == 162: - import_from_files(record_list=[['crm', 'search_criteria', 'sales_order_pending_items1']]) - elif patch_no == 163: - sql("delete from `tabModule Def Item` where display_name = 'Sales Orderwise Pending Packing Item Summary' and parent = 'CRM'") - import_from_files(record_list=[['crm', 'search_criteria', 'sales_orderwise_pending_qty_to_deliver'], ['crm', 'search_criteria', 'sales_orderwise_pending_amount_to_bill'], ['crm', 'search_criteria', 'delivered_items_to_be_install']]) - elif patch_no == 164: - import_from_files(record_list=[['srm', 'search_criteria', 'pending_po_items_to_receive'], ['srm', 'search_criteria', 'pending_po_items_to_bill']]) - elif patch_no == 165: - pass - elif patch_no == 166: - import_from_files(record_list=[['srm', 'doctype', 'purchase_order']]) - elif patch_no == 167: - if webnotes.conn.get_value('Control Panel', None, 'account_id') not in ['ax0000956', 'ax0001338']: - sql("delete from tabDocField where parent = 'Purchase Order' and fieldname in ('test_certificate_required', 'estimated_cost', 'transport', 'vendor_reference', 'transportation_required', 'mode_of_dispatch', 'octroi')") - elif patch_no == 168: - sql("update tabDocField set fieldtype = 'Data', options = 'Suggest' where fieldname = 'bank_name' and parent = 'Employee'") - elif patch_no == 169: - import_from_files(record_list=[['accounts', 'doctype', 'pv_detail'], ['accounts', 'doctype', 'rv_detail']]) - elif patch_no == 170: - import_from_files(record_list=[['mapper', 'DocType Mapper', 'Delivery Note-Receivable Voucher']]) - elif patch_no == 171: - import_from_files(record_list=[['srm', 'doctype', 'supplier']]) - elif patch_no == 172: - import webnotes - webnotes.conn.set_global("system_message", """Welcome to the new financial year 2011-2012 !!!

So obvious question in your mind is how to start Entries in the New Fiscal Year in ERPNext? What are the changes you have to make in the system?
We have made some guidelines regarding the basic steps you should follow. Please click on link How to start Entries in the New Fiscal Year in ERPNext?""") - webnotes.conn.set_global("system_message_id", "6") - elif patch_no == 173: - sql("delete from tabDocField where label = 'Get Other Charges' and parent = 'Delivery Note'") - sql("update tabDocField set reqd = 0 where fieldname = 'posting_time' and parent = 'Serial No'") - elif patch_no == 174: - c = sql("select count(name) from `tabField Mapper Detail` where parent = 'Delivery Note-Receivable Voucher' and from_field = 'description' and to_field = 'description' and match_id = 2") - if c and cint(c[0][0]) > 1: - sql("update `tabField Mapper Detail` set match_id = 1 where parent = 'Delivery Note-Receivable Voucher' and from_field = 'description' and to_field = 'description' limit 1") - elif patch_no == 175: - import webnotes - webnotes.conn.set_global("system_message", """If your financial year starts on 1st April then you have make some changes in the system to start entry in the new year.
We have made some guidelines regarding the basic steps you should follow. Please click on link How to start Entries in the New Fiscal Year in ERPNext?""") - webnotes.conn.set_global("system_message_id", "6") - elif patch_no == 176: - sql("update tabDocPerm set role='Guest', `write`=0, `create`=0 where role='Administrator' and parent='Notification Control' limit 1") - elif patch_no == 177: - sql("delete from `tabDocField` where label = 'Next Steps' and parent = 'Purchase Order'") - sql("update tabDocField set options = 'Material Issue\nMaterial Receipt\nMaterial Transfer\nSales Return\nPurchase Return\nSubcontracting\nProduction Order' where parent = 'Stock Entry' and fieldname = 'purpose'") - elif patch_no == 178: - import_from_files(record_list = [['payroll', 'doctype', 'salary_slip']]) - elif patch_no == 179: - from webnotes.utils import get_defaults - sl = sql("select name, net_pay from `tabSalary Slip`") - for d in sl: - in_words = get_obj('Sales Common').get_total_in_words(get_defaults()['currency'], round(flt(d[1]))) - sql("update `tabSalary Slip` set rounded_total = '%s', total_in_words = '%s' where name = '%s'" % (round(flt(d[1])), in_words, d[0])) - elif patch_no == 180: - sql("delete from tabDocField where parent = 'Salary Slip' and fieldname = 'net_pay_in_words'") - elif patch_no == 181: - import_from_files(record_list = [['accounts', 'doctype', 'journal_voucher']]) - elif patch_no == 182: - sql("update tabDocField set options = CONCAT(options, '\nWrite Off Voucher') where fieldname = 'voucher_type' and parent = 'Journal Voucher'") - elif patch_no == 183: - sql("delete from tabDocField where label = 'SMS' and fieldtype = 'Section Break' and parent in ('Enquiry', 'Lead', 'Sales Order', 'Delivery Note')") - elif patch_no == 184: - from webnotes.model import delete_doc - delete_doc('DocType', 'Feed') - delete_doc('DocType', 'Feed List') - delete_doc('DocType', 'Feed Control') - - # add trigger - from webnotes.model.triggers import add_trigger - add_trigger('*','*','*','event_updates.update_feed') - - webnotes.conn.commit() - - try: - sql("drop table tabFeed") - sql("drop table `tabFeed List`") - except: pass - - # import - from webnotes.modules.module_manager import reload_doc - reload_doc('event_updates','doctype','feed') - elif patch_no==185: - sql("delete from tabDocTrigger where method = 'webnotes.widgets.follow.on_docsave'") - elif patch_no==186: - from webnotes.modules.module_manager import reload_doc - reload_doc('event_updates','doctype','feed') - elif patch_no == 187: - sql("update tabDocType set autoname = '' where name = 'QA Inspection Report'") - elif patch_no == 188: - import_from_files(record_list = [['srm', 'doctype', 'qa_inspection_report']]) - elif patch_no == 189: - sql("update `tabDocField` set allow_on_submit = 1 where fieldname in ('entries', 'other_charges') and parent = 'Receivable Voucher'") - elif patch_no == 190: - sql("update tabDocField set permlevel=0 where fieldname = 'fiscal_year' and parent = 'Stock Entry'") - elif patch_no == 191: - import_from_files(record_list = [['maintenance', 'doctype', 'customer_issue']]) - elif patch_no == 192: - sql("delete from `tabModule Def Item` where parent = 'Material Management' and doc_name = 'Landed Cost Wizard' and display_name = 'Landed Cost Wizard'") - import_from_files(record_list = [['srm', 'Module Def', 'SRM']]) - elif patch_no == 193: - sql("update tabDocField set fieldtype='Button', `trigger`='Client' where parent='Letter Head' and fieldname='set_from_image'") - elif patch_no == 194: - sql("delete from `tabModule Def Item` where parent = 'SRM' and doc_name = 'Landed Cost Wizard' and display_name = 'Landed Cost Wizard'") - import_from_files(record_list = [['material_management', 'Module Def', 'Material Management']]) - elif patch_no == 195: - from webnotes.modules.module_manager import reload_doc - reload_doc('setup','doctype','manage_account') - elif patch_no == 196: - sql("update `tabModule Def` set module_page = null where name = 'Material Management'") - elif patch_no == 197: - sql("update `tabDocField` set permlevel = 0, in_filter = 1 where fieldname = 'warranty_amc_status' and parent = 'Customer Issue'") - import_from_files(record_list = [['maintenance', 'doctype', 'customer_issue']]) - elif patch_no == 198: - sql("delete from `tabDocField` where (label in ('SMS', 'Send SMS') or fieldname in ('message', 'customer_mobile_no')) and parent in ('Quoattion', 'Sales Order', 'Delivery Note', 'Receivable Voucher')") - sql("delete from `tabDocField` where label in ('SMS', 'Send SMS') and parent = 'Purchase Order'") - sql("delete from `tabDocField` where (label in ('Send SMS', 'SMS Html') or fieldname in ('sms_message', 'lead_sms_detail', 'enquiry_sms_detail')) and parent in ('Lead', 'Enquiry')") - from webnotes.model import delete_doc - delete_doc('DocType', 'Lead SMS Detail') - delete_doc('DocType', 'Enquiry SMS Detail') - elif patch_no == 199: - sql("update tabDocField set reqd = 0 where parent = 'Attendance' and fieldname = 'shifts'") - elif patch_no == 200: - reload_doc('event_updates','page','profile_settings') - elif patch_no == 201: - reload_doc('setup','doctype','price_list') - elif patch_no == 202: - name1 = sql("select name from tabDocField where parent='Price List' and label='Clear Prices' limit 1,1") - name2 = sql("select name from tabDocField where parent='Price List' and label='Update Prices' limit 1,1") - if name1: - sql("delete from tabDocField where name=%s limit 1", name1[0][0]) - if name2: - sql("delete from tabDocField where name=%s limit 1", name2[0][0]) - elif patch_no == 203: - sql("delete from tabDocField where parent = 'Company' and fieldname = 'default_salary_account' limit 1") - elif patch_no == 204: - sql("delete from tabDocField where parent = 'Company' and fieldname = 'default_salary_acount' limit 1") - elif patch_no == 205: - sql("update `tabDocField` set `default` = '' where fieldname = 'naming_series' and parent = 'Installation Note'") - elif patch_no == 206: - reload_doc('crm','doctype','installation_note') - elif patch_no == 207: - import_from_files(record_list = [['setup', 'doctype', 'company']]) - elif patch_no == 208: - sql("delete from `tabDocField` where (label in ('SMS', 'Send SMS') or fieldname in ('message', 'customer_mobile_no')) and parent ='Quotation'") - default_currency = get_obj('Manage Account').doc.default_currency - sql("update tabCompany set default_currency = '%s'" % default_currency) - elif patch_no == 209: - import_from_files(record_list = [['setup', 'doctype', 'company']]) - elif patch_no == 210: - sql("delete FROM `tabDocField` WHERE parent = 'Lead' AND label in ('CC:','Attachment Html','Create New File','Attachment')") - elif patch_no == 212: - # reload company because of disturbed UI - import_from_files(record_list = [['setup', 'doctype', 'company']]) - elif patch_no == 213: - reload_doc('crm','doctype','lead') - reload_doc('setup','doctype','company') - elif patch_no == 214: - reload_doc('crm','doctype','sales_order') - elif patch_no == 215: - # patch for item and image in description - sql("update tabDocField set width = '300px' where fieldname='description'") - reload_doc('material_management', 'doctype', 'item') - sql("delete from __DocTypeCache") - elif patch_no == 216: - import_from_files(record_list = [['material_management', 'doctype', 'serial_no'], ['material_management', 'doctype', 'stock_ledger_entry']]) - elif patch_no == 217: - sql("update tabDocField set options = '\nIn Store\nDelivered\nNot in Use' where fieldname = 'status' and parent = 'Serial No'") - sql("update tabDocField set no_copy = 1 where fieldname = 'serial_no' and parent = 'Delivery Note Detail'") - sql("update tabDocField set no_copy = 1 where fieldname = 'serial_no' and parent = 'Stock Entry Detail'") - elif patch_no == 218: - for d in sql("select name from `tabSerial No`"): - sql("Commit") - sql("Start Transaction") - s = Document('Serial No', d[0]) - if s.pr_no: - s.purchase_document_type = 'Purchase Receipt' - s.purchase_document_no = s.pr_no - if s.delivery_note_no: - s.delivery_document_type = 'Delivery Note' - s.delivery_document_no = s.delivery_note_no - if s.notes: - s.delivery_note_no = s.notes - s.company = webnotes.utils.get_defaults()['company'] - s.fiscal_year = webnotes.utils.get_defaults()['fiscal_year'] - s.save() - elif patch_no == 219: - sql("delete from tabDocField where fieldname in ('pr_no', 'make', 'label', 'delivery_note_no', 'notes') and parent = 'Serial No'") - elif patch_no == 220: - sql("update tabDocField set label = 'Incoming Rate' where fieldname = 'purchase_rate' and parent = 'Serial No'") - sql("update tabDocField set label = 'Incoming Time' where fieldname = 'purchase_time' and parent = 'Serial No'") - elif patch_no == 221: - sql("update tabDocField set reqd = 1 where fieldname in ('purchase_rate', 'warehouse') and parent = 'Serial No'") - elif patch_no == 222: - sql("update tabDocField set options = '\nDelivery Note\nReceivable Voucher\nStock Entry' where fieldname = 'delivery_document_type' and parent = 'Serial No'") - elif patch_no == 223: - sql("update tabDocField set hidden = 0 where fieldname in ('pay_to_recd_from', 'total_amount', 'total_amount_in_words') and parent = 'Journal Voucher'") - sql("update tabDocField set permlevel = 0 where fieldname = 'pay_to_recd_from' and parent = 'Journal Voucher'") - elif patch_no == 224: - import_from_files(record_list = [['material_management', 'doctype', 'delivery_note_packing_detail'], ['accounts', 'Print Format', 'Payment Receipt Voucher']]) - elif patch_no == 225: - import_from_files(record_list = [['material_management', 'doctype', 'delivery_note_packing_detail']]) - elif patch_no == 226: - import_from_files(record_list = [['material_management', 'doctype', 'delivery_note_packing_detail']]) - elif patch_no == 227: - reload_doc('material_management', 'doctype', 'item') - if webnotes.conn.get_value('Control Panel', None, 'account_id') != 'axjanak2011': - sql("delete from tabDocField where parent = 'Item' and fieldname='alternate_description' limit 1") - elif patch_no == 228: - # knowledge base patch - reload_doc('knowledge_base', 'doctype', 'question') - reload_doc('knowledge_base', 'doctype', 'answer') - reload_doc('knowledge_base', 'page', 'questions') - reload_doc('knowledge_base', 'Module Def', 'Knowledge Base') - sql("update `tabModule Def` set disabled='No' where name='Knowledge Base'") - elif patch_no == 229: - reload_doc('knowledge_base', 'page', 'question_view') - elif patch_no == 230: - reload_doc('srm', 'doctype', 'indent') - reload_doc('srm', 'doctype', 'indent_detail') - reload_doc('Mapper', 'DocType Mapper', 'Sales Order-Indent') - elif patch_no == 231: - reload_doc('Mapper', 'DocType Mapper', 'Sales Order-Indent') - elif patch_no == 232: - sql("update `tabDocField` set options = 'Sales Order' where fieldname = 'sales_order_no' and parent = 'Indent'") - elif patch_no == 233: - reload_doc('Mapper', 'DocType Mapper', 'Sales Order-Receivable Voucher') - reload_doc('Mapper', 'DocType Mapper', 'Delivery Note-Receivable Voucher') - elif patch_no == 234: - sql("update `tabTable Mapper Detail` set validation_logic = 'docstatus=1' where parent = 'Sales Order-Indent' and from_table = 'Sales Order Detail'") - elif patch_no == 235: - for sc in sql("""select name from `tabSearch Criteria` where ifnull(name,'') - like 'srch%' or ifnull(name,'') like '%stdsrch'"""): - try: - get_obj('Search Criteria', sc[0]).rename() - except AttributeError, e: - pass - reload_doc('core', 'doctype', 'system_console') - elif patch_no == 236: - # warehouse not mandatory for delivered serial nos - sql("update tabDocField set reqd=0 where parent='Serial No' and fieldname='warehouse'") - elif patch_no == 237: - sql("update tabDocField set depends_on = 'eval:doc.is_pos==1' where fieldname = 'cash_bank_account' and parent = 'Receivable Voucher'") - elif patch_no == 238: - reload_doc('accounts', 'doctype', 'receivable_voucher') - reload_doc('accounts', 'GL Mapper', 'POS with write off') - elif patch_no == 239: - reload_doc('core', 'doctype', 'docfield') - reload_doc('core', 'doctype', 'doctype') - - from patches.feed_patch import set_subjects_and_tagfields - set_subjects_and_tagfields() - elif patch_no == 240: - # again for sales order (status) - from patches.feed_patch import set_subjects_and_tagfields - set_subjects_and_tagfields() - elif patch_no == 241: - sql("update `tabDocField` set fieldtype = 'Text', options = '', in_filter = '' where fieldname = 'serial_no' and parent = 'Stock Ledger Entry'") - elif patch_no == 242: - if webnotes.conn.get_value('Control Panel', None, 'account_id') not in ['axjanak2011']: - sql("commit") - try: - sql("alter table `tabStock Ledger Entry` drop index serial_no") - except: - pass - - sql("alter table `tabStock Ledger Entry` change serial_no serial_no text") - elif patch_no == 243: - # moving custom script and custom fields to framework - webnotes.conn.set_value('DocType', 'Custom Script', 'module', 'Core') - webnotes.conn.set_value('DocType', 'Custom Field', 'module', 'Core') - reload_doc('setup', 'doctype', 'company') - elif patch_no == 244: - reload_doc('material_management', 'search_criteria', 'shortage_to_indent') - elif patch_no == 245: - from patches.doctype_permission_patch import set_doctype_permissions - set_doctype_permissions() - - from patches.feed_patch import set_subjects_and_tagfields - set_subjects_and_tagfields() - elif patch_no == 246: - webnotes.conn.set_value('DocType','Stock Entry','tag_fields','purpose') - webnotes.conn.set_value('DocType','Stock Entry','subject','%(remarks)s') - elif patch_no == 247: - webnotes.conn.set_value('DocType','Stock Entry','subject','%(remarks)s') - elif patch_no == 248: - reload_doc('setup', 'doctype', 'manage_account') - elif patch_no == 249: - sql("update `tabDocPerm` t1, `tabDocType` t2 set t1.role = 'System Manager' where t1.role = 'Administrator' and t1.parent = t2.name and t2.module != 'Core'") - elif patch_no == 250: - from patches.feed_patch import support_patch - support_patch() - elif patch_no == 251: - from webnotes.model import db_schema - db_schema.remove_all_foreign_keys() - from patches.customer_address import run_patch - run_patch() - elif patch_no == 252: - reload_doc('maintenance','doctype','support_ticket') - reload_doc('maintenance','doctype','support_ticket_response') - elif patch_no == 253: - reload_doc('accounts','doctype','ledger_balance_export') - reload_doc('accounts','doctype','ledger_detail') - reload_doc('accounts', 'Module Def', 'Accounts') - - from webnotes.model.db_schema import updatedb - updatedb('Ledger Balance Export') - updatedb('Ledger Detail') - elif patch_no == 254: - reload_doc('settings', 'doctype', 'sms_settings') - reload_doc('settings', 'doctype', 'static_parameter_detail') - - from webnotes.model.db_schema import updatedb - updatedb('SMS Settings') - updatedb('Static Parameter Detail') - elif patch_no == 255: - from patches.customer_address import run_old_data_sync_patch - run_old_data_sync_patch() - elif patch_no == 256: - sql("update `tabLetter Head` set content = replace(content, 'http://46.4.50.84/v170-test/', '')") - sql("update `tabSingles` set value = replace(value, 'http://46.4.50.84/v170-test/', '') where field in ('letter_head', 'client_name') and doctype = 'Control Panel'") - sql("update `tabItem` set description_html = replace(description_html, 'http://46.4.50.84/v170-test/', '')") - elif patch_no == 257: - from patches.customer_address import run_old_data_sync_patch - run_old_data_sync_patch() - elif patch_no == 258: - sql("update tabDocField set `default`=NULL where fieldname = 'naming_series'") - elif patch_no == 259: - sql("update `tabQuotation Detail` set description = replace(description, 'http://46.4.50.84/v170-test/', '')") - sql("update `tabSales Order Detail` set description = replace(description, 'http://46.4.50.84/v170-test/', '')") - sql("update `tabRV Detail` set description = replace(description, 'http://46.4.50.84/v170-test/', '')") - sql("update `tabDelivery Note Detail` set description = replace(description, 'http://46.4.50.84/v170-test/', '')") - elif patch_no == 260: - sql("update `tabLetter Head` set content = replace(content, 'http://46.4.50.84/v170/', '')") - sql("update `tabSingles` set value = replace(value, 'http://46.4.50.84/v170/', '') where field in ('letter_head', 'client_name') and doctype = 'Control Panel'") - sql("update `tabItem` set description_html = replace(description_html, 'http://46.4.50.84/v170/', '')") - sql("update `tabQuotation Detail` set description = replace(description, 'http://46.4.50.84/v170/', '')") - sql("update `tabSales Order Detail` set description = replace(description, 'http://46.4.50.84/v170/', '')") - sql("update `tabRV Detail` set description = replace(description, 'http://46.4.50.84/v170/', '')") - sql("update `tabDelivery Note Detail` set description = replace(description, 'http://46.4.50.84/v170/', '')") - elif patch_no == 261: - sql("update `tabPrint Format` set html = replace(html, 'customer_address', 'address_display')") - elif patch_no == 262: - from patches.customer_address import sync_lead_phone - sync_lead_phone() - elif patch_no == 263: - ol = ['','Open','To Reply','Waiting for Customer','Hold','Closed'] - sql("update tabDocField set options=%s where parent=%s and fieldname=%s", ('\n'.join(ol), 'Support Ticket', 'status')) - elif patch_no == 264: - sql("delete from tabDocField where parent = 'Customer Issue' and (fieldname = 'issue_in' or fieldname = 'issue_category')") - sql("update tabDocField set options=NULL where parent='Support Ticket' and label = 'Send'") - elif patch_no == 266: - reload_doc('setup','doctype','support_email_settings') - elif patch_no == 267: - sql("update `tabPrint Format` set html = replace(html, 'supplier_address', 'address_display')") - elif patch_no == 268: - sql("update `tabDocPerm` set permlevel = 0 where permlevel is null") - elif patch_no == 269: - p = get_obj('Patch Util') - p.add_permission('GL Entry', 'Accounts User', 0, read = 1) - elif patch_no == 270: - pages = ['Accounts Setup', 'Accounts', 'Accounting Reports','GeneralLedger','How do I - Accounts','Making Opening Entries',\ - 'Analysis','How do I - CRM','How do I - Inventory','Inventory Setup', 'Stock','HR','HR & Payroll Setup',\ - 'Payroll Setup','Production Setup','Production','Buying','SRM Setup','Contact Page','Forum','Messages','Test Toolbar',\ - 'Trend Analyzer'] - from webnotes.model import delete_doc - sql("delete from `tabPage Visit`") - for p in pages: - try: delete_doc('Page', p) - except: pass - elif patch_no == 271: - # tags patch - reload_doc('crm','doctype','sales_order') - reload_doc('material_management','doctype','delivery_note') - sql("delete from tabDocField where fieldname='per_amt_billed' and parent in ('Sales Order', 'Delivery Note')") - - sql("""update `tabSales Order` set delivery_status = if(ifnull(per_delivered,0) < 0.001, 'Not Delivered', - if(per_delivered >= 99.99, 'Fully Delivered', 'Partly Delivered'))""") - sql("""update `tabSales Order` set billing_status = if(ifnull(per_billed,0) < 0.001, 'Not Billed', - if(per_billed >= 99.99, 'Fully Billed', 'Partly Billed'))""") - sql("""update `tabDelivery Note` set billing_status = if(ifnull(per_billed,0) < 0.001, 'Not Billed', - if(per_billed >= 99.99, 'Fully Billed', 'Partly Billed'))""") - elif patch_no == 272: - from webnotes.model import delete_doc - try: - delete_doc('Search Criteria', '_SRCH00003') - except: - pass - reload_doc('accounts', 'search_criteria', 'purchase_register') - elif patch_no == 276: - from webnotes.model import delete_doc - sn = sql("select name from `tabSearch Criteria` where criteria_name = 'Sales Personwise Transaction Summary'") - for d in sn: - delete_doc('Search Criteria', d[0]) - reload_doc('crm', 'search_criteria', 'sales_personwise_transaction_summary') - elif patch_no == 277: - webnotes.model.delete_doc('DocType','HomePage Settings') - webnotes.model.delete_doc('DocType','Badge Settings') - sql("update tabDocType set module='Home' where module in ('Event Updates', 'My Company')") - sql("update tabPage set module='Home' where module in ('Event Updates', 'My Company')") - sql("update `tabSearch Criteria` set module='Home' where module in ('Event Updates', 'My Company')") - - - delete_pages = ('Chat User Gallery', 'Badge Info', 'Home', 'Website Setup', 'Test Page', 'Setup Masters', 'Service', 'Selling', 'Sales Reports', 'Organize','My Cart', 'My Activity', 'Manage Users', 'Maintenance', 'Getting Started', 'Gantt Test', 'Custom Reports - Stock', 'Custom Reports - Selling', 'Custom Reports - Production', 'Custom Reports - Payroll', 'Custom Reports - Maintenance', 'Custom Reports - Buying', 'Custom Reports - Accounts', 'CRM Setup', 'CRM Reports') - for p in delete_pages: - webnotes.model.delete_doc('Page',p) - elif patch_no == 278: - sql("update tabDocTrigger set method = 'home.update_feed' where method = 'event_updates.update_feed'") - elif patch_no == 279: - dt = ['GL Entry', 'Stock Ledger Entry'] - for t in dt: - rec = sql("select voucher_type, voucher_no, ifnull(is_cancelled, 'No') from `tab%s` where modified >= '2011-06-15 01:00:00' group by voucher_no" % t) - for d in rec: - sql("update `tab%s` set docstatus = %s where name = '%s'" % (d[0], d[2]=='No' and 1 or 2, d[1])) - - other_dt = ['Enquiry', 'Quotation', 'Sales Order', 'Indent', 'Purchase Order', 'Production Order', 'Customer Issue', 'Installation Note'] - for dt in other_dt: - rec = sql("select name, status from `tab%s` where modified >= '2011-06-15 01:00:00'" % dt) - for r in rec: - sql("update `tab%s` set docstatus = %s where name = '%s'" % (dt, (r[1] in ['Submitted', 'Closed'] and 1 or r[1]=='Cancelled' and 2 or 0), r[0])) - elif patch_no == 280: - reload_doc('accounts', 'doctype', 'form_16a') - elif patch_no == 281: - dt_list = ['Delivery Note', 'Purchase Receipt'] - for dt in dt_list: - sql("update `tab%s` set status = 'Submitted' where docstatus = 1 and modified >='2011-06-15 01:00:00'" % dt) - sql("update `tab%s` set status = 'Cancelled' where docstatus = 2 and modified >='2011-06-15 01:00:00'" % dt) - elif patch_no == 282: - dt_list = ['Enquiry', 'Quotation', 'Sales Order', 'Indent', 'Purchase Order', 'Production Order', 'Customer Issue', 'Installation Note', 'Receivable Voucher', 'Payable Voucher', 'Delivery Note', 'Purchase Receipt', 'Journal Voucher', 'Stock Entry'] - for d in dt_list: - tbl = sql("select options from `tabDocField` where fieldtype = 'Table' and parent = '%s'" % d) - for t in tbl: - sql("update `tab%s` t1, `tab%s` t2 set t1.docstatus = t2.docstatus where t1.parent = t2.name" % (t[0], d)) - elif patch_no == 283: - rec = sql("select voucher_type, voucher_no, ifnull(is_cancelled, 'No') from `tabGL Entry` where modified >= '2011-06-15 01:00:00' order by name ASC") - for d in rec: - sql("update `tab%s` set docstatus = %s where name = '%s'" % (d[0], d[2]=='No' and 1 or 2, d[1])) - elif patch_no == 284: - reload_doc('maintenance', 'doctype', 'support_ticket') - sql("update `tabDocField` set in_filter = 1 where fieldname in ('raised_by', 'subject') and parent = 'Support Ticket'") - elif patch_no == 286: - reload_doc('accounts', 'search_criteria', 'itemwise_sales_register') - reload_doc('accounts', 'search_criteria', 'itemwise_purchase_register') - elif patch_no == 287: - sql("update `tabDocField` set no_copy = 1 where fieldname in ('per_received', 'per_billed', 'per_delivered') and parent in ('Purchase Order', 'Purchase Receipt', 'Sales Order', 'Delivery Note')") - elif patch_no == 288: - reload_doc('accounts', 'doctype', 'payable_voucher') - elif patch_no == 289: - sql("update `tabDocType` set subject = 'From %(supplier_name)s worth %(grand_total)s due on %(due_date)s | %(outstanding_amount)s outstanding' where name = 'Payable Voucher'") - sql("update `tabDocType` set search_fields = 'status,transaction_date,customer,lead,order_type' where name = 'Quotation'") - elif patch_no == 290: - count = sql("""SELECT * FROM `tabModule Def` - WHERE `module_name` LIKE 'Home'""") - if not count: - md = Document('Module Def') - md.module_name = 'Home' - md.module_label = 'Home' - md.save(1) - elif patch_no == 291: - reload_doc('tools','doctype','rename_tool') - elif patch_no == 292: - reload_doc('accounts', 'search_criteria', 'trial_balance') - elif patch_no == 293: - sql("delete from tabDocField where parent='Account' and fieldname='address'") - reload_doc('accounts', 'doctype', 'account') - elif patch_no == 294: - # new account profile fix - ul = sql("select name from tabProfile where ifnull(name,'') not in ('Administrator', 'Guest', '')") - # if one user and one user has no roles - if len(ul)==1 and not sql("select parent from tabUserRole where role='System Manager' and parent=%s", ul[0][0]): - get_obj('Setup Control').add_roles(Document('Profile', ul[0][0])) - elif patch_no == 295: - sql("update `tabDocField` set options = 'Delivered\nNot Delivered\nPartly Delivered\nClosed\nNot Applicable' where parent = 'Sales Order' and fieldname = 'delivery_status'") - sql("update `tabDocField` set options = 'Billed\nNot Billed\nPartly Billed\nClosed' where parent = 'Sales Order' and fieldname = 'billing_status'") - elif patch_no == 296: - sql("delete from tabDocField where parent='Support Ticket' and fieldname='contact_no'") - reload_doc('maintenance', 'doctype', 'support_ticket') - elif patch_no == 297: - reload_doc('payroll', 'doctype', 'employee') - reload_doc('payroll', 'doctype', 'attendance') - reload_doc('payroll', 'doctype', 'expense_voucher') - reload_doc('payroll', 'doctype', 'appraisal') - reload_doc('payroll', 'doctype', 'salary_structure') - reload_doc('payroll', 'doctype', 'salary_slip') - elif patch_no == 298: - sql("update `tabDocField` set options = 'link:Company' where parent = 'Attendance' and fieldname = 'company'") - sql("update `tabDocField` set options = 'link:Company' where parent = 'Expense Voucher' and fieldname = 'company'") - sql("update `tabDocField` set options = 'link:Company' where parent = 'Appraisal' and fieldname = 'company'") - elif patch_no == 299: - sql("update `tabDocPerm` set `match` = NULL where parent = 'Employee' and role = 'Employee'") - elif patch_no == 300: - sql("""DELETE FROM `tabSearch Criteria` WHERE name IN - ('sales_register1', 'sales_register2', 'purchase_register1')""") - elif patch_no == 301: + if patch_no == 301: from patches.delivery_billing_status_patch import run_patch run_patch() elif patch_no == 302: @@ -1212,7 +31,7 @@ def execute(patch_no): sql("update `tabDocField` set options = 'link:Item' where parent = 'Raw Materials Supplied' and fieldname = 'po_item'") sql("update `tabDocField` set options = 'Sales Order' where parent = 'Indent Detail' and fieldname = 'sales_order_no'") sql("update `tabDocField` set options = 'link:Company', fieldtype = 'Select' where parent = 'Stock Ledger Entry' and fieldname = 'company'") - reload_doc('tools', 'doctype', 'rename_tool') + reload_doc('utilities', 'doctype', 'rename_tool') elif patch_no == 307: sql("delete from `tabDocField` where parent = 'company' and label = 'Trash Company' and fieldtype = 'Button'") reload_doc('setup', 'doctype', 'company') @@ -1317,7 +136,6 @@ def execute(patch_no): webnotes.conn.get_value('Support Email Settings',None,field_map[key])) # delete support email settings - from webnotes.model import delete_doc delete_doc('DocType', 'Support Email Settings') reload_doc('support','doctype','support_ticket') @@ -1335,7 +153,7 @@ def execute(patch_no): reload_doc('accounts', 'search_criteria', 'lease_agreement_list') reload_doc('accounts', 'search_criteria', 'lease_monthly_future_installment_inflows') reload_doc('accounts', 'search_criteria', 'lease_overdue_age_wise') - reload_doc('accounts', 'search_criteria', 'lease_overdue_list') + reload_doc('accounts', 'search_criteria', 'lease_over_due_list') reload_doc('accounts', 'search_criteria', 'lease_receipts_client_wise') reload_doc('accounts', 'search_criteria', 'lease_receipt_summary_year_to_date') reload_doc('accounts', 'search_criteria', 'lease_yearly_future_installment_inflows') @@ -1348,3 +166,95 @@ def execute(patch_no): p.add_permission('Lease Agreement', 'Accounts Manager', 1, read = 1) elif patch_no == 332: sql("update `tabDocField` set permlevel=1, hidden = 1 where parent = 'Bulk Rename Tool' and fieldname = 'file_list'") + elif patch_no == 333: + sql("update `tabDocPerm` set `create` =1 where role = 'Accounts Manager' and parent = 'Lease Agreement'") + + p = get_obj('Patch Util') + p.add_permission('DocType Mapper', 'System Manager', 0, read = 1, write=1, create=1) + p.add_permission('Role', 'System Manager', 0, read = 1, write=1, create=1) + p.add_permission('Print Format', 'System Manager', 0, read = 1, write=1, create=1) + elif patch_no == 334: + reload_doc('knowledge_base', 'doctype', 'answer') + elif patch_no == 335: + for dt in ['Account', 'Cost Center', 'Territory', 'Item Group', 'Customer Group']: + sql("update `tabDocField` set fieldtype = 'Link', options = %s where fieldname = 'old_parent' and parent = %s", (dt, dt)) + elif patch_no == 336: + reload_doc('server_tools','page','billing') + elif patch_no == 337: + item_list = webnotes.conn.sql("""SELECT name, description_html + FROM tabItem""") + if item_list: + for item, html in item_list: + if html and "getfile" in html and "acx" in html: + ac_id = webnotes.conn.sql("""SELECT value FROM `tabSingles` WHERE doctype='Control Panel' AND field='account_id'""") + sp_acx = html.split("acx=") + l_acx = len(sp_acx) + if l_acx > 1: + for i in range(l_acx-1): + sp_quot = sp_acx[i+1].split('"') + if len(sp_quot) > 1: sp_quot[0] = str(ac_id[0][0]) + sp_acx[i+1] = '"'.join(sp_quot) + html = "acx=".join(sp_acx) + webnotes.conn.sql("""UPDATE tabItem SET description_html=%s WHERE name=%s""", (html, item)) + elif patch_no == 338: + # Patch for billing status based on amount + # reload so and dn + reload_doc('selling','doctype','sales_order') + reload_doc('stock','doctype','delivery_note') + + # delete billed_qty field + sql("delete from `tabDocField` where fieldname = 'billed_qty' and parent in ('Sales Order Detail', 'Delivery Note Detail')") + + # update billed amt in item table in so and dn + sql(""" update `tabSales Order Detail` so + set billed_amt = (select sum(amount) from `tabRV Detail` where `so_detail`= so.name and docstatus=1 and parent not like 'old%%'), modified = now()""") + + sql(""" update `tabDelivery Note Detail` dn + set billed_amt = (select sum(amount) from `tabRV Detail` where `dn_detail`= dn.name and docstatus=1 and parent not like 'old%%'), modified = now()""") + + # calculate % billed based on item table + sql(""" update `tabSales Order` so + set per_billed = (select sum(if(amount > ifnull(billed_amt, 0), billed_amt, amount))/sum(amount)*100 from `tabSales Order Detail` where parent = so.name), modified = now()""") + + sql(""" update `tabDelivery Note` dn + set per_billed = (select sum(if(amount > ifnull(billed_amt, 0), billed_amt, amount))/sum(amount)*100 from `tabDelivery Note Detail` where parent = dn.name), modified = now()""") + + # update billing status based on % billed + sql("""update `tabSales Order` set billing_status = if(ifnull(per_billed,0) < 0.001, 'Not Billed', + if(per_billed >= 99.99, 'Fully Billed', 'Partly Billed'))""") + sql("""update `tabDelivery Note` set billing_status = if(ifnull(per_billed,0) < 0.001, 'Not Billed', + if(per_billed >= 99.99, 'Fully Billed', 'Partly Billed'))""") + + # update name of questions page + sql("update tabPage set name='questions' where name='Questions'") + sql("update tabPage set name='question-view' where name='Question View'") + elif patch_no == 339: + reload_doc('production','doctype','bill_of_materials') + elif patch_no == 340: + sql("update `tabDocField` set permlevel = 0 where (fieldname in ('process', 'production_order', 'fg_completed_qty') or label = 'Get Items') and parent = 'Stock Entry'") + elif patch_no == 341: + reload_doc('stock','doctype','delivery_note') + reload_doc('stock','doctype','item') + reload_doc('selling','doctype','quotation') + reload_doc('stock','Print Format','Delivery Note Packing List Wise') + + if not sql("select format from `tabDocFormat` where name = 'Delivery Note Packing List Wise' and parent = 'Delivery Note'"): + from webnotes.model.doc import addchild + dt_obj = get_obj('DocType', 'Delivery Note', with_children = 1) + ch = addchild(dt_obj.doc, 'formats', 'DocFormat', 1) + ch.format = 'Delivery Note Packing List Wise' + ch.save(1) + elif patch_no == 342: + sql("update `tabDocField` set permlevel = 0 where parent = 'Stock Entry Detail' and fieldname in ('s_warehouse', 't_warehouse', 'fg_item')") + elif patch_no == 343: + reload_doc('stock','doctype','item_customer_detail') + elif patch_no == 344: + sql("delete from `tabDocFormat` where ifnull(format, '') = '' and parent = 'Delivery Note'") + elif patch_no == 345: + sql("delete from `tabModule Def Item` where display_name = 'Salary Slip Control Panel' and parent = 'HR'") + reload_doc('hr','Module Def','HR') + elif patch_no == 346: + delete_doc('DocType', 'Profile') + reload_doc('core', 'doctype', 'profile') + + diff --git a/production/doctype/bill_of_materials/bill_of_materials.js b/production/doctype/bill_of_materials/bill_of_materials.js index ede959f2c39..d458d27cc48 100644 --- a/production/doctype/bill_of_materials/bill_of_materials.js +++ b/production/doctype/bill_of_materials/bill_of_materials.js @@ -1,20 +1,22 @@ -$import(Production Tips Common) +//$import(Production Tips Common) // ONLOAD cur_frm.cscript.onload = function(doc,cdt,cdn){ - + } // On REFRESH cur_frm.cscript.refresh = function(doc,cdt,cdn){ - + // Hide - Un Hide Buttons if (!doc.is_default && doc.__islocal!=1) unhide_field('Set as Default BOM'); else hide_field('Set as Default BOM'); - + if (doc.is_default && doc.__islocal!=1) unhide_field('Unset as Default BOM'); + else hide_field('Unset as Default BOM'); + if(doc.__islocal!=1){ set_field_permlevel('item',1); } @@ -76,9 +78,20 @@ cur_frm.cscript['Set as Default BOM'] = function(doc,cdt,cdn) { if (check) { $c('runserverobj', args={'method':'set_as_default_bom', 'docs': compress_doclist([doc])}, function(r,rt) { refresh_field('is_default'); - hide_field('Set as Default BOM'); + hide_field('Set as Default BOM');unhide_field('Unset as Default BOM'); refresh_field('Set as Default BOM'); - }); + }); + } +} + +cur_frm.cscript['Unset as Default BOM'] = function(doc,cdt,cdn) { + var check = confirm("Do you Really want to Unset BOM " + doc.name + " as default for Item " + doc.item); + if (check) { + $c('runserverobj', args={'method':'unset_as_default_bom', 'docs': compress_doclist([doc])}, function(r,rt) { + refresh_field('is_default'); + hide_field('Unset as Default BOM');unhide_field('Set as Default BOM'); + refresh_field('Unset as Default BOM'); + }); } } @@ -88,16 +101,23 @@ cur_frm.cscript['Activate BOM'] = function(doc,cdt,cdn) { if (check) { $c('runserverobj', args={'method':'activate_inactivate_bom', 'arg': 'Activate', 'docs': compress_doclist(make_doclist(doc.doctype, doc.name))}, function(r,rt) { cur_frm.refresh(); - }); + }); } } +cur_frm.cscript['Test Flat BOM'] = function(doc,cdt,cdn) { + + $c('runserverobj', args={'method':'get_current_flat_bom_items', 'docs': compress_doclist(make_doclist(doc.doctype, doc.name))}, function(r,rt) { + cur_frm.refresh(); + }); +} + cur_frm.cscript['Inactivate BOM'] = function(doc,cdt,cdn) { var check = confirm("DO YOU REALLY WANT TO INACTIVATE BOM : " + doc.name); if (check) { $c('runserverobj', args={'method':'activate_inactivate_bom', 'arg': 'Inactivate', 'docs': compress_doclist(make_doclist(doc.doctype, doc.name))}, function(r,rt) { cur_frm.refresh(); - }); + }); } } \ No newline at end of file diff --git a/production/doctype/bill_of_materials/bill_of_materials.py b/production/doctype/bill_of_materials/bill_of_materials.py index f8f8e30c4a2..d287d2f9d57 100644 --- a/production/doctype/bill_of_materials/bill_of_materials.py +++ b/production/doctype/bill_of_materials/bill_of_materials.py @@ -13,7 +13,7 @@ sql = webnotes.conn.sql get_value = webnotes.conn.get_value in_transaction = webnotes.conn.in_transaction convert_to_lists = webnotes.conn.convert_to_lists - + # ----------------------------------------------------------------------------------------- @@ -21,14 +21,14 @@ class DocType: def __init__(self, doc, doclist=[]): self.doc = doc self.doclist = doclist - + def autoname(self): last_name = sql("select max(name) from `tabBill Of Materials` where name like 'BOM/%s/%%'" % self.doc.item) if last_name: idx = cint(cstr(last_name[0][0]).split('/')[-1]) + 1 else: idx = 1 - self.doc.name = 'BOM/' + self.doc.item + ('/%.3i' % idx) + self.doc.name = 'BOM/' + self.doc.item + ('/%.3i' % idx) #----------- Client Trigger function ---------- def get_item_detail(self, item_code): @@ -36,7 +36,7 @@ class DocType: ret={ 'description' : item and item[0]['description'] or '' } - return cstr(ret) + return ret def get_workstation_details(self,workstation): ws = sql("select hour_rate, capacity from `tabWorkstation` where name = %s",workstation , as_dict = 1) @@ -44,7 +44,7 @@ class DocType: 'hour_rate' : ws and flt(ws[0]['hour_rate']) or '', 'workstation_capacity' : ws and flt(ws[0]['capacity']) or '' } - return cstr(ret) + return ret def get_bom_material_detail(self, arg): arg = eval(arg) @@ -53,15 +53,15 @@ class DocType: raise Exception if arg['item_code']: item = sql("select is_asset_item, is_purchase_item, docstatus, is_sub_contracted_item, description, stock_uom, default_bom from `tabItem` where item_code = %s", (arg['item_code']), as_dict = 1) - + # Check for Asset Item if item and item[0]['is_asset_item'] == 'Yes': msgprint("Sorry!!! Item " + arg['item_code'] + " is an Asset of the company. Entered in BOM := " + cstr(self.doc.name)) raise Exception - + if item and item[0]['docstatus'] == 2: msgprint("Item %s does not exist in system" % cstr(args['item_code'])) - + ret_item = { 'description' : item and item[0]['description'] or '', 'stock_uom' : item and item[0]['stock_uom'] or '', @@ -78,15 +78,15 @@ class DocType: if arg['bom_no'] or not ret_item['bom_no'] =='': if arg['bom_no']: bom = sql("select name, dir_mat_as_per_mar,dir_mat_as_per_lpr,dir_mat_as_per_sr, operating_cost, quantity from `tabBill Of Materials` where is_active = 'Yes' and name = %s", (arg['bom_no']), as_dict=1) - else: - # get recent direct material cost, operating_cost, cost from Default BOM of Item + else: + # get recent direct material cost, operating_cost, cost from Default BOM of Item bom = sql("select name, dir_mat_as_per_mar, dir_mat_as_per_lpr, dir_mat_as_per_sr, operating_cost, quantity from `tabBill Of Materials` where is_active = 'Yes' and name = %s", (ret_item['bom_no']), as_dict=1) - - # get recent direct material cost, operating_cost, cost from Entered BOM of Item + + # get recent direct material cost, operating_cost, cost from Entered BOM of Item ret_item['bom_no'] = bom and bom[0]['name'] or '' if bom and bom[0]['name']: - ret_bom = { + ret_bom = { 'dir_mat_as_per_mar' : flt(bom[0]['dir_mat_as_per_mar']) / flt(bom[0]['quantity']) or 0.00, 'dir_mat_as_per_lpr' : flt(bom[0]['dir_mat_as_per_lpr']) / flt(bom[0]['quantity']) or 0.00, 'dir_mat_as_per_sr' : flt(bom[0]['dir_mat_as_per_sr']) / flt(bom[0]['quantity']) or 0.00, @@ -106,15 +106,15 @@ class DocType: 'standard_rate' : 0 } ret_item.update(ret_bom_rates) - return cstr(ret_item) - + return ret_item + def set_as_default_bom(self): # set Is Default as 1 set(self.doc,'is_default', flt(1)) # get previous default bom from Item Master prev_def_bom = sql("select default_bom from `tabItem` where name = %s", self.doc.item,as_dict = 1) - + if prev_def_bom[0]['default_bom'] and prev_def_bom[0]['default_bom'] != self.doc.name: # update Is Default as 0 in Previous Default BOM msgprint(cstr(prev_def_bom[0]['default_bom']) + "is no longer Default BOM for item" + cstr(self.doc.item)) @@ -124,12 +124,20 @@ class DocType: sql("update `tabItem` set default_bom = '%s' where name = '%s'" % (self.doc.name,self.doc.item)) msgprint(cstr(self.doc.name) + "has been set as Default BOM for Item "+cstr(self.doc.item)) + def unset_as_default_bom(self): + # set Is Default as 1 + set(self.doc,'is_default', flt(0)) + + # update current BOM as default bom in Item Master + sql("update `tabItem` set default_bom = null where name = '%s'" % (self.doc.item)) + msgprint(cstr(self.doc.name) + "has been unset as Default BOM for Item "+cstr(self.doc.item)) + def check_active_parent_boms(self): act_pbom = sql("select distinct t1.parent from `tabBOM Material` t1, `tabBill Of Materials` t2 where t1.bom_no ='%s' and t2.name = t1.parent and t2.is_active = 'Yes' and t2.docstatus = 1 and t1.docstatus =1 " % self.doc.name ) if act_pbom and act_pbom[0][0]: msgprint("Sorry cannot Inactivate as BOM %s is child of one or many other active parent BOMs" % self.doc.name) raise Exception - + def activate_inactivate_bom(self, action): if cstr(action) == 'Activate': self.validate() @@ -141,11 +149,11 @@ class DocType: #------ On Validation Of Document ---------- def validate_main_item(self): item = sql("select is_manufactured_item, is_sub_contracted_item from `tabItem` where name = %s and (ifnull(end_of_life,'')='' or end_of_life = '0000-00-00' or end_of_life > now())", self.doc.item, as_dict = 1) - + if not item: msgprint("Item %s do not exists in the system. Entered in BOM := %s" % (cstr(self.doc.item), cstr(self.doc.name))) raise Exception - + elif not item[0]['is_manufactured_item'] == 'Yes' and not item[0]['is_sub_contracted_item'] == 'Yes': msgprint("Sorry cannot make Bill Of Materials for Item %s. As it is not a manufactured / sub-contracted item. Entered in BOM := %s " % (cstr(self.doc.item), cstr(self.doc.name))) raise Exception @@ -156,7 +164,7 @@ class DocType: if not o.operation_no: msgprint("Please Enter Operation No at Row " + cstr(o.idx)+" in BOM := " +cstr(self.doc.name)) raise Exception - + if not o.workstation: msgprint("Please Enter Workstation for Operation No. " + cstr(o.operation_no) + " in BOM NO. " + self.doc.name) raise Exception @@ -172,7 +180,7 @@ class DocType: # add operation in op list self.op.append(cstr(o.operation_no)) - + # Validate materials #------------------------------------------------- @@ -196,7 +204,7 @@ class DocType: if not item: msgprint("Item %s is not present in Item Master." % m.item_code) raise Exception - + if item[0]['is_manufactured_item'] == 'Yes' or item[0]['is_sub_contracted_item'] == 'Yes': bom = sql("select name, is_active, docstatus from `tabBill Of Materials` where item = %s", m.item_code, as_dict =1) if bom and bom[0]['name']: @@ -209,17 +217,17 @@ class DocType: if cstr(m.bom_no) == cstr(b['name']): if b['is_active'] != 'Yes': msgprint("BOM %s NOT ACTIVE BOM. Entered in BOM := %s at row no := %s" % (cstr(m.bom_no), cstr(self.doc.name), m.idx)) - raise Exception - + raise Exception + #if flt(b['docstatus']) != 1: # msgprint("BOM %s is NOT SUBMITTED."% cstr(m.bom_no)) # raise Exception - + match = 1 if not match: msgprint("Item %s does not belongs to Bill Of Material %s or Bill Of Material %s is NOT ACTIVE BOM. Entered in BOM := %s at row no := %s" % (cstr(m.item_code),cstr(m.bom_no), cstr(m.bom_no), self.doc.name, m.idx)) raise Exception - + if not item[0]['is_manufactured_item'] == 'Yes' and not item[0]['is_sub_contracted_item']== 'Yes': if m.bom_no: msgprint("As in Item Master of Item %s Is Manufactured Item / Is Sub-Contracted Item is not 'Yes' hence there should be no BOM.In BOm := %s at row no := %s" % (m.item_code, cstr(self.doc.name), m.idx)) @@ -235,22 +243,23 @@ class DocType: # Calculate Cost #----------------------------------------------- - + def calculate_cost(self, validate = 0): self.op, op_cost, dir_mat_as_per_mar, dir_mat_as_per_lpr, dir_mat_as_per_sr, count_mat = [], 0.0, 0.0,0.0,0.0, 0 # -------- Calculate Cost Of BOM ------------- # --- calculate operating cost from BOM Operations ---- for o in getlist(self.doclist, 'bom_operations'): - # --- Validation for enteries in BOM Operations ---- + # --- Validation for enteries in BOM Operations ---- if validate: self.validate_operations(o) - + o.operating_cost = flt(flt(o.time_in_mins)/60) * flt(o.hour_rate) if validate != 1: o.save() + msgprint('Operation saved') op_cost = flt(op_cost) + flt(o.operating_cost) - + # --- calculate operating cost and direct material cost from BOM Material --- for m in getlist(self.doclist, 'bom_materials'): # --- Validation for enteries in BOM Material --- ''' @@ -259,12 +268,12 @@ class DocType: self.validate_materials(m) if m.bom_no: - # add operating cost of child boms + # add operating cost of child boms op_cost += flt(m.operating_cost) - + # update dir_mat, op_cost, value from child bom self.update_childs_dir_op_value(m, child_bom_cost = 1) - + # check for is_sub_contracted_item item = sql("select is_sub_contracted_item from `tabItem` where name = '%s'" % m.item_code, as_dict =1) if item and item[0]['is_sub_contracted_item'] == 'Yes': @@ -275,13 +284,13 @@ class DocType: # calculate Direct Material dir_mat_as_per_mar, dir_mat_as_per_lpr, dir_mat_as_per_sr = self.calculate_dir_mat(m, dir_mat_as_per_mar, dir_mat_as_per_lpr, dir_mat_as_per_sr, has_bom = 1, is_sub_cont =1) else: - # update mar,lpr,sr as 0 + # update mar,lpr,sr as 0 self.update_mar_lpr_sr( m, mar = 0, lpr = 0, sr = 0) # calculate amount self.calculate_amount( m, has_bom = 1, is_sub_cont = 0) # calculate Direct Material dir_mat_as_per_mar, dir_mat_as_per_lpr, dir_mat_as_per_sr = self.calculate_dir_mat(m, dir_mat_as_per_mar, dir_mat_as_per_lpr, dir_mat_as_per_sr, has_bom = 1, is_sub_cont =0) - + else : # update dir_mat,op_cost, value as 0 self.update_childs_dir_op_value(m, child_bom_cost = 0) @@ -291,7 +300,7 @@ class DocType: self.calculate_amount(m, has_bom = 0, is_sub_cont = 0) # calculate Direct Material dir_mat_as_per_mar, dir_mat_as_per_lpr, dir_mat_as_per_sr = self.calculate_dir_mat(m, dir_mat_as_per_mar, dir_mat_as_per_lpr, dir_mat_as_per_sr, has_bom =0, is_sub_cont =0) - + # update qty_consumed_per_unit m.qty_consumed_per_unit = flt(m.qty) / flt(self.doc.quantity) m.save() @@ -314,12 +323,12 @@ class DocType: def update_childs_dir_op_value(self, m, child_bom_cost = 0): #msgprint("IN UPDATE CHILDS DIR OP VALUE") if child_bom_cost: - # get recent direct material cost, operating cost, cost from child bom + # get recent direct material cost, operating cost, cost from child bom child_bom_cost = sql("select dir_mat_as_per_mar, dir_mat_as_per_lpr, dir_mat_as_per_sr, operating_cost, cost_as_per_mar, cost_as_per_lpr, cost_as_per_sr, quantity from `tabBill Of Materials` where name = %s", m.bom_no, as_dict = 1) - + # operating_cost m.operating_cost = child_bom_cost and flt(child_bom_cost[0]['operating_cost']) / flt(child_bom_cost[0]['quantity']) or 0.00 - + val_dir_dict = {'value_as_per_mar': 'cost_as_per_mar', 'dir_mat_as_per_mar': 'dir_mat_as_per_mar', 'value_as_per_lpr': 'cost_as_per_lpr', 'dir_mat_as_per_lpr': 'dir_mat_as_per_lpr', 'value_as_per_sr' : 'cost_as_per_sr' , 'dir_mat_as_per_sr' : 'dir_mat_as_per_sr' } @@ -353,7 +362,7 @@ class DocType: dir_mat_as_per_mar += flt(m.amount_as_per_mar) dir_mat_as_per_lpr += flt(m.amount_as_per_lpr) dir_mat_as_per_sr += flt(m.amount_as_per_sr) - #msgprint(cstr(m.item_code)) + #msgprint(cstr(m.item_code)) #msgprint("dir_mat_as_per_mar < ==> " + cstr(dir_mat_as_per_mar) + "***" + "dir_mat_as_per_lpr < ==> " + cstr(dir_mat_as_per_lpr) + "***" + "dir_mat_as_per_sr < ==> " + cstr(dir_mat_as_per_sr) + "***") return dir_mat_as_per_mar, dir_mat_as_per_lpr, dir_mat_as_per_sr @@ -367,9 +376,9 @@ class DocType: while withdraw: if not fcfs_bal: break # nothing in store - + batch = fcfs_bal[0] - + if batch[0] < withdraw: # not enough in current batch, clear batch withdraw -= batch[0] @@ -424,8 +433,8 @@ class DocType: #ma_rate = sql("select ifnull(sum(ma_rate), 0)/ ifnull(count(*),1) from `tabBin` where item_code = '%s' and ifnull(ma_rate, 0) > 0" % cstr(item_code)) #ma_rate = flt(ma_rate and ma_rate[0][0]) or 0 ma_rate = self.get_valuation_rate(item_code, qty) - - # get recent last purchase rate + + # get recent last purchase rate lpr_rate = lpr and flt(sql("select last_purchase_rate from `tabItem` where name = '%s'" % item_code)[0][0]) or 0.00 # get recent standard rate sr_rate = sr and flt(sql("select standard_rate from `tabItem` where name = '%s'" % item_code)[0][0]) or 0.00 @@ -440,13 +449,14 @@ class DocType: raise Exception else: check_list.append(cstr(d.item_code)) - - #----- Document on Save function------ + + #----- Document on Save function------ def validate(self): + #msgprint(len(getlist(self.doclist, 'bom_materials'))) self.validate_main_item() self.validate_duplicate_items() self.calculate_cost(validate = 1) - + def check_recursion(self): check_list = [['parent', 'bom_no', 'parent'], ['bom_no', 'parent', 'child']] for d in check_list: @@ -466,10 +476,10 @@ class DocType: msgprint("Cannot change Item once the Bill Of Material is created.") raise Exception self.check_recursion() - + # ********************************************** Submit ************************************************************* - + # Add Flat BOM Details # ----------------------- def add_to_flat_bom_detail(self, is_submit = 0): @@ -486,9 +496,11 @@ class DocType: #Get Child Flat BOM Items #---------------------------------------- - def get_child_flat_bom_items(self, item, d): + def get_child_flat_bom_items(self, item, d): + child_flat_bom_items=[] if item and (item[0]['is_sub_contracted_item'] == 'Yes' or item[0]['is_pro_applicable'] == 'Yes'): + child_flat_bom_items = sql("select item_code, description, qty_consumed_per_unit, stock_uom, moving_avg_rate, last_purchase_rate, standard_rate, '%s' as parent_bom, bom_mat_no, 'No' as is_pro_applicable from `tabFlat BOM Detail` where parent = '%s' and is_pro_applicable = 'No' and docstatus = 1" % ( d.bom_no, cstr(d.bom_no))) self.cur_flat_bom_items.append([d.item_code, d.description, flt(d.qty), d.stock_uom, flt(d.moving_avg_rate), flt(d.amount_as_per_mar), flt(d.last_purchase_rate), flt(d.amount_as_per_lpr), flt(d.standard_rate), flt(d.amount_as_per_sr), flt(d.qty_consumed_per_unit), (item[0]['is_sub_contracted_item'] == 'Yes') and d.parent or d.bom_no, d.name, (item[0]['is_sub_contracted_item'] == 'Yes') and 'No' or 'Yes']) @@ -500,20 +512,22 @@ class DocType: raise Exception else: return child_flat_bom_items - - + + # Get Current Flat BOM Items # ----------------------------- def get_current_flat_bom_items(self): + self.cur_flat_bom_items = [] - + cfb_lbl = {'item_code': 0, 'description': 1, 'qty_consumed_per_unit': 2, 'stock_uom': 3, 'moving_avg_rate': 4, 'last_purchase_rate': 5, 'standard_rate': 6, 'parent_bom': 7, 'bom_mat_no': 8, 'is_pro_applicable': 9} - - for d in getlist(self.doclist, 'bom_materials'): + + for d in getlist(self.doclist, 'bom_materials'): + if d.bom_no: item = sql("select is_sub_contracted_item, is_pro_applicable from `tabItem` where name = '%s'" % d.item_code, as_dict = 1) child_flat_bom_items = self.get_child_flat_bom_items(item,d) - + for c in child_flat_bom_items: self.cur_flat_bom_items.append([c[cfb_lbl['item_code']], c[cfb_lbl['description']], flt(d.qty) * flt(c[cfb_lbl['qty_consumed_per_unit']]), c[cfb_lbl['stock_uom']], flt(c[cfb_lbl['moving_avg_rate']]), flt(d.qty) * flt(c[cfb_lbl['qty_consumed_per_unit']]) * flt(c[cfb_lbl['moving_avg_rate']]) ,flt(c[cfb_lbl['last_purchase_rate']]), flt(d.qty) * flt(c[cfb_lbl['qty_consumed_per_unit']]) * flt(c[cfb_lbl['last_purchase_rate']]), flt(c[cfb_lbl['standard_rate']]), flt(d.qty) * flt(c[cfb_lbl['qty_consumed_per_unit']]) * flt(c[cfb_lbl['standard_rate']]), flt(d.qty_consumed_per_unit) * flt(c[cfb_lbl['qty_consumed_per_unit']]), c[cfb_lbl['parent_bom']], c[cfb_lbl['bom_mat_no']], c[cfb_lbl['is_pro_applicable']]]) else: @@ -521,10 +535,10 @@ class DocType: self.cur_flat_bom_items.append([d.item_code, d.description, flt(d.qty), d.stock_uom, flt(d.moving_avg_rate), flt(d.amount_as_per_mar), flt(d.last_purchase_rate), flt(d.amount_as_per_lpr), flt(d.standard_rate), flt(d.amount_as_per_sr), flt(d.qty_consumed_per_unit), d.parent, d.name, 'No' ]) # Update Flat BOM Engine - # ------------------------ + # ------------------------ def update_flat_bom_engine(self, is_submit = 0): # following will be correct data - # get correct / updated flat bom data + # get correct / updated flat bom data self.get_current_flat_bom_items() # insert to curr flat bom data self.add_to_flat_bom_detail(is_submit) @@ -533,9 +547,9 @@ class DocType: # On Submit # ----------- def on_submit(self): - self.update_flat_bom_engine() + self.update_flat_bom_engine(1) + - def get_parent_bom_list(self, bom_no): p_bom = sql("select parent from `tabBOM Material` where bom_no = '%s'" % bom_no) return p_bom and [i[0] for i in p_bom] or [] diff --git a/production/doctype/bill_of_materials/bill_of_materials.txt b/production/doctype/bill_of_materials/bill_of_materials.txt index 37d8b69491b..259081793dc 100644 --- a/production/doctype/bill_of_materials/bill_of_materials.txt +++ b/production/doctype/bill_of_materials/bill_of_materials.txt @@ -34,7 +34,7 @@ 'section_style': 'Tabbed', 'server_code_error': ' ', 'show_in_menu': 0, - 'subject': '%(item_code)s', + 'subject': '%(item)s', 'version': 170 }, diff --git a/production/doctype/bom_control/bom_control.py b/production/doctype/bom_control/bom_control.py index 02b61e316e7..6b0987bafe9 100644 --- a/production/doctype/bom_control/bom_control.py +++ b/production/doctype/bom_control/bom_control.py @@ -1,7 +1,7 @@ # Please edit this list and import only required elements import webnotes -from webnotes.utils import add_days, add_months, add_years, cint, cstr, date_diff, default_fields, flt, fmt_money, formatdate, generate_hash, getTraceback, get_defaults, get_first_day, get_last_day, getdate, has_common, month_name, now, nowdate, replace_newlines, sendmail, set_default, str_esc_quote, user_format, validate_email_add +from webnotes.utils import cint, flt from webnotes.model import db_exists from webnotes.model.doc import Document, addchild, removechild, getchildren, make_autoname, SuperDocType from webnotes.model.doclist import getlist, copy_doclist @@ -13,7 +13,7 @@ sql = webnotes.conn.sql get_value = webnotes.conn.get_value in_transaction = webnotes.conn.in_transaction convert_to_lists = webnotes.conn.convert_to_lists - + # ----------------------------------------------------------------------------------------- @@ -32,7 +32,7 @@ class DocType: return '~~~'.join([r for r in item_group]) def get_item_code(self,item_group): - # here Bill Of Materials docstatus = 1 and is_active ='yes' condition is not given because some bom is under construction + # here Bill Of Materials docstatus = 1 and is_active ='yes' condition is not given because some bom is under construction # that is it is still in saved mode and they want see till where they have reach. ret = sql("select distinct t1.name from `tabItem` t1, `tabBill Of Materials` t2 where t2.item = t1.name and t1.item_group = '%s' " % (item_group)) return '~~~'.join([r[0] for r in ret]) @@ -44,18 +44,20 @@ class DocType: def get_operations(self,bom_no): # reply = [ 'Operation',operation_no, opn_description,BOM NO , workstation, hour_rate, time_in_minutes, Total Direct Material, Total Operating Cost, Cost] # reply = [ 0 , 1 , 2 ,3 , 4 , 5 , 6 , 7 , 8 ,9 , 10 , 11 ] - ret = sql("select operation_no,opn_description,workstation,hour_rate,time_in_mins from `tabBOM Operation` where parent = %s", bom_no, as_dict = 1) cost = sql("select dir_mat_as_per_mar , operating_cost , cost_as_per_mar from `tabBill Of Materials` where name = %s", bom_no, as_dict = 1) + # Validate the BOM ENTRIES #check = get_obj('Bill Of Materials', bom_no, with_children =1).validate() reply = [] - for r in ret: - reply.append(['operation',cint(r['operation_no']), r['opn_description'] or '','%s'% bom_no,r['workstation'],flt(r['hour_rate']),flt(r['time_in_mins']),0,0,0]) - reply[0][7]= flt(cost[0]['dir_mat_as_per_mar']) - reply[0][8]=flt(cost[0]['operating_cost']) - reply[0][9]=flt(cost[0]['cost_as_per_mar']) - #msgprint(bom_no) + + if ret: + for r in ret: + reply.append(['operation',cint(r['operation_no']), r['opn_description'] or '','%s'% bom_no,r['workstation'],flt(r['hour_rate']),flt(r['time_in_mins']),0,0,0]) + + reply[0][7]= flt(cost[0]['dir_mat_as_per_mar']) + reply[0][8]=flt(cost[0]['operating_cost']) + reply[0][9]=flt(cost[0]['cost_as_per_mar']) return reply def get_item_bom(self,data): @@ -64,7 +66,7 @@ class DocType: data = eval(data) reply = [] ret = sql("select item_code,description,bom_no,qty,scrap,stock_uom,value_as_per_mar,moving_avg_rate from `tabBOM Material` where parent = '%s' and operation_no = '%s'" % (data['bom_no'],data['op_no']), as_dict =1 ) - + for r in ret: item = sql("select is_manufactured_item, is_sub_contracted_item from `tabItem` where name = '%s'" % r['item_code'], as_dict=1) if not item[0]['is_manufactured_item'] == 'Yes' and not item[0]['is_sub_contracted_item'] =='Yes': @@ -78,9 +80,8 @@ class DocType: return reply - - #------------- Wrapper Code -------------- - # BOM TREE + #------------- Wrapper Code -------------- + # BOM TREE def calculate_cost( self, bom_no): main_bom_list = get_obj(dt = 'Production Control').traverse_bom_tree( bom_no = bom_no, qty = 1, calculate_cost = 1) main_bom_list.reverse() @@ -89,13 +90,13 @@ class DocType: bom_obj.calculate_cost(validate = 0) bom_obj.doc.save() return 'calculated' - + def get_bom_tree_list(self,args): arg = eval(args) i =[] for a in sql("select t1.name from `tabBill Of Materials` t1, `tabItem` t2 where t2.item_group like '%s' and t1.item like '%s'"%(arg['item_group'] +'%',arg['item_code'] + '%')): if a[0] not in i: - i.append(a[0]) + i.append(a[0]) return i # return [s[0] for s in sql("select t1.name from `tabBill Of Materials` t1, `tabItem` t2 where t2.item_group like '%s' and t1.item like '%s' " %(arg['item_group']+'%',arg['item_code'+'%'])] \ No newline at end of file diff --git a/production/doctype/production_order/production_order.py b/production/doctype/production_order/production_order.py index ce8f0828bb8..570c8026661 100644 --- a/production/doctype/production_order/production_order.py +++ b/production/doctype/production_order/production_order.py @@ -34,7 +34,7 @@ class DocType: 'stock_uom' : item and item[0]['stock_uom'] or '', 'default_bom' : item and item[0]['default_bom'] or '' } - return cstr(ret) + return ret def validate(self): if not self.doc.production_item : diff --git a/production/doctype/production_planning_tool/production_planning_tool.py b/production/doctype/production_planning_tool/production_planning_tool.py index c548173e21a..d0ae05b2f8a 100644 --- a/production/doctype/production_planning_tool/production_planning_tool.py +++ b/production/doctype/production_planning_tool/production_planning_tool.py @@ -32,7 +32,7 @@ class DocType: 'stock_uom' : item and item[0]['stock_uom'], 'bom_no' : item and item[0]['default_bom'] } - return cstr(ret) + return ret else: msgprint("Item %s does not exist in system." %(args['item_code'])) raise Exception diff --git a/production/doctype/workstation/workstation.py b/production/doctype/workstation/workstation.py index aaa490837f4..45851de3e29 100644 --- a/production/doctype/workstation/workstation.py +++ b/production/doctype/workstation/workstation.py @@ -25,7 +25,7 @@ class DocType: def update_bom_operation(self): bom_list = sql(" select DISTINCT parent from `tabBOM Operation` where workstation = '%s'" % self.doc.name) for bom_no in bom_list: - sql("update `tabBOM Operation` set hour_rate = '%s' where parent = '%s' and workstation = '%s'"%( self.doc.hour_rate, bom_no, self.doc.name)) + sql("update `tabBOM Operation` set hour_rate = '%s' where parent = '%s' and workstation = '%s'"%( self.doc.hour_rate, bom_no[0], self.doc.name)) def on_update(self): set(self.doc, 'overhead', flt(self.doc.hour_rate_electricity) + flt(self.doc.hour_rate_consumable) + flt(self.doc.hour_rate_rent)) diff --git a/projects/doctype/project/project.py b/projects/doctype/project/project.py index e68771ce6a5..9930bf42131 100644 --- a/projects/doctype/project/project.py +++ b/projects/doctype/project/project.py @@ -38,7 +38,7 @@ class DocType: ret['contact_person'] = contact_det and contact_det[0]['contact_name'] or '' ret['contact_no'] = contact_det and contact_det[0]['contact_no'] or '' ret['email_id'] = contact_det and contact_det[0]['email_id'] or '' - return cstr(ret) + return ret else: msgprint("Customer : %s does not exist in system." % (self.doc.customer)) raise Exception @@ -52,7 +52,7 @@ class DocType: 'contact_no' : contact and contact[0]['contact_no'] or '', 'email_id' : contact and contact[0]['email_id'] or '' } - return str(ret) + return ret else: msgprint("Contact Person : %s does not exist in the system." % (self.doc,contact_person)) raise Exception @@ -65,7 +65,7 @@ class DocType: #if pft > 0: per_pft = (flt(pft) / flt(self.doc.project_value)) * 100 ret = {'gross_margin_value': pft, 'per_gross_margin': per_pft} - return cstr(ret) + return ret # validate #================================================ diff --git a/projects/doctype/ticket/ticket.py b/projects/doctype/ticket/ticket.py index 8d716cc1cd7..0f18b21e753 100644 --- a/projects/doctype/ticket/ticket.py +++ b/projects/doctype/ticket/ticket.py @@ -22,18 +22,18 @@ class DocType: cust = sql("select customer, customer_name from `tabProject` where name = %s", self.doc.project) if cust: ret = {'customer': cust and cust[0][0] or '', 'customer_name': cust and cust[0][1] or ''} - return cstr(ret) + return ret def get_customer_details(self): cust = sql("select customer_name from `tabCustomer` where name=%s", self.doc.customer) if cust: ret = {'customer_name': cust and cust[0][0] or ''} - return cstr(ret) + return ret def get_allocated_to_name(self): as_em = sql("select first_name, last_name from `tabProfile` where name=%s",self.doc.allocated_to) ret = { 'allocated_to_name' : as_em and (as_em[0][0] + ' ' + as_em[0][1]) or ''} - return cstr(ret) + return ret # validate #-------------------------------------------- diff --git a/projects/doctype/timesheet/timesheet.py b/projects/doctype/timesheet/timesheet.py index ba921f478a7..f07975c8197 100644 --- a/projects/doctype/timesheet/timesheet.py +++ b/projects/doctype/timesheet/timesheet.py @@ -32,7 +32,7 @@ class DocType: tsk = sql("select name, project, customer, customer_name from `tabTicket` where subject = %s", task_sub) if tsk: ret = {'task_id': tsk and tsk[0][0] or '', 'project_name': tsk and tsk[0][1] or '', 'customer_name': tsk and tsk[0][3] or ''} - return cstr(ret) + return ret def validate(self): if getdate(self.doc.timesheet_date) > getdate(nowdate()): diff --git a/selling/doctype/enquiry/enquiry.py b/selling/doctype/enquiry/enquiry.py index 61bc4ec07d9..12597022bd3 100644 --- a/selling/doctype/enquiry/enquiry.py +++ b/selling/doctype/enquiry/enquiry.py @@ -50,7 +50,7 @@ class DocType(TransactionBase): ret['contact_no'] = contact_det and contact_det[0]['contact_no'] or '' ret['email_id'] = contact_det and contact_det[0]['email_id'] or '' - return cstr(ret) + return ret else: msgprint("Customer : %s does not exist in system." % (name)) raise Exception @@ -64,7 +64,7 @@ class DocType(TransactionBase): 'contact_no' : contact and contact[0]['contact_no'] or '', 'email_id' : contact and contact[0]['email_id'] or '' } - return str(ret) + return ret # ==================================================================================================================== def on_update(self): @@ -184,7 +184,7 @@ class DocType(TransactionBase): else: set(self.doc, 'status', 'Enquiry Lost') set(self.doc, 'order_lost_reason', arg) - return cstr('true') + return 'true' # ==================================================================================================================== def update_follow_up(self): diff --git a/selling/doctype/installation_note/installation_note.py b/selling/doctype/installation_note/installation_note.py index ce213632c79..e0af7ece248 100644 --- a/selling/doctype/installation_note/installation_note.py +++ b/selling/doctype/installation_note/installation_note.py @@ -29,20 +29,7 @@ class DocType(TransactionBase): # --------- def autoname(self): self.doc.name = make_autoname(self.doc.naming_series+'.#####') - - #fetch customer details - #================================= - #def get_customer_details(self): - # det = sql("select t1.customer_name, t1.address,t1.territory,t2.contact_name from `tabCustomer` t1, `tabContact` t2 where t1.name = '%s' and t1.name=t2.customer and t2.is_primary_contact = 'Yes'"%self.doc.customer, as_dict=1) - - # ret = { - # 'customer_name': det and det[0]['customer_name'] or '', - # 'address' : det and det[0]['address'] or '', - # 'territory': det and det[0]['territory'] or '', - # 'contact_person' : det and det[0]['contact_name'] or '' - # } - - # return str(ret) + #fetch delivery note details #==================================== diff --git a/selling/doctype/lead/lead.py b/selling/doctype/lead/lead.py index 1bf8c8d1b65..14d14e12adf 100644 --- a/selling/doctype/lead/lead.py +++ b/selling/doctype/lead/lead.py @@ -51,7 +51,7 @@ class DocType: 'description': it and it[0][3] or '', 'uom' : it and it[0][4] or '' } - return cstr(ret) + return ret def validate(self): import string diff --git a/selling/doctype/quotation/quotation.js b/selling/doctype/quotation/quotation.js index f21df25c479..b3dcde681a3 100644 --- a/selling/doctype/quotation/quotation.js +++ b/selling/doctype/quotation/quotation.js @@ -11,7 +11,7 @@ $import(SMS Control) // ONLOAD // =================================================================================== -cur_frm.cscript.onload = function(doc, cdt, cdn) { +cur_frm.cscript.onload = function(doc, cdt, cdn) { if(!doc.quotation_to) hide_field(['customer','customer_address','contact_person','customer_name','lead', 'lead_name', 'address_display', 'contact_display', 'contact_mobile', 'contact_email', 'territory', 'customer_group']); if(!doc.price_list_name) set_multiple(cdt,cdn,{price_list_name:sys_defaults.price_list_name}); if(!doc.status) set_multiple(cdt,cdn,{status:'Draft'}); @@ -21,7 +21,7 @@ cur_frm.cscript.onload = function(doc, cdt, cdn) { //if(!doc.price_list_name && sys_defaults.price_list_name) set_multiple(cdt,cdn,{price_list_name:sys_defaults.price_list_name}); if(!doc.company && sys_defaults.company) set_multiple(cdt,cdn,{company:sys_defaults.company}); if(!doc.fiscal_year && sys_defaults.fiscal_year) set_multiple(cdt,cdn,{fiscal_year:sys_defaults.fiscal_year}); - + if(doc.quotation_to) { if(doc.quotation_to == 'Customer') { hide_field(['lead', 'lead_name']); @@ -34,7 +34,7 @@ cur_frm.cscript.onload = function(doc, cdt, cdn) { cur_frm.cscript.onload_post_render = function(doc, dt, dn) { // load default charges - if(doc.__islocal && !getchildren('RV Tax Detail', doc.name, 'other_charges', doc.doctype).length) + if(doc.__islocal && !getchildren('RV Tax Detail', doc.name, 'other_charges', doc.doctype).length) cur_frm.cscript.load_taxes(doc, cdt, cdn); } @@ -46,9 +46,9 @@ cur_frm.cscript.lead_cust_show = function(doc,cdt,cdn){ hide_field(['lead_name','customer','customer_address','contact_person','customer_name','address_display','contact_display','contact_mobile','contact_email','territory','customer_group']); doc.lead = doc.lead_name = doc.customer = doc.customer_address = doc.contact_person = doc.address_display = doc.contact_display = doc.contact_mobile = doc.contact_email = doc.territory = doc.customer_group = ""; } - else if(doc.quotation_to == 'Customer'){ + else if(doc.quotation_to == 'Customer'){ unhide_field(['customer']); - hide_field(['lead','lead_name','address_display','contact_display','contact_mobile','contact_email','territory']); + hide_field(['lead','lead_name','address_display','contact_display','contact_mobile','contact_email','territory']); doc.lead = doc.lead_name = doc.customer = doc.customer_address = doc.contact_person = doc.address_display = doc.contact_display = doc.contact_mobile = doc.contact_email = doc.territory = doc.customer_group = ""; } //refresh_many(['lead','customer']); @@ -56,7 +56,7 @@ cur_frm.cscript.lead_cust_show = function(doc,cdt,cdn){ -//================ hide - unhide fields on basis of quotation to either lead or customer =============================== +//================ hide - unhide fields on basis of quotation to either lead or customer =============================== cur_frm.cscript.quotation_to = function(doc,cdt,cdn){ cur_frm.cscript.lead_cust_show(doc,cdt,cdn); //doc.customer_address = doc.territory = doc.contact_no = doc.email_id = ""; @@ -77,7 +77,7 @@ cur_frm.cscript.refresh = function(doc, cdt, cdn) { cur_frm.add_custom_button('Set as Lost', cur_frm.cscript['Declare Order Lost']); cur_frm.add_custom_button('Send SMS', cur_frm.cscript['Send SMS']); } - + if (!doc.docstatus) hide_field(['Update Follow up']); else unhide_field(['Update Follow up']); //cur_frm.cscript.lead_cust_show(doc,cdt,cdn); @@ -111,7 +111,7 @@ cur_frm.cscript.customer = function(doc,dt,dn) { var callback = function(r,rt) { var doc = locals[cur_frm.doctype][cur_frm.docname]; cur_frm.refresh(); - } + } if(doc.customer) $c_obj(make_doclist(doc.doctype, doc.name), 'get_default_customer_address', '', callback); if(doc.customer) unhide_field(['customer_address','contact_person','customer_name','address_display','contact_display','contact_mobile','contact_email','territory','customer_group']); @@ -123,12 +123,12 @@ cur_frm.cscript.customer_address = cur_frm.cscript.contact_person = function(doc cur_frm.fields_dict.customer_address.on_new = function(dn) { locals['Address'][dn].customer = locals[cur_frm.doctype][cur_frm.docname].customer; - locals['Address'][dn].customer_name = locals[cur_frm.doctype][cur_frm.docname].customer_name; + locals['Address'][dn].customer_name = locals[cur_frm.doctype][cur_frm.docname].customer_name; } cur_frm.fields_dict.contact_person.on_new = function(dn) { locals['Contact'][dn].customer = locals[cur_frm.doctype][cur_frm.docname].customer; - locals['Contact'][dn].customer_name = locals[cur_frm.doctype][cur_frm.docname].customer_name; + locals['Contact'][dn].customer_name = locals[cur_frm.doctype][cur_frm.docname].customer_name; } cur_frm.fields_dict['customer_address'].get_query = function(doc, cdt, cdn) { @@ -146,7 +146,7 @@ cur_frm.fields_dict['lead'].get_query = function(doc,cdt,cdn){ cur_frm.cscript.lead = function(doc, cdt, cdn) { if(doc.lead) get_server_fields('get_lead_details', doc.lead,'', doc, cdt, cdn, 1); - if(doc.lead) unhide_field(['lead_name','address_display','contact_mobile','contact_email','territory']); + if(doc.lead) unhide_field(['lead_name','address_display','contact_mobile','contact_email','territory']); } @@ -166,7 +166,7 @@ cur_frm.fields_dict['enq_no'].get_query = function(doc,cdt,cdn){ cur_frm.cscript['Make Sales Order'] = function() { var doc = cur_frm.doc; - if (doc.docstatus == 1) { + if (doc.docstatus == 1) { var n = createLocal("Sales Order"); $c('dt_map', args={ 'docs':compress_doclist([locals["Sales Order"][n]]), @@ -186,17 +186,17 @@ cur_frm.cscript['Pull Enquiry Detail'] = function(doc,cdt,cdn){ var callback = function(r,rt){ if(r.message){ doc.quotation_to = r.message; - + if(doc.quotation_to == 'Lead') { - unhide_field(['lead','lead_name','address_display','contact_mobile','contact_email','territory']); + unhide_field(['lead','lead_name','address_display','contact_mobile','contact_email','territory']); } else if(doc.quotation_to == 'Customer') { unhide_field(['customer','customer_address','contact_person','address_display','contact_display','contact_mobile','contact_email','territory','customer_group']); } refresh_many(['quotation_details','quotation_to','customer','customer_address','contact_person','lead','lead_name','address_display','contact_display','contact_mobile','contact_email','territory','customer_group','order_type']); } - } - + } + $c_obj(make_doclist(doc.doctype, doc.name),'pull_enq_details','',callback); } @@ -217,7 +217,7 @@ cur_frm.cscript['Update Follow up'] = function(doc){ //------------------------- cur_frm.cscript['Declare Order Lost'] = function(){ var qtn_lost_dialog; - + set_qtn_lost_dialog = function(doc,cdt,cdn){ qtn_lost_dialog = new Dialog(400,400,'Add Quotation Lost Reason'); qtn_lost_dialog.make_body([ @@ -226,26 +226,26 @@ cur_frm.cscript['Declare Order Lost'] = function(){ ['HTML', 'Response', '
'], ['HTML', 'Add Reason', '
'] ]); - + var add_reason_btn1 = $a($i(qtn_lost_dialog.widgets['Add Reason']), 'button', 'button'); add_reason_btn1.innerHTML = 'Add'; add_reason_btn1.onclick = function(){ qtn_lost_dialog.add(); } - + var add_reason_btn2 = $a($i(qtn_lost_dialog.widgets['Add Reason']), 'button', 'button'); add_reason_btn2.innerHTML = 'Cancel'; $y(add_reason_btn2,{marginLeft:'4px'}); add_reason_btn2.onclick = function(){ qtn_lost_dialog.hide();} - + qtn_lost_dialog.onshow = function() { qtn_lost_dialog.widgets['Quotation Lost Reason'].value = ''; $i('update_quotation_dialog_response').innerHTML = ''; } - + qtn_lost_dialog.add = function() { // sending... $i('update_quotation_dialog_response').innerHTML = 'Processing...'; var arg = strip(qtn_lost_dialog.widgets['Quotation Lost Reason'].value); - var call_back = function(r,rt) { + var call_back = function(r,rt) { if(r.message == 'true'){ $i('update_quotation_dialog_response').innerHTML = 'Done'; qtn_lost_dialog.hide(); @@ -254,11 +254,11 @@ cur_frm.cscript['Declare Order Lost'] = function(){ if(arg) $c_obj(make_doclist(cur_frm.doc.doctype, cur_frm.doc.name),'declare_order_lost',arg,call_back); else msgprint("Please add Quotation lost reason"); } - } - + } + if(!qtn_lost_dialog){ set_qtn_lost_dialog(doc,cdt,cdn); - } + } qtn_lost_dialog.show(); } @@ -284,23 +284,23 @@ cur_frm.fields_dict['territory'].get_query = function(doc,cdt,cdn) { //===================== Quotation to validation - either customer or lead mandatory ==================== cur_frm.cscript.quot_to_validate = function(doc,cdt,cdn){ - + if(doc.quotation_to == 'Lead'){ - + if(!doc.lead){ - alert("Lead is mandatory."); - validated = false; + alert("Lead is mandatory."); + validated = false; } } else if(doc.quotation_to == 'Customer'){ - + if(!doc.customer){ alert("Customer is mandatory."); validated = false; } - + } - + } //===================validation function ================================= @@ -308,3 +308,35 @@ cur_frm.cscript.quot_to_validate = function(doc,cdt,cdn){ cur_frm.cscript.validate = function(doc,cdt,cdn){ cur_frm.cscript.quot_to_validate(doc,cdt,cdn); } + +//================ Last Quoted Price and Last Sold Price suggestion ====================== +cur_frm.fields_dict['quotation_details'].grid.get_field('item_code').get_query= function(doc, cdt, cdn) { + var d = locals[cdt][cdn]; + if(doc.customer) + return repl("SELECT i.name,i.item_code,concat('Last quoted at - ',cast(quote_rate as char)) as quote_rate,concat('Last sold at - ',cast(sales_rate as char)) as sales_rate FROM\ + (\ + select item_code,name from tabItem where tabItem.%(key)s like '%s'\ + )i\ + left join\ + (\ + select q.item_code,q.quote_rate from\ + (\ + select q.transaction_date,qd.item_code,basic_rate as quote_rate from `tabQuotation Detail` qd, `tabQuotation` q where q.name=qd.parent and q.docstatus=1 and customer='%(cust)s'\ + )q,\ + (\ + select qd.item_code,max(transaction_date) as transaction_date from `tabQuotation Detail` qd, `tabQuotation` q where q.name=qd.parent and q.docstatus=1 and customer='%(cust)s' group by qd.item_code\ + )m where q.item_code=m.item_code and q.transaction_date=m.transaction_date\ + )q on i.item_code=q.item_code\ + left join\ + (\ + select r.item_code,r.sales_rate from\ + (\ + select r.voucher_date,rd.item_code,basic_rate as sales_rate from `tabRV Detail` rd, `tabReceivable Voucher` r where r.name=rd.parent and r.docstatus=1 and customer='%(cust)s'\ + )r,\ + (\ + select rd.item_code,max(voucher_date) as voucher_date from `tabRV Detail` rd, `tabReceivable Voucher` r where r.name=rd.parent and r.docstatus=1 and customer='%(cust)s' group by rd.item_code\ + )m where r.item_code=m.item_code and r.voucher_date=m.voucher_date\ + )s on i.item_code=s.item_code ORDER BY item_code LIMIT 50",{cust:doc.customer}); + else + return "SELECT name, item_code FROM tabItem WHERE `tabItem`.%(key)s LIKE '%s' ORDER BY tabItem.item_code DESC LIMIT 50"; +} \ No newline at end of file diff --git a/selling/doctype/quotation/quotation.py b/selling/doctype/quotation/quotation.py index aed868ef1d9..11755406faf 100644 --- a/selling/doctype/quotation/quotation.py +++ b/selling/doctype/quotation/quotation.py @@ -45,17 +45,12 @@ class DocType(TransactionBase): self.get_adj_percent() - return cstr(self.doc.quotation_to) - - # Get Customer Details - # -------------------- - #def get_customer_details(self): - # return cstr(get_obj('Sales Common').get_customer_details(self)) + return self.doc.quotation_to # Get contact person details based on customer selected # ------------------------------------------------------ def get_contact_details(self): - return cstr(get_obj('Sales Common').get_contact_details(self,0)) + return get_obj('Sales Common').get_contact_details(self,0) # Clear Quotation Details # ----------------------- @@ -111,7 +106,7 @@ class DocType(TransactionBase): 'contact_mobile' : details and details[0]['mobile_no'] or '-', 'contact_email' : details and details[0]['email_id'] or '-' } - return cstr(ret) + return ret # GET TERMS AND CONDITIONS @@ -295,7 +290,7 @@ class DocType(TransactionBase): set(self.doc, 'status', 'Order Lost') set(self.doc, 'order_lost_reason', arg) self.update_enquiry('order lost') - return cstr('true') + return 'true' #check if value entered in item table #-------------------------------------- diff --git a/selling/doctype/sales_common/sales_common.py b/selling/doctype/sales_common/sales_common.py index 25dd960bdc5..acdca50f7b0 100644 --- a/selling/doctype/sales_common/sales_common.py +++ b/selling/doctype/sales_common/sales_common.py @@ -118,21 +118,21 @@ class DocType(TransactionBase): t = {} for x in tax: t[x[0]] = flt(x[1]) ret = { - 'description' : item and item[0]['description_html'] or item[0]['description'], - 'item_group' : item and item[0]['item_group'] or '', - 'item_name' : item and item[0]['item_name'] or '', - 'brand' : item and item[0]['brand'] or '', - 'stock_uom' : item and item[0]['stock_uom'] or '', - 'reserved_warehouse' : item and item[0]['default_warehouse'] or '', - 'warehouse' : item and item[0]['default_warehouse'] or '', - 'income_account' : item and item[0]['default_income_account'] or '', - 'cost_center' : item and item[0]['default_sales_cost_center'] or '', - 'qty' : 1.00, # this is done coz if item once fetched is fetched again thn its qty shld be reset to 1 - 'adj_rate' : 0, - 'amount' : 0, - 'export_amount' : 0, - 'item_tax_rate' : str(t), - 'batch_no' : '' + 'description' : item and item[0]['description_html'] or item[0]['description'], + 'item_group' : item and item[0]['item_group'] or '', + 'item_name' : item and item[0]['item_name'] or '', + 'brand' : item and item[0]['brand'] or '', + 'stock_uom' : item and item[0]['stock_uom'] or '', + 'reserved_warehouse' : item and item[0]['default_warehouse'] or '', + 'warehouse' : item and item[0]['default_warehouse'] or '', + 'income_account' : item and item[0]['default_income_account'] or '', + 'cost_center' : item and item[0]['default_sales_cost_center'] or '', + 'qty' : 1.00, # this is done coz if item once fetched is fetched again thn its qty shld be reset to 1 + 'adj_rate' : 0, + 'amount' : 0, + 'export_amount' : 0, + 'item_tax_rate' : str(t), + 'batch_no' : '' } if(obj.doc.price_list_name and item): #this is done to fetch the changed BASIC RATE and REF RATE based on PRICE LIST ref_rate = self.get_ref_rate(item_code, obj.doc.price_list_name, obj.doc.currency) @@ -143,7 +143,8 @@ class DocType(TransactionBase): if obj.doc.doctype == 'Receivable Voucher': return ret - return str(ret) + + return ret # ***************** Get Ref rate as entered in Item Master ******************** def get_ref_rate(self, item_code, price_list_name, currency): @@ -161,7 +162,6 @@ class DocType(TransactionBase): d.base_ref_rate = flt(ref_rate) * flt(obj.doc.conversion_rate) d.export_rate = flt(ref_rate) - # Load Default Taxes # ==================== def load_default_taxes(self, obj): @@ -203,7 +203,7 @@ class DocType(TransactionBase): ret = { 'item_tax_rate' : tax and str(t) or '' } - return str(ret) + return ret # Get Serial No Details # ========================================================================== @@ -220,7 +220,7 @@ class DocType(TransactionBase): 'description' : item and item[0]['description'] or '', 'item_tax_rate' : str(t) } - return str(ret) + return ret # Get Commission rate # ======================================================================= @@ -233,7 +233,7 @@ class DocType(TransactionBase): 'commission_rate' : comm_rate and flt(comm_rate[0]['commission_rate']) or 0, 'total_commission' : flt(total_comm) } - return str(ret) + return ret else: msgprint("Business Associate : %s does not exist in the system." % (sales_partner)) raise Exception @@ -287,7 +287,7 @@ class DocType(TransactionBase): ret = { 'rate' : rate and flt(rate[0]['tax_rate']) or 0 } - return cstr(ret) + return ret # Make Packing List from Sales BOM @@ -324,11 +324,33 @@ class DocType(TransactionBase): if self.has_sales_bom(d.item_code): for i in self.get_sales_bom_items(d.item_code): - il.append([warehouse, i[0], flt(flt(i[1])* qty), reserved_qty, i[2], d.batch_no, d.serial_no]) + il.append([warehouse, i[0], flt(flt(i[1])* qty), flt(flt(i[1])*reserved_qty), i[2], d.batch_no, d.serial_no]) else: il.append([warehouse, d.item_code, qty, reserved_qty, d.stock_uom, d.batch_no, d.serial_no]) return il + # --------------------------------------------------------------------------------------------- + # get qty, amount already billed or delivered against curr line item for current doctype + # For Eg: SO-RV get total qty, amount from SO and also total qty, amount against that SO in RV + # --------------------------------------------------------------------------------------------- + def get_curr_and_ref_doc_details(self, curr_doctype, ref_tab_fname, ref_tab_dn, ref_doc_tname, curr_parent_name, curr_parent_doctype): + # Get total qty, amt of current doctype (eg RV) except for qty, amt of this transaction + if curr_parent_doctype == 'Installation Note': + curr_det = sql("select sum(qty) from `tab%s` where %s = '%s' and docstatus = 1 and parent != '%s'"% (curr_doctype, ref_tab_fname, ref_tab_dn, curr_parent_name)) + qty, amt = curr_det and flt(curr_det[0][0]) or 0, 0 + else: + curr_det = sql("select sum(qty), sum(amount) from `tab%s` where %s = '%s' and docstatus = 1 and parent != '%s'"% (curr_doctype, ref_tab_fname, ref_tab_dn, curr_parent_name)) + qty, amt = curr_det and flt(curr_det[0][0]) or 0, curr_det and flt(curr_det[0][1]) or 0 + + # get total qty of ref doctype + ref_det = sql("select qty, amount from `tab%s` where name = '%s' and docstatus = 1"% (ref_doc_tname, ref_tab_dn)) + max_qty, max_amt = ref_det and flt(ref_det[0][0]) or 0, ref_det and flt(ref_det[0][1]) or 0 + + return qty, max_qty, amt, max_amt + + + + # ----------------------- # add packing list items @@ -458,26 +480,6 @@ class DocType(TransactionBase): def update_prevdoc_detail(self, is_submit, obj): StatusUpdater(obj, is_submit).update() - # --------------------------------------------------------------------------------------------- - # get qty, amount already billed or delivered against curr line item for current doctype - # For Eg: SO-RV get total qty, amount from SO and also total qty, amount against that SO in RV - # --------------------------------------------------------------------------------------------- - def get_curr_and_ref_doc_details(self, curr_doctype, ref_tab_fname, ref_tab_dn, ref_doc_tname, curr_parent_name, curr_parent_doctype): - # Get total qty, amt of current doctype (eg RV) except for qty, amt of this transaction - if curr_parent_doctype == 'Installation Note': - curr_det = sql("select sum(qty) from `tab%s` where %s = '%s' and docstatus = 1 and parent != '%s'"% (curr_doctype, ref_tab_fname, ref_tab_dn, curr_parent_name)) - qty, amt = curr_det and flt(curr_det[0][0]) or 0, 0 - else: - curr_det = sql("select sum(qty), sum(amount) from `tab%s` where %s = '%s' and docstatus = 1 and parent != '%s'"% (curr_doctype, ref_tab_fname, ref_tab_dn, curr_parent_name)) - qty, amt = curr_det and flt(curr_det[0][0]) or 0, curr_det and flt(curr_det[0][1]) or 0 - - # get total qty of ref doctype - ref_det = sql("select qty, amount from `tab%s` where name = '%s' and docstatus = 1"% (ref_doc_tname, ref_tab_dn)) - max_qty, max_amt = ref_det and flt(ref_det[0][0]) or 0, ref_det and flt(ref_det[0][1]) or 0 - - return qty, max_qty, amt, max_amt - - @@ -496,7 +498,7 @@ class StatusUpdater: - Validate over delivery From Receivable Voucher - - Update Billed Qty + - Update Billed Amt - Update Percent - Validate over billing @@ -524,23 +526,33 @@ class StatusUpdater: self.validate_qty({ 'source_dt' :'Delivery Note Detail', 'compare_field' :'delivered_qty', + 'compare_ref_field' :'qty', 'target_dt' :'Sales Order Detail', 'join_field' :'prevdoc_detail_docname' }) elif self.obj.doc.doctype=='Receivable Voucher': self.validate_qty({ 'source_dt' :'RV Detail', - 'compare_field' :'billed_qty', + 'compare_field' :'billed_amt', + 'compare_ref_field' :'amount', 'target_dt' :'Sales Order Detail', 'join_field' :'so_detail' }) + self.validate_qty({ + 'source_dt' :'RV Detail', + 'compare_field' :'billed_amt', + 'compare_ref_field' :'amount', + 'target_dt' :'Delivery Note Detail', + 'join_field' :'dn_detail' + }, no_tolerance =1) elif self.obj.doc.doctype=='Installation Note': self.validate_qty({ 'source_dt' :'Installation Item Details', 'compare_field' :'installed_qty', + 'compare_ref_field' :'qty', 'target_dt' :'Delivery Note Detail', 'join_field' :'dn_detail' - }, no_tolerance =1); + }, no_tolerance =1) def get_tolerance_for(self, item_code): @@ -567,22 +579,22 @@ class StatusUpdater: # check if overflow is within tolerance tolerance = self.get_tolerance_for(item['item_code']) - overflow_percent = ((item[args['compare_field']] - item['qty']) / item['qty'] * 100) + overflow_percent = ((item[args['compare_field']] - item[args['compare_ref_field']]) / item[args['compare_ref_field']] * 100) if overflow_percent - tolerance > 0.0001: - item['max_allowed'] = flt(item['qty'] * (100+tolerance)/100) + item['max_allowed'] = flt(item[args['compare_ref_field']] * (100+tolerance)/100) item['reduce_by'] = item[args['compare_field']] - item['max_allowed'] msgprint(""" - Row #%(idx)s: Max qty allowed for Item %(item_code)s against %(parenttype)s %(parent)s is %(max_allowed)s. + Row #%(idx)s: Max %(compare_ref_field)s allowed for Item %(item_code)s against %(parenttype)s %(parent)s is %(max_allowed)s. If you want to increase your overflow tolerance, please increase tolerance %% in Global Defaults or Item master. - Or, you must reduce the qty by %(reduce_by)s""" % item, raise_exception=1) + Or, you must reduce the %(compare_ref_field)s by %(reduce_by)s""" % item, raise_exception=1) def validate_qty(self, args, no_tolerance=None): """ - Updates qty at row level + Validates qty at row level """ # get unique transactions to update for d in self.obj.doclist: @@ -591,22 +603,23 @@ class StatusUpdater: # get all qty where qty > compare_field item = sql(""" - select item_code, qty, `%(compare_field)s`, parenttype, parent from `tab%(target_dt)s` - where qty < `%(compare_field)s` and name="%(name)s" and docstatus=1 + select item_code, `%(compare_ref_field)s`, `%(compare_field)s`, parenttype, parent from `tab%(target_dt)s` + where `%(compare_ref_field)s` < `%(compare_field)s` and name="%(name)s" and docstatus=1 """ % args, as_dict=1) if item: item = item[0] item['idx'] = d.idx - + item['compare_ref_field'] = args['compare_ref_field'] if no_tolerance: - item['reduce_by'] = item[args['compare_field']] - item['qty'] + item['reduce_by'] = item[args['compare_field']] - item[args['compare_ref_field']] msgprint(""" - Row #%(idx)s: Max qty allowed for Item %(item_code)s against - %(parenttype)s %(parent)s is %(qty)s. + Row #%(idx)s: Max %(compare_ref_field)s allowed for Item %(item_code)s against + %(parenttype)s %(parent)s is """ % item + + cstr(item[args['compare_ref_field']]) + """. - You must reduce the qty by %(reduce_by)s""" % item, raise_exception=1) - + You must reduce the %(compare_ref_field)s by %(reduce_by)s""" % item, raise_exception=1) + else: self.check_overflow_with_tolerance(item, args) @@ -621,6 +634,7 @@ class StatusUpdater: 'target_dt' :'Sales Order Detail', 'target_parent_dt' :'Sales Order', 'target_parent_field' :'per_delivered', + 'target_ref_field' :'qty', 'source_dt' :'Delivery Note Detail', 'source_field' :'qty', 'join_field' :'prevdoc_detail_docname', @@ -631,12 +645,13 @@ class StatusUpdater: elif self.obj.doc.doctype=='Receivable Voucher': self.update_qty({ - 'target_field' :'billed_qty', + 'target_field' :'billed_amt', 'target_dt' :'Sales Order Detail', 'target_parent_dt' :'Sales Order', 'target_parent_field' :'per_billed', + 'target_ref_field' :'amount', 'source_dt' :'RV Detail', - 'source_field' :'qty', + 'source_field' :'amount', 'join_field' :'so_detail', 'percent_join_field' :'sales_order', 'status_field' :'billing_status', @@ -644,12 +659,13 @@ class StatusUpdater: }) self.update_qty({ - 'target_field' :'billed_qty', + 'target_field' :'billed_amt', 'target_dt' :'Delivery Note Detail', 'target_parent_dt' :'Delivery Note', 'target_parent_field' :'per_billed', + 'target_ref_field' :'amount', 'source_dt' :'RV Detail', - 'source_field' :'qty', + 'source_field' :'amount', 'join_field' :'dn_detail', 'percent_join_field' :'delivery_note', 'status_field' :'billing_status', @@ -662,6 +678,7 @@ class StatusUpdater: 'target_dt' :'Delivery Note Detail', 'target_parent_dt' :'Delivery Note', 'target_parent_field' :'per_installed', + 'target_ref_field' :'qty', 'source_dt' :'Installed Item Details', 'source_field' :'qty', 'join_field' :'prevdoc_detail_docname', @@ -692,7 +709,7 @@ class StatusUpdater: update `tab%(target_dt)s` set - %(target_field)s = (select sum(qty) from `tab%(source_dt)s` where `%(join_field)s`="%(detail_id)s" and (docstatus=1 %(cond)s)) + %(target_field)s = (select sum(%(source_field)s) from `tab%(source_dt)s` where `%(join_field)s`="%(detail_id)s" and (docstatus=1 %(cond)s)) where name="%(detail_id)s" """ % args) @@ -708,10 +725,10 @@ class StatusUpdater: `tab%(target_parent_dt)s` set %(target_parent_field)s = - (select sum(if(qty > ifnull(%(target_field)s, 0), %(target_field)s, qty))/sum(qty)*100 from `tab%(target_dt)s` where parent="%(name)s"), + (select sum(if(%(target_ref_field)s > ifnull(%(target_field)s, 0), %(target_field)s, %(target_ref_field)s))/sum(%(target_ref_field)s)*100 from `tab%(target_dt)s` where parent="%(name)s"), modified = now() - where - name="%(name)s" + where + name="%(name)s" """ % args) # update field diff --git a/selling/doctype/sales_order/sales_order.py b/selling/doctype/sales_order/sales_order.py index 11842fb0799..ca5af7ae662 100644 --- a/selling/doctype/sales_order/sales_order.py +++ b/selling/doctype/sales_order/sales_order.py @@ -19,470 +19,469 @@ convert_to_lists = webnotes.conn.convert_to_lists from utilities.transaction_base import TransactionBase class DocType(TransactionBase): - def __init__(self, doc, doclist=[]): - self.doc = doc - self.doclist = doclist - self.tname = 'Sales Order Detail' - self.fname = 'sales_order_details' - self.person_tname = 'Target Detail' - self.partner_tname = 'Partner Target Detail' - self.territory_tname = 'Territory Target Detail' + def __init__(self, doc, doclist=[]): + self.doc = doc + self.doclist = doclist + self.tname = 'Sales Order Detail' + self.fname = 'sales_order_details' + self.person_tname = 'Target Detail' + self.partner_tname = 'Partner Target Detail' + self.territory_tname = 'Territory Target Detail' # Autoname # =============== - def autoname(self): - self.doc.name = make_autoname(self.doc.naming_series+'.#####') + def autoname(self): + self.doc.name = make_autoname(self.doc.naming_series+'.#####') - + # DOCTYPE TRIGGER FUNCTIONS # ============================= - # Pull Quotation Details - # ----------------------- - def pull_quotation_details(self): - self.doc.clear_table(self.doclist, 'other_charges') - self.doc.clear_table(self.doclist, 'sales_order_details') - self.doc.clear_table(self.doclist, 'sales_team') - self.doc.clear_table(self.doclist, 'tc_details') - if self.doc.quotation_no: - get_obj('DocType Mapper', 'Quotation-Sales Order').dt_map('Quotation', 'Sales Order', self.doc.quotation_no, self.doc, self.doclist, "[['Quotation', 'Sales Order'],['Quotation Detail', 'Sales Order Detail'],['RV Tax Detail','RV Tax Detail'],['Sales Team','Sales Team'],['TC Detail','TC Detail']]") - else: - msgprint("Please select Quotation whose details need to pull") + # Pull Quotation Details + # ----------------------- + def pull_quotation_details(self): + self.doc.clear_table(self.doclist, 'other_charges') + self.doc.clear_table(self.doclist, 'sales_order_details') + self.doc.clear_table(self.doclist, 'sales_team') + self.doc.clear_table(self.doclist, 'tc_details') + if self.doc.quotation_no: + get_obj('DocType Mapper', 'Quotation-Sales Order').dt_map('Quotation', 'Sales Order', self.doc.quotation_no, self.doc, self.doclist, "[['Quotation', 'Sales Order'],['Quotation Detail', 'Sales Order Detail'],['RV Tax Detail','RV Tax Detail'],['Sales Team','Sales Team'],['TC Detail','TC Detail']]") + else: + msgprint("Please select Quotation whose details need to pull") - return cstr(self.doc.quotation_no) - - #pull project customer - #------------------------- - def pull_project_customer(self): - res = sql("select customer from `tabProject` where name = '%s'"%self.doc.project_name) - if res: - get_obj('DocType Mapper', 'Project-Sales Order').dt_map('Project', 'Sales Order', self.doc.project_name, self.doc, self.doclist, "[['Project', 'Sales Order']]") - - - # Get Customer Details - # --------------------- - #def get_customer_details(self): - # sales_com_obj = get_obj('Sales Common') - # sales_com_obj.get_customer_details(self) - # sales_com_obj.get_shipping_details(self) + return cstr(self.doc.quotation_no) + + #pull project customer + #------------------------- + def pull_project_customer(self): + res = sql("select customer from `tabProject` where name = '%s'"%self.doc.project_name) + if res: + get_obj('DocType Mapper', 'Project-Sales Order').dt_map('Project', 'Sales Order', self.doc.project_name, self.doc, self.doclist, "[['Project', 'Sales Order']]") + + + # Get Customer Details + # --------------------- + #def get_customer_details(self): + # sales_com_obj = get_obj('Sales Common') + # sales_com_obj.get_customer_details(self) + # sales_com_obj.get_shipping_details(self) - # Get contact person details based on customer selected - # ------------------------------------------------------ - def get_contact_details(self): - get_obj('Sales Common').get_contact_details(self,0) + # Get contact person details based on customer selected + # ------------------------------------------------------ + def get_contact_details(self): + get_obj('Sales Common').get_contact_details(self,0) - # Get Commission rate of Sales Partner - # ------------------------------------- - def get_comm_rate(self, sales_partner): - return get_obj('Sales Common').get_comm_rate(sales_partner, self) + # Get Commission rate of Sales Partner + # ------------------------------------- + def get_comm_rate(self, sales_partner): + return get_obj('Sales Common').get_comm_rate(sales_partner, self) - # Clear Sales Order Details Table - # -------------------------------- - def clear_sales_order_details(self): - self.doc.clear_table(self.doclist, 'sales_order_details') - + # Clear Sales Order Details Table + # -------------------------------- + def clear_sales_order_details(self): + self.doc.clear_table(self.doclist, 'sales_order_details') + # SALES ORDER DETAILS TRIGGER FUNCTIONS # ================================================================================ - # Get Item Details - # ---------------- - def get_item_details(self, item_code): - return get_obj('Sales Common').get_item_details(item_code, self) + # Get Item Details + # ---------------- + def get_item_details(self, item_code): + return get_obj('Sales Common').get_item_details(item_code, self) - # Re-calculates Basic Rate & amount based on Price List Selected - # -------------------------------------------------------------- - def get_adj_percent(self, arg=''): - get_obj('Sales Common').get_adj_percent(self) + # Re-calculates Basic Rate & amount based on Price List Selected + # -------------------------------------------------------------- + def get_adj_percent(self, arg=''): + get_obj('Sales Common').get_adj_percent(self) - # Get projected qty of item based on warehouse selected - # ----------------------------------------------------- - def get_available_qty(self,args): - args = eval(args) - tot_avail_qty = sql("select projected_qty, actual_qty from `tabBin` where item_code = '%s' and warehouse = '%s'" % (args['item_code'], args['warehouse']), as_dict=1) - ret = { - 'projected_qty' : tot_avail_qty and flt(tot_avail_qty[0]['projected_qty']) or 0, - 'actual_qty' : tot_avail_qty and flt(tot_avail_qty[0]['actual_qty']) or 0 - } - return cstr(ret) - - + # Get projected qty of item based on warehouse selected + # ----------------------------------------------------- + def get_available_qty(self,args): + args = eval(args) + tot_avail_qty = sql("select projected_qty, actual_qty from `tabBin` where item_code = '%s' and warehouse = '%s'" % (args['item_code'], args['warehouse']), as_dict=1) + ret = { + 'projected_qty' : tot_avail_qty and flt(tot_avail_qty[0]['projected_qty']) or 0, + 'actual_qty' : tot_avail_qty and flt(tot_avail_qty[0]['actual_qty']) or 0 + } + return ret + # OTHER CHARGES TRIGGER FUNCTIONS # ==================================================================================== - - # Get Tax rate if account type is TAX - # ------------------------------------ - def get_rate(self,arg): - return get_obj('Sales Common').get_rate(arg) + + # Get Tax rate if account type is TAX + # ------------------------------------ + def get_rate(self,arg): + return get_obj('Sales Common').get_rate(arg) - # Load Default Charges - # ---------------------------------------------------------- - def load_default_taxes(self): - return get_obj('Sales Common').load_default_taxes(self) + # Load Default Charges + # ---------------------------------------------------------- + def load_default_taxes(self): + return get_obj('Sales Common').load_default_taxes(self) - # Pull details from other charges master (Get Other Charges) - # ---------------------------------------------------------- - def get_other_charges(self): - return get_obj('Sales Common').get_other_charges(self) + # Pull details from other charges master (Get Other Charges) + # ---------------------------------------------------------- + def get_other_charges(self): + return get_obj('Sales Common').get_other_charges(self) # GET TERMS & CONDITIONS # ===================================================================================== - def get_tc_details(self): - return get_obj('Sales Common').get_tc_details(self) + def get_tc_details(self): + return get_obj('Sales Common').get_tc_details(self) #check if maintenance schedule already generated #============================================ - def check_maintenance_schedule(self): - nm = sql("select t1.name from `tabMaintenance Schedule` t1, `tabItem Maintenance Detail` t2 where t2.parent=t1.name and t2.prevdoc_docname=%s and t1.docstatus=1", self.doc.name) - nm = nm and nm[0][0] or '' - - if not nm: - return cstr('No') + def check_maintenance_schedule(self): + nm = sql("select t1.name from `tabMaintenance Schedule` t1, `tabItem Maintenance Detail` t2 where t2.parent=t1.name and t2.prevdoc_docname=%s and t1.docstatus=1", self.doc.name) + nm = nm and nm[0][0] or '' + + if not nm: + return 'No' #check if maintenance visit already generated #============================================ - def check_maintenance_visit(self): - nm = sql("select t1.name from `tabMaintenance Visit` t1, `tabMaintenance Visit Detail` t2 where t2.parent=t1.name and t2.prevdoc_docname=%s and t1.docstatus=1 and t1.completion_status='Fully Completed'", self.doc.name) - nm = nm and nm[0][0] or '' - - if not nm: - return cstr('No') + def check_maintenance_visit(self): + nm = sql("select t1.name from `tabMaintenance Visit` t1, `tabMaintenance Visit Detail` t2 where t2.parent=t1.name and t2.prevdoc_docname=%s and t1.docstatus=1 and t1.completion_status='Fully Completed'", self.doc.name) + nm = nm and nm[0][0] or '' + + if not nm: + return 'No' # VALIDATE # ===================================================================================== - # Fiscal Year Validation - # ---------------------- - def validate_fiscal_year(self): - get_obj('Sales Common').validate_fiscal_year(self.doc.fiscal_year,self.doc.transaction_date,'Sales Order Date') - - # Validate values with reference document - #---------------------------------------- - def validate_reference_value(self): - get_obj('DocType Mapper', 'Quotation-Sales Order', with_children = 1).validate_reference_value(self, self.doc.name) + # Fiscal Year Validation + # ---------------------- + def validate_fiscal_year(self): + get_obj('Sales Common').validate_fiscal_year(self.doc.fiscal_year,self.doc.transaction_date,'Sales Order Date') + + # Validate values with reference document + #---------------------------------------- + def validate_reference_value(self): + get_obj('DocType Mapper', 'Quotation-Sales Order', with_children = 1).validate_reference_value(self, self.doc.name) - # Validate Mandatory - # ------------------- - def validate_mandatory(self): - # validate transaction date v/s delivery date - if self.doc.delivery_date: - if getdate(self.doc.transaction_date) > getdate(self.doc.delivery_date): - msgprint("Expected Delivery Date cannot be before Sales Order Date") - raise Exception + # Validate Mandatory + # ------------------- + def validate_mandatory(self): + # validate transaction date v/s delivery date + if self.doc.delivery_date: + if getdate(self.doc.transaction_date) > getdate(self.doc.delivery_date): + msgprint("Expected Delivery Date cannot be before Sales Order Date") + raise Exception - # Validate P.O Date - # ------------------ - def validate_po_date(self): - # validate p.o date v/s delivery date - if self.doc.po_date and self.doc.delivery_date and getdate(self.doc.po_date) >= getdate(self.doc.delivery_date): - msgprint("Expected Delivery Date cannot be before Purchase Order Date") - raise Exception - # amendment date is necessary if document is amended - if self.doc.amended_from and not self.doc.amendment_date: - msgprint("Please Enter Amendment Date") - raise Exception - - # Validations of Details Table - # ----------------------------- - def validate_for_items(self): - check_list,flag = [],0 - chk_dupl_itm = [] - # Sales Order Details Validations - for d in getlist(self.doclist, 'sales_order_details'): - if cstr(self.doc.quotation_no) == cstr(d.prevdoc_docname): - flag = 1 - if d.prevdoc_docname: - if self.doc.quotation_date and getdate(self.doc.quotation_date) > getdate(self.doc.transaction_date): - msgprint("Sales Order Date cannot be before Quotation Date") - raise Exception - # validates whether quotation no in doctype and in table is same - if not cstr(d.prevdoc_docname) == cstr(self.doc.quotation_no): - msgprint("Items in table does not belong to the Quotation No mentioned.") - raise Exception + # Validate P.O Date + # ------------------ + def validate_po_date(self): + # validate p.o date v/s delivery date + if self.doc.po_date and self.doc.delivery_date and getdate(self.doc.po_date) >= getdate(self.doc.delivery_date): + msgprint("Expected Delivery Date cannot be before Purchase Order Date") + raise Exception + # amendment date is necessary if document is amended + if self.doc.amended_from and not self.doc.amendment_date: + msgprint("Please Enter Amendment Date") + raise Exception + + # Validations of Details Table + # ----------------------------- + def validate_for_items(self): + check_list,flag = [],0 + chk_dupl_itm = [] + # Sales Order Details Validations + for d in getlist(self.doclist, 'sales_order_details'): + if cstr(self.doc.quotation_no) == cstr(d.prevdoc_docname): + flag = 1 + if d.prevdoc_docname: + if self.doc.quotation_date and getdate(self.doc.quotation_date) > getdate(self.doc.transaction_date): + msgprint("Sales Order Date cannot be before Quotation Date") + raise Exception + # validates whether quotation no in doctype and in table is same + if not cstr(d.prevdoc_docname) == cstr(self.doc.quotation_no): + msgprint("Items in table does not belong to the Quotation No mentioned.") + raise Exception - # validates whether item is not entered twice - e = [d.item_code, d.description, d.reserved_warehouse, d.prevdoc_docname or ''] - f = [d.item_code, d.description] + # validates whether item is not entered twice + e = [d.item_code, d.description, d.reserved_warehouse, d.prevdoc_docname or ''] + f = [d.item_code, d.description] - #check item is stock item - st_itm = sql("select is_stock_item from `tabItem` where name = '%s'"%d.item_code) + #check item is stock item + st_itm = sql("select is_stock_item from `tabItem` where name = '%s'"%d.item_code) - if st_itm and st_itm[0][0] == 'Yes': - if e in check_list: - msgprint("Item %s has been entered twice." % d.item_code) - else: - check_list.append(e) - elif st_itm and st_itm[0][0]== 'No': - if f in chk_dupl_itm: - msgprint("Item %s has been entered twice." % d.item_code) - else: - chk_dupl_itm.append(f) + if st_itm and st_itm[0][0] == 'Yes': + if e in check_list: + msgprint("Item %s has been entered twice." % d.item_code) + else: + check_list.append(e) + elif st_itm and st_itm[0][0]== 'No': + if f in chk_dupl_itm: + msgprint("Item %s has been entered twice." % d.item_code) + else: + chk_dupl_itm.append(f) - # used for production plan - d.transaction_date = self.doc.transaction_date - d.delivery_date = self.doc.delivery_date + # used for production plan + d.transaction_date = self.doc.transaction_date + d.delivery_date = self.doc.delivery_date - # gets total projected qty of item in warehouse selected (this case arises when warehouse is selected b4 item) - tot_avail_qty = sql("select projected_qty from `tabBin` where item_code = '%s' and warehouse = '%s'" % (d.item_code,d.reserved_warehouse)) - d.projected_qty = tot_avail_qty and flt(tot_avail_qty[0][0]) or 0 - - if flag == 0: - msgprint("There are no items of the quotation selected.") - raise Exception + # gets total projected qty of item in warehouse selected (this case arises when warehouse is selected b4 item) + tot_avail_qty = sql("select projected_qty from `tabBin` where item_code = '%s' and warehouse = '%s'" % (d.item_code,d.reserved_warehouse)) + d.projected_qty = tot_avail_qty and flt(tot_avail_qty[0][0]) or 0 + + if flag == 0: + msgprint("There are no items of the quotation selected.") + raise Exception - # validate sales/ service item against order type - #---------------------------------------------------- - def validate_sales_mntc_item(self): - if self.doc.order_type == 'Maintenance': - item_field = 'is_service_item' - order_type = 'Maintenance Order' - item_type = 'service item' - else : - item_field = 'is_sales_item' - order_type = 'Sales Order' - item_type = 'sales item' - - for d in getlist(self.doclist, 'sales_order_details'): - res = sql("select %s from `tabItem` where name='%s'"% (item_field,d.item_code)) - res = res and res[0][0] or 'No' - - if res == 'No': - msgprint("You can not select non "+item_type+" "+d.item_code+" in "+order_type) - raise Exception - - # validate sales/ maintenance quotation against order type - #------------------------------------------------------------------ - def validate_sales_mntc_quotation(self): - for d in getlist(self.doclist, 'sales_order_details'): - if d.prevdoc_docname: - res = sql("select order_type from `tabQuotation` where name=%s", (d.prevdoc_docname)) - res = res and res[0][0] or '' - - if self.doc.order_type== 'Maintenance' and res != 'Maintenance': - msgprint("You can not select non Maintenance Quotation against Maintenance Order") - raise Exception - elif self.doc.order_type != 'Maintenance' and res == 'Maintenance': - msgprint("You can not select non Sales Quotation against Sales Order") - raise Exception + # validate sales/ service item against order type + #---------------------------------------------------- + def validate_sales_mntc_item(self): + if self.doc.order_type == 'Maintenance': + item_field = 'is_service_item' + order_type = 'Maintenance Order' + item_type = 'service item' + else : + item_field = 'is_sales_item' + order_type = 'Sales Order' + item_type = 'sales item' + + for d in getlist(self.doclist, 'sales_order_details'): + res = sql("select %s from `tabItem` where name='%s'"% (item_field,d.item_code)) + res = res and res[0][0] or 'No' + + if res == 'No': + msgprint("You can not select non "+item_type+" "+d.item_code+" in "+order_type) + raise Exception + + # validate sales/ maintenance quotation against order type + #------------------------------------------------------------------ + def validate_sales_mntc_quotation(self): + for d in getlist(self.doclist, 'sales_order_details'): + if d.prevdoc_docname: + res = sql("select order_type from `tabQuotation` where name=%s", (d.prevdoc_docname)) + res = res and res[0][0] or '' + + if self.doc.order_type== 'Maintenance' and res != 'Maintenance': + msgprint("You can not select non Maintenance Quotation against Maintenance Order") + raise Exception + elif self.doc.order_type != 'Maintenance' and res == 'Maintenance': + msgprint("You can not select non Sales Quotation against Sales Order") + raise Exception - #do not allow sales item/quotation in maintenance order and service item/quotation in sales order - #----------------------------------------------------------------------------------------------- - def validate_order_type(self): - #validate delivery date - if self.doc.order_type != 'Maintenance' and not self.doc.delivery_date: - msgprint("Please enter 'Expected Delivery Date'") - raise Exception - - self.validate_sales_mntc_quotation() - self.validate_sales_mntc_item() + #do not allow sales item/quotation in maintenance order and service item/quotation in sales order + #----------------------------------------------------------------------------------------------- + def validate_order_type(self): + #validate delivery date + if self.doc.order_type != 'Maintenance' and not self.doc.delivery_date: + msgprint("Please enter 'Expected Delivery Date'") + raise Exception + + self.validate_sales_mntc_quotation() + self.validate_sales_mntc_item() - #check for does customer belong to same project as entered.. - #------------------------------------------------------------------------------------------------- - def validate_proj_cust(self): - if self.doc.project_name and self.doc.customer_name: - res = sql("select name from `tabProject` where name = '%s' and (customer = '%s' or ifnull(customer,'')='')"%(self.doc.project_name, self.doc.customer)) - if not res: - msgprint("Customer - %s does not belong to project - %s. \n\nIf you want to use project for multiple customers then please make customer details blank in project - %s."%(self.doc.customer,self.doc.project_name,self.doc.project_name)) - raise Exception - + #check for does customer belong to same project as entered.. + #------------------------------------------------------------------------------------------------- + def validate_proj_cust(self): + if self.doc.project_name and self.doc.customer_name: + res = sql("select name from `tabProject` where name = '%s' and (customer = '%s' or ifnull(customer,'')='')"%(self.doc.project_name, self.doc.customer)) + if not res: + msgprint("Customer - %s does not belong to project - %s. \n\nIf you want to use project for multiple customers then please make customer details blank in project - %s."%(self.doc.customer,self.doc.project_name,self.doc.project_name)) + raise Exception + - # Validate - # --------- - def validate(self): - self.validate_fiscal_year() - self.validate_order_type() - self.validate_mandatory() - self.validate_proj_cust() - self.validate_po_date() - #self.validate_reference_value() - self.validate_for_items() - sales_com_obj = get_obj(dt = 'Sales Common') - sales_com_obj.check_active_sales_items(self) - sales_com_obj.check_conversion_rate(self) + # Validate + # --------- + def validate(self): + self.validate_fiscal_year() + self.validate_order_type() + self.validate_mandatory() + self.validate_proj_cust() + self.validate_po_date() + #self.validate_reference_value() + self.validate_for_items() + sales_com_obj = get_obj(dt = 'Sales Common') + sales_com_obj.check_active_sales_items(self) + sales_com_obj.check_conversion_rate(self) - # verify whether rate is not greater than max_discount - sales_com_obj.validate_max_discount(self,'sales_order_details') - # this is to verify that the allocated % of sales persons is 100% - sales_com_obj.get_allocated_sum(self) - sales_com_obj.make_packing_list(self,'sales_order_details') - - # get total in words - dcc = TransactionBase().get_company_currency(self.doc.company) - self.doc.in_words = sales_com_obj.get_total_in_words(dcc, self.doc.rounded_total) - self.doc.in_words_export = sales_com_obj.get_total_in_words(self.doc.currency, self.doc.rounded_total_export) - - # set SO status - self.doc.status='Draft' - if not self.doc.billing_status: self.doc.billing_status = 'Not Billed' - if not self.doc.delivery_status: self.doc.delivery_status = 'Not Delivered' - + # verify whether rate is not greater than max_discount + sales_com_obj.validate_max_discount(self,'sales_order_details') + # this is to verify that the allocated % of sales persons is 100% + sales_com_obj.get_allocated_sum(self) + sales_com_obj.make_packing_list(self,'sales_order_details') + + # get total in words + dcc = TransactionBase().get_company_currency(self.doc.company) + self.doc.in_words = sales_com_obj.get_total_in_words(dcc, self.doc.rounded_total) + self.doc.in_words_export = sales_com_obj.get_total_in_words(self.doc.currency, self.doc.rounded_total_export) + + # set SO status + self.doc.status='Draft' + if not self.doc.billing_status: self.doc.billing_status = 'Not Billed' + if not self.doc.delivery_status: self.doc.delivery_status = 'Not Delivered' + # ON SUBMIT # =============================================================================================== - # Checks Quotation Status - # ------------------------ - def check_prev_docstatus(self): - for d in getlist(self.doclist, 'sales_order_details'): - cancel_quo = sql("select name from `tabQuotation` where docstatus = 2 and name = '%s'" % d.prevdoc_docname) - if cancel_quo: - msgprint("Quotation :" + cstr(cancel_quo[0][0]) + " is already cancelled !") - raise Exception , "Validation Error. " - - def update_enquiry_status(self, prevdoc, flag): - enq = sql("select t2.prevdoc_docname from `tabQuotation` t1, `tabQuotation Detail` t2 where t2.parent = t1.name and t1.name=%s", prevdoc) - if enq: - sql("update `tabEnquiry` set status = %s where name=%s",(flag,enq[0][0])) + # Checks Quotation Status + # ------------------------ + def check_prev_docstatus(self): + for d in getlist(self.doclist, 'sales_order_details'): + cancel_quo = sql("select name from `tabQuotation` where docstatus = 2 and name = '%s'" % d.prevdoc_docname) + if cancel_quo: + msgprint("Quotation :" + cstr(cancel_quo[0][0]) + " is already cancelled !") + raise Exception , "Validation Error. " + + def update_enquiry_status(self, prevdoc, flag): + enq = sql("select t2.prevdoc_docname from `tabQuotation` t1, `tabQuotation Detail` t2 where t2.parent = t1.name and t1.name=%s", prevdoc) + if enq: + sql("update `tabEnquiry` set status = %s where name=%s",(flag,enq[0][0])) - #update status of quotation, enquiry - #---------------------------------------- - def update_prevdoc_status(self, flag): - for d in getlist(self.doclist, 'sales_order_details'): - if d.prevdoc_docname: - if flag=='submit': - sql("update `tabQuotation` set status = 'Order Confirmed' where name=%s",d.prevdoc_docname) - - #update enquiry - self.update_enquiry_status(d.prevdoc_docname, 'Order Confirmed') - elif flag == 'cancel': - chk = sql("select t1.name from `tabSales Order` t1, `tabSales Order Detail` t2 where t2.parent = t1.name and t2.prevdoc_docname=%s and t1.name!=%s and t1.docstatus=1", (d.prevdoc_docname,self.doc.name)) - if not chk: - sql("update `tabQuotation` set status = 'Submitted' where name=%s",d.prevdoc_docname) - - #update enquiry - self.update_enquiry_status(d.prevdoc_docname, 'Quotation Sent') - - # Submit - # ------- - def on_submit(self): - self.check_prev_docstatus() - self.update_stock_ledger(update_stock = 1) - self.set_sms_msg(1) - # update customer's last sales order no. - update_customer = sql("update `tabCustomer` set last_sales_order = '%s', modified = '%s' where name = '%s'" %(self.doc.name, self.doc.modified, self.doc.customer)) - get_obj('Sales Common').check_credit(self,self.doc.grand_total) - - # Check for Approving Authority - get_obj('Authorization Control').validate_approving_authority(self.doc.doctype, self.doc.grand_total, self) - - #update prevdoc status - self.update_prevdoc_status('submit') - # set SO status - set(self.doc, 'status', 'Submitted') - - # on submit notification - if self.doc.email_id: - get_obj('Notification Control').notify_contact('Sales Order',self.doc.doctype,self.doc.name, self.doc.email_id, self.doc.contact_person) - + #update status of quotation, enquiry + #---------------------------------------- + def update_prevdoc_status(self, flag): + for d in getlist(self.doclist, 'sales_order_details'): + if d.prevdoc_docname: + if flag=='submit': + sql("update `tabQuotation` set status = 'Order Confirmed' where name=%s",d.prevdoc_docname) + + #update enquiry + self.update_enquiry_status(d.prevdoc_docname, 'Order Confirmed') + elif flag == 'cancel': + chk = sql("select t1.name from `tabSales Order` t1, `tabSales Order Detail` t2 where t2.parent = t1.name and t2.prevdoc_docname=%s and t1.name!=%s and t1.docstatus=1", (d.prevdoc_docname,self.doc.name)) + if not chk: + sql("update `tabQuotation` set status = 'Submitted' where name=%s",d.prevdoc_docname) + + #update enquiry + self.update_enquiry_status(d.prevdoc_docname, 'Quotation Sent') + + # Submit + # ------- + def on_submit(self): + self.check_prev_docstatus() + self.update_stock_ledger(update_stock = 1) + self.set_sms_msg(1) + # update customer's last sales order no. + update_customer = sql("update `tabCustomer` set last_sales_order = '%s', modified = '%s' where name = '%s'" %(self.doc.name, self.doc.modified, self.doc.customer)) + get_obj('Sales Common').check_credit(self,self.doc.grand_total) + + # Check for Approving Authority + get_obj('Authorization Control').validate_approving_authority(self.doc.doctype, self.doc.grand_total, self) + + #update prevdoc status + self.update_prevdoc_status('submit') + # set SO status + set(self.doc, 'status', 'Submitted') + + # on submit notification + if self.doc.email_id: + get_obj('Notification Control').notify_contact('Sales Order',self.doc.doctype,self.doc.name, self.doc.email_id, self.doc.contact_person) + # ON CANCEL # =============================================================================================== - def on_cancel(self): - # Cannot cancel stopped SO - if self.doc.status == 'Stopped': - msgprint("Sales Order : '%s' cannot be cancelled as it is Stopped. Unstop it for any further transactions" %(self.doc.name)) - raise Exception - self.check_nextdoc_docstatus() - self.update_stock_ledger(update_stock = -1) - self.set_sms_msg() - - #update prevdoc status - self.update_prevdoc_status('cancel') - - # ::::::::: SET SO STATUS :::::::::: - set(self.doc, 'status', 'Cancelled') - - # CHECK NEXT DOCSTATUS - # does not allow to cancel document if DN or RV made against it is SUBMITTED - # ---------------------------------------------------------------------------- - def check_nextdoc_docstatus(self): - # Checks Delivery Note - submit_dn = sql("select t1.name from `tabDelivery Note` t1,`tabDelivery Note Detail` t2 where t1.name = t2.parent and t2.prevdoc_docname = '%s' and t1.docstatus = 1" % (self.doc.name)) - if submit_dn: - msgprint("Delivery Note : " + cstr(submit_dn[0][0]) + " has been submitted against " + cstr(self.doc.doctype) + ". Please cancel Delivery Note : " + cstr(submit_dn[0][0]) + " first and then cancel "+ cstr(self.doc.doctype), raise_exception = 1) - # Checks Receivable Voucher - submit_rv = sql("select t1.name from `tabReceivable Voucher` t1,`tabRV Detail` t2 where t1.name = t2.parent and t2.sales_order = '%s' and t1.docstatus = 1" % (self.doc.name)) - if submit_rv: - msgprint("Sales Invoice : " + cstr(submit_rv[0][0]) + " has already been submitted against " +cstr(self.doc.doctype)+ ". Please cancel Sales Invoice : "+ cstr(submit_rv[0][0]) + " first and then cancel "+ cstr(self.doc.doctype), raise_exception = 1) - #check maintenance schedule - submit_ms = sql("select t1.name from `tabMaintenance Schedule` t1, `tabItem Maintenance Detail` t2 where t2.parent=t1.name and t2.prevdoc_docname = %s and t1.docstatus = 1",self.doc.name) - if submit_ms: - msgprint("Maintenance Schedule : " + cstr(submit_ms[0][0]) + " has already been submitted against " +cstr(self.doc.doctype)+ ". Please cancel Maintenance Schedule : "+ cstr(submit_ms[0][0]) + " first and then cancel "+ cstr(self.doc.doctype), raise_exception = 1) - submit_mv = sql("select t1.name from `tabMaintenance Visit` t1, `tabMaintenance Visit Detail` t2 where t2.parent=t1.name and t2.prevdoc_docname = %s and t1.docstatus = 1",self.doc.name) - if submit_mv: - msgprint("Maintenance Visit : " + cstr(submit_mv[0][0]) + " has already been submitted against " +cstr(self.doc.doctype)+ ". Please cancel Maintenance Visit : " + cstr(submit_mv[0][0]) + " first and then cancel "+ cstr(self.doc.doctype), raise_exception = 1) + def on_cancel(self): + # Cannot cancel stopped SO + if self.doc.status == 'Stopped': + msgprint("Sales Order : '%s' cannot be cancelled as it is Stopped. Unstop it for any further transactions" %(self.doc.name)) + raise Exception + self.check_nextdoc_docstatus() + self.update_stock_ledger(update_stock = -1) + self.set_sms_msg() + + #update prevdoc status + self.update_prevdoc_status('cancel') + + # ::::::::: SET SO STATUS :::::::::: + set(self.doc, 'status', 'Cancelled') + + # CHECK NEXT DOCSTATUS + # does not allow to cancel document if DN or RV made against it is SUBMITTED + # ---------------------------------------------------------------------------- + def check_nextdoc_docstatus(self): + # Checks Delivery Note + submit_dn = sql("select t1.name from `tabDelivery Note` t1,`tabDelivery Note Detail` t2 where t1.name = t2.parent and t2.prevdoc_docname = '%s' and t1.docstatus = 1" % (self.doc.name)) + if submit_dn: + msgprint("Delivery Note : " + cstr(submit_dn[0][0]) + " has been submitted against " + cstr(self.doc.doctype) + ". Please cancel Delivery Note : " + cstr(submit_dn[0][0]) + " first and then cancel "+ cstr(self.doc.doctype), raise_exception = 1) + # Checks Receivable Voucher + submit_rv = sql("select t1.name from `tabReceivable Voucher` t1,`tabRV Detail` t2 where t1.name = t2.parent and t2.sales_order = '%s' and t1.docstatus = 1" % (self.doc.name)) + if submit_rv: + msgprint("Sales Invoice : " + cstr(submit_rv[0][0]) + " has already been submitted against " +cstr(self.doc.doctype)+ ". Please cancel Sales Invoice : "+ cstr(submit_rv[0][0]) + " first and then cancel "+ cstr(self.doc.doctype), raise_exception = 1) + #check maintenance schedule + submit_ms = sql("select t1.name from `tabMaintenance Schedule` t1, `tabItem Maintenance Detail` t2 where t2.parent=t1.name and t2.prevdoc_docname = %s and t1.docstatus = 1",self.doc.name) + if submit_ms: + msgprint("Maintenance Schedule : " + cstr(submit_ms[0][0]) + " has already been submitted against " +cstr(self.doc.doctype)+ ". Please cancel Maintenance Schedule : "+ cstr(submit_ms[0][0]) + " first and then cancel "+ cstr(self.doc.doctype), raise_exception = 1) + submit_mv = sql("select t1.name from `tabMaintenance Visit` t1, `tabMaintenance Visit Detail` t2 where t2.parent=t1.name and t2.prevdoc_docname = %s and t1.docstatus = 1",self.doc.name) + if submit_mv: + msgprint("Maintenance Visit : " + cstr(submit_mv[0][0]) + " has already been submitted against " +cstr(self.doc.doctype)+ ". Please cancel Maintenance Visit : " + cstr(submit_mv[0][0]) + " first and then cancel "+ cstr(self.doc.doctype), raise_exception = 1) - def check_modified_date(self): - mod_db = sql("select modified from `tabSales Order` where name = '%s'" % self.doc.name) - date_diff = sql("select TIMEDIFF('%s', '%s')" % ( mod_db[0][0],cstr(self.doc.modified))) - - if date_diff and date_diff[0][0]: - msgprint(cstr(self.doc.doctype) +" => "+ cstr(self.doc.name) +" has been modified. Please Refresh. ") - raise Exception + def check_modified_date(self): + mod_db = sql("select modified from `tabSales Order` where name = '%s'" % self.doc.name) + date_diff = sql("select TIMEDIFF('%s', '%s')" % ( mod_db[0][0],cstr(self.doc.modified))) + + if date_diff and date_diff[0][0]: + msgprint(cstr(self.doc.doctype) +" => "+ cstr(self.doc.name) +" has been modified. Please Refresh. ") + raise Exception - # STOP SALES ORDER - # ============================================================================================== - # Stops Sales Order & no more transactions will be created against this Sales Order - def stop_sales_order(self): - self.check_modified_date() - self.update_stock_ledger(update_stock = -1,clear = 1) - # ::::::::: SET SO STATUS :::::::::: - set(self.doc, 'status', 'Stopped') - msgprint(self.doc.doctype + ": " + self.doc.name + " has been Stopped. To make transactions against this Sales Order you need to Unstop it.") + # STOP SALES ORDER + # ============================================================================================== + # Stops Sales Order & no more transactions will be created against this Sales Order + def stop_sales_order(self): + self.check_modified_date() + self.update_stock_ledger(update_stock = -1,clear = 1) + # ::::::::: SET SO STATUS :::::::::: + set(self.doc, 'status', 'Stopped') + msgprint(self.doc.doctype + ": " + self.doc.name + " has been Stopped. To make transactions against this Sales Order you need to Unstop it.") - # UNSTOP SALES ORDER - # ============================================================================================== - # Unstops Sales Order & now transactions can be continued against this Sales Order - def unstop_sales_order(self): - self.check_modified_date() - self.update_stock_ledger(update_stock = 1,clear = 1) - # ::::::::: SET SO STATUS :::::::::: - set(self.doc, 'status', 'Submitted') - msgprint(self.doc.doctype + ": " + self.doc.name + " has been Unstopped.") + # UNSTOP SALES ORDER + # ============================================================================================== + # Unstops Sales Order & now transactions can be continued against this Sales Order + def unstop_sales_order(self): + self.check_modified_date() + self.update_stock_ledger(update_stock = 1,clear = 1) + # ::::::::: SET SO STATUS :::::::::: + set(self.doc, 'status', 'Submitted') + msgprint(self.doc.doctype + ": " + self.doc.name + " has been Unstopped.") - # UPDATE STOCK LEDGER - # =============================================================================================== - def update_stock_ledger(self, update_stock, clear = 0): - for d in self.get_item_list(clear): - stock_item = sql("SELECT is_stock_item FROM tabItem where name = '%s'"%(d[1]),as_dict = 1) # stock ledger will be updated only if it is a stock item - if stock_item and stock_item[0]['is_stock_item'] == "Yes": - if not d[0]: - msgprint("Message: Please enter Reserved Warehouse for item %s as it is stock item."% d[1]) - raise Exception - bin = get_obj('Warehouse', d[0]).update_bin( 0, flt(update_stock) * flt(d[2]), 0, 0, 0, d[1], self.doc.transaction_date) + # UPDATE STOCK LEDGER + # =============================================================================================== + def update_stock_ledger(self, update_stock, clear = 0): + for d in self.get_item_list(clear): + stock_item = sql("SELECT is_stock_item FROM tabItem where name = '%s'"%(d[1]),as_dict = 1) # stock ledger will be updated only if it is a stock item + if stock_item and stock_item[0]['is_stock_item'] == "Yes": + if not d[0]: + msgprint("Message: Please enter Reserved Warehouse for item %s as it is stock item."% d[1]) + raise Exception + bin = get_obj('Warehouse', d[0]).update_bin( 0, flt(update_stock) * flt(d[2]), 0, 0, 0, d[1], self.doc.transaction_date) + + # Gets Items from packing list + #================================= + def get_item_list(self, clear): + return get_obj('Sales Common').get_item_list( self, clear) + + # SET MESSAGE FOR SMS + #====================== + def set_sms_msg(self, is_submitted = 0): + if is_submitted: + if not self.doc.amended_from: + msg = 'Sales Order: '+self.doc.name+' has been made against PO no: '+cstr(self.doc.po_no) + set(self.doc, 'message', msg) + else: + msg = 'Sales Order has been amended. New SO no:'+self.doc.name + set(self.doc, 'message', msg) + else: + msg = 'Sales Order: '+self.doc.name+' has been cancelled.' + set(self.doc, 'message', msg) + + # SEND SMS + # ========= + def send_sms(self): + if not self.doc.customer_mobile_no: + msgprint("Please enter customer mobile no") + elif not self.doc.message: + msgprint("Please enter the message you want to send") + else: + msgprint(get_obj("SMS Control", "SMS Control").send_sms([self.doc.customer_mobile_no,], self.doc.message)) - # Gets Items from packing list - #================================= - def get_item_list(self, clear): - return get_obj('Sales Common').get_item_list( self, clear) - - # SET MESSAGE FOR SMS - #====================== - def set_sms_msg(self, is_submitted = 0): - if is_submitted: - if not self.doc.amended_from: - msg = 'Sales Order: '+self.doc.name+' has been made against PO no: '+cstr(self.doc.po_no) - set(self.doc, 'message', msg) - else: - msg = 'Sales Order has been amended. New SO no:'+self.doc.name - set(self.doc, 'message', msg) - else: - msg = 'Sales Order: '+self.doc.name+' has been cancelled.' - set(self.doc, 'message', msg) - - # SEND SMS - # ========= - def send_sms(self): - if not self.doc.customer_mobile_no: - msgprint("Please enter customer mobile no") - elif not self.doc.message: - msgprint("Please enter the message you want to send") - else: - msgprint(get_obj("SMS Control", "SMS Control").send_sms([self.doc.customer_mobile_no,], self.doc.message)) + # on update + def on_update(self): + pass - # on update - def on_update(self): - pass - - # Repair Sales Order - # =========================================== - def repair_sales_order(self): - get_obj('Sales Common', 'Sales Common').repair_curr_doctype_details(self) + # Repair Sales Order + # =========================================== + def repair_sales_order(self): + get_obj('Sales Common', 'Sales Common').repair_curr_doctype_details(self) diff --git a/selling/doctype/sales_order/sales_order.txt b/selling/doctype/sales_order/sales_order.txt index 69773ddf72a..98833d17ce7 100644 --- a/selling/doctype/sales_order/sales_order.txt +++ b/selling/doctype/sales_order/sales_order.txt @@ -5,15 +5,14 @@ { 'creation': '2010-08-08 17:09:21', 'docstatus': 0, - 'modified': '2011-06-27 16:05:56', + 'modified': '2011-08-09 17:06:09', 'modified_by': 'Administrator', 'owner': 'Administrator' }, # These values are common for all DocType { - '_last_update': '1309170956', - 'client_script': "cur_frm.add_fetch('customer','sales_person','sales_person');", + '_last_update': '1311621379', 'colour': 'White:FFF', 'doctype': 'DocType', 'document_type': 'Transaction', @@ -28,7 +27,7 @@ 'show_in_menu': 0, 'subject': 'From %(customer_name)s on %(transaction_date)s worth %(currency)s %(grand_total_export)s | %(per_delivered)s% delivered | %(per_billed)s% billed', 'tag_fields': 'delivery_status,billing_status', - 'version': 593 + 'version': 597 }, # These values are common for all DocField @@ -58,28 +57,23 @@ # DocPerm { - 'amend': 0, - 'cancel': 0, - 'create': 0, 'doctype': 'DocPerm', 'idx': 1, - 'permlevel': 1, - 'role': 'Sales Manager', - 'submit': 0, - 'write': 0 + 'permlevel': 0, + 'role': 'Production Manager' }, # DocPerm { - 'amend': 1, - 'cancel': 1, - 'create': 1, + 'amend': 0, + 'cancel': 0, + 'create': 0, 'doctype': 'DocPerm', 'idx': 2, - 'permlevel': 0, + 'permlevel': 1, 'role': 'Sales Manager', - 'submit': 1, - 'write': 1 + 'submit': 0, + 'write': 0 }, # DocPerm @@ -90,6 +84,19 @@ 'doctype': 'DocPerm', 'idx': 3, 'permlevel': 0, + 'role': 'Sales Manager', + 'submit': 1, + 'write': 1 + }, + + # DocPerm + { + 'amend': 1, + 'cancel': 1, + 'create': 1, + 'doctype': 'DocPerm', + 'idx': 4, + 'permlevel': 0, 'role': 'Sales User', 'submit': 1, 'write': 1 @@ -101,7 +108,7 @@ 'cancel': 0, 'create': 0, 'doctype': 'DocPerm', - 'idx': 4, + 'idx': 5, 'permlevel': 1, 'role': 'Sales User', 'submit': 0, @@ -111,7 +118,7 @@ # DocPerm { 'doctype': 'DocPerm', - 'idx': 5, + 'idx': 6, 'match': 'customer_name', 'permlevel': 0, 'role': 'Customer' @@ -120,7 +127,7 @@ # DocPerm { 'doctype': 'DocPerm', - 'idx': 6, + 'idx': 7, 'permlevel': 2, 'role': 'Accounts User', 'write': 1 @@ -132,7 +139,7 @@ 'cancel': 1, 'create': 1, 'doctype': 'DocPerm', - 'idx': 7, + 'idx': 8, 'permlevel': 0, 'role': 'Maintenance Manager', 'submit': 1, @@ -142,7 +149,7 @@ # DocPerm { 'doctype': 'DocPerm', - 'idx': 8, + 'idx': 9, 'permlevel': 1, 'role': 'Maintenance Manager' }, @@ -153,7 +160,7 @@ 'cancel': 1, 'create': 1, 'doctype': 'DocPerm', - 'idx': 9, + 'idx': 10, 'permlevel': 0, 'role': 'Maintenance User', 'submit': 1, @@ -163,7 +170,7 @@ # DocPerm { 'doctype': 'DocPerm', - 'idx': 10, + 'idx': 11, 'permlevel': 1, 'role': 'Maintenance User' }, @@ -204,7 +211,7 @@ 'no_copy': 1, 'oldfieldname': 'naming_series', 'oldfieldtype': 'Select', - 'options': 'SO\nSO/10-11/', + 'options': 'PI/2011/\nSO\nSO/10-11/\nSO1112', 'permlevel': 0, 'print_hide': 1, 'reqd': 1 @@ -504,7 +511,7 @@ 'fieldtype': 'Currency', 'idx': 23, 'in_filter': 1, - 'label': '% Qty Billed', + 'label': '% Amount Billed', 'no_copy': 1, 'oldfieldname': 'per_billed', 'oldfieldtype': 'Currency', @@ -605,6 +612,16 @@ 'width': '150px' }, + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'vehicle_detail', + 'fieldtype': 'Small Text', + 'idx': 30, + 'label': 'Vehicle Detail', + 'permlevel': 0 + }, + # DocField { 'colour': 'White:FFF', @@ -612,7 +629,7 @@ 'fieldname': 'quotation_date', 'fieldtype': 'Date', 'hidden': 1, - 'idx': 30, + 'idx': 31, 'label': 'Quotation Date', 'no_copy': 0, 'oldfieldname': 'quotation_date', @@ -627,7 +644,7 @@ { 'doctype': 'DocField', 'fieldtype': 'Button', - 'idx': 31, + 'idx': 32, 'label': 'Pull Quotation Details', 'oldfieldtype': 'Button', 'options': 'pull_quotation_details', @@ -642,7 +659,7 @@ 'doctype': 'DocField', 'fieldname': 'price_list_name', 'fieldtype': 'Select', - 'idx': 32, + 'idx': 33, 'label': 'Price List', 'oldfieldname': 'price_list_name', 'oldfieldtype': 'Select', @@ -658,7 +675,7 @@ { 'doctype': 'DocField', 'fieldtype': 'Column Break', - 'idx': 33, + 'idx': 34, 'permlevel': 0, 'width': '50%' }, @@ -670,7 +687,7 @@ 'doctype': 'DocField', 'fieldname': 'currency', 'fieldtype': 'Select', - 'idx': 34, + 'idx': 35, 'label': 'Currency', 'oldfieldname': 'currency', 'oldfieldtype': 'Select', @@ -689,7 +706,7 @@ 'doctype': 'DocField', 'fieldname': 'conversion_rate', 'fieldtype': 'Currency', - 'idx': 35, + 'idx': 36, 'label': 'Conversion Rate', 'oldfieldname': 'conversion_rate', 'oldfieldtype': 'Currency', @@ -704,7 +721,7 @@ { 'doctype': 'DocField', 'fieldtype': 'Section Break', - 'idx': 36, + 'idx': 37, 'permlevel': 0 }, @@ -715,7 +732,7 @@ 'doctype': 'DocField', 'fieldname': 'sales_order_details', 'fieldtype': 'Table', - 'idx': 37, + 'idx': 38, 'label': 'Sales Order Details', 'oldfieldname': 'sales_order_details', 'oldfieldtype': 'Table', @@ -729,7 +746,7 @@ { 'doctype': 'DocField', 'fieldtype': 'Button', - 'idx': 38, + 'idx': 39, 'label': 'Clear Table', 'oldfieldtype': 'Button', 'options': 'clear_sales_order_details', @@ -741,7 +758,7 @@ { 'doctype': 'DocField', 'fieldtype': 'Button', - 'idx': 39, + 'idx': 40, 'label': 'Re-Calculate Values', 'oldfieldtype': 'Button', 'permlevel': 0, @@ -755,7 +772,7 @@ 'doctype': 'DocField', 'fieldname': 'net_total', 'fieldtype': 'Currency', - 'idx': 40, + 'idx': 41, 'label': 'Net Total*', 'oldfieldname': 'net_total', 'oldfieldtype': 'Currency', @@ -770,7 +787,7 @@ 'colour': 'White:FFF', 'doctype': 'DocField', 'fieldtype': 'HTML', - 'idx': 41, + 'idx': 42, 'label': 'Note1', 'oldfieldtype': 'HTML', 'options': 'NOTE : * In Base Currency', @@ -783,7 +800,7 @@ 'colour': 'White:FFF', 'doctype': 'DocField', 'fieldtype': 'Section Break', - 'idx': 42, + 'idx': 43, 'label': 'Taxes', 'oldfieldtype': 'Section Break', 'permlevel': 0, @@ -795,7 +812,7 @@ 'doctype': 'DocField', 'fieldname': 'charge', 'fieldtype': 'Link', - 'idx': 43, + 'idx': 44, 'label': 'Select Charges Master', 'oldfieldname': 'charge', 'oldfieldtype': 'Link', @@ -808,7 +825,7 @@ { 'doctype': 'DocField', 'fieldtype': 'Button', - 'idx': 44, + 'idx': 45, 'label': 'Get Charges', 'oldfieldtype': 'Button', 'permlevel': 0, @@ -820,7 +837,7 @@ 'doctype': 'DocField', 'fieldname': 'other_charges', 'fieldtype': 'Table', - 'idx': 45, + 'idx': 46, 'label': 'Other Charges', 'oldfieldname': 'other_charges', 'oldfieldtype': 'Table', @@ -832,7 +849,7 @@ { 'doctype': 'DocField', 'fieldtype': 'Button', - 'idx': 46, + 'idx': 47, 'label': 'Calculate Charges', 'oldfieldtype': 'Button', 'permlevel': 0, @@ -845,7 +862,7 @@ 'doctype': 'DocField', 'fieldname': 'other_charges_total', 'fieldtype': 'Currency', - 'idx': 47, + 'idx': 48, 'label': 'Charges Total*', 'oldfieldname': 'other_charges_total', 'oldfieldtype': 'Currency', @@ -859,7 +876,7 @@ 'doctype': 'DocField', 'fieldname': 'grand_total', 'fieldtype': 'Currency', - 'idx': 48, + 'idx': 49, 'label': 'Grand Total*', 'oldfieldname': 'grand_total', 'oldfieldtype': 'Currency', @@ -873,7 +890,7 @@ { 'doctype': 'DocField', 'fieldtype': 'HTML', - 'idx': 49, + 'idx': 50, 'label': 'OT Notes', 'oldfieldtype': 'HTML', 'options': 'NOTE : * In Base Currency', @@ -885,7 +902,7 @@ { 'doctype': 'DocField', 'fieldtype': 'HTML', - 'idx': 50, + 'idx': 51, 'label': 'Other Charges Calculation', 'oldfieldtype': 'HTML', 'permlevel': 0, @@ -897,7 +914,7 @@ 'colour': 'White:FFF', 'doctype': 'DocField', 'fieldtype': 'Section Break', - 'idx': 51, + 'idx': 52, 'label': 'Totals', 'oldfieldtype': 'Section Break', 'permlevel': 0, @@ -909,7 +926,7 @@ 'doctype': 'DocField', 'fieldname': 'rounded_total', 'fieldtype': 'Currency', - 'idx': 52, + 'idx': 53, 'label': 'Rounded Total', 'oldfieldname': 'rounded_total', 'oldfieldtype': 'Currency', @@ -925,7 +942,7 @@ 'doctype': 'DocField', 'fieldname': 'in_words', 'fieldtype': 'Data', - 'idx': 53, + 'idx': 54, 'label': 'In Words', 'oldfieldname': 'in_words', 'oldfieldtype': 'Data', @@ -938,7 +955,7 @@ { 'doctype': 'DocField', 'fieldtype': 'Column Break', - 'idx': 54, + 'idx': 55, 'oldfieldtype': 'Column Break', 'permlevel': 0, 'print_hide': 1, @@ -950,7 +967,7 @@ 'doctype': 'DocField', 'fieldname': 'grand_total_export', 'fieldtype': 'Currency', - 'idx': 55, + 'idx': 56, 'label': 'Grand Total (Export)', 'oldfieldname': 'grand_total_export', 'oldfieldtype': 'Currency', @@ -965,7 +982,7 @@ 'doctype': 'DocField', 'fieldname': 'rounded_total_export', 'fieldtype': 'Currency', - 'idx': 56, + 'idx': 57, 'label': 'Rounded Total (Export)', 'oldfieldname': 'rounded_total_export', 'oldfieldtype': 'Currency', @@ -981,7 +998,7 @@ 'doctype': 'DocField', 'fieldname': 'in_words_export', 'fieldtype': 'Data', - 'idx': 57, + 'idx': 58, 'label': 'In Words (Export)', 'oldfieldname': 'in_words_export', 'oldfieldtype': 'Data', @@ -995,7 +1012,7 @@ 'colour': 'White:FFF', 'doctype': 'DocField', 'fieldtype': 'Section Break', - 'idx': 58, + 'idx': 59, 'label': 'Terms', 'oldfieldtype': 'Section Break', 'permlevel': 0, @@ -1007,7 +1024,7 @@ 'doctype': 'DocField', 'fieldname': 'tc_name', 'fieldtype': 'Link', - 'idx': 59, + 'idx': 60, 'label': 'Select Terms', 'oldfieldname': 'tc_name', 'oldfieldtype': 'Link', @@ -1021,7 +1038,7 @@ { 'doctype': 'DocField', 'fieldtype': 'Button', - 'idx': 60, + 'idx': 61, 'label': 'Get Terms', 'oldfieldtype': 'Button', 'options': 'get_tc_details', @@ -1033,7 +1050,7 @@ { 'doctype': 'DocField', 'fieldtype': 'HTML', - 'idx': 61, + 'idx': 62, 'label': 'Terms HTML', 'oldfieldtype': 'HTML', 'options': 'You can add Terms and Notes that will be printed in the Transaction', @@ -1046,7 +1063,7 @@ 'doctype': 'DocField', 'fieldname': 'terms', 'fieldtype': 'Text Editor', - 'idx': 62, + 'idx': 63, 'label': 'Term Details', 'oldfieldname': 'terms', 'oldfieldtype': 'Text Editor', @@ -1060,7 +1077,7 @@ 'description': 'Filling in additional information about the Sales Order will help you analyze your data better.', 'doctype': 'DocField', 'fieldtype': 'Section Break', - 'idx': 63, + 'idx': 64, 'label': 'More Info', 'oldfieldtype': 'Section Break', 'permlevel': 0, @@ -1071,7 +1088,7 @@ { 'doctype': 'DocField', 'fieldtype': 'Column Break', - 'idx': 64, + 'idx': 65, 'oldfieldtype': 'Column Break', 'permlevel': 0, 'print_hide': 1, @@ -1084,7 +1101,7 @@ 'doctype': 'DocField', 'fieldname': 'letter_head', 'fieldtype': 'Select', - 'idx': 65, + 'idx': 66, 'label': 'Letter Head', 'oldfieldname': 'letter_head', 'oldfieldtype': 'Select', @@ -1100,7 +1117,7 @@ 'doctype': 'DocField', 'fieldname': 'company', 'fieldtype': 'Link', - 'idx': 66, + 'idx': 67, 'in_filter': 1, 'label': 'Company', 'oldfieldname': 'company', @@ -1119,7 +1136,7 @@ 'doctype': 'DocField', 'fieldname': 'fiscal_year', 'fieldtype': 'Select', - 'idx': 67, + 'idx': 68, 'in_filter': 1, 'label': 'Fiscal Year', 'oldfieldname': 'fiscal_year', @@ -1139,7 +1156,7 @@ 'doctype': 'DocField', 'fieldname': 'select_print_heading', 'fieldtype': 'Link', - 'idx': 68, + 'idx': 69, 'label': 'Select Print Heading', 'no_copy': 1, 'oldfieldname': 'select_print_heading', @@ -1154,7 +1171,7 @@ { 'doctype': 'DocField', 'fieldtype': 'Column Break', - 'idx': 69, + 'idx': 70, 'oldfieldtype': 'Column Break', 'permlevel': 0, 'print_hide': 1, @@ -1167,7 +1184,7 @@ 'doctype': 'DocField', 'fieldname': 'source', 'fieldtype': 'Select', - 'idx': 70, + 'idx': 71, 'label': 'Source', 'oldfieldname': 'source', 'oldfieldtype': 'Select', @@ -1183,7 +1200,7 @@ 'doctype': 'DocField', 'fieldname': 'campaign', 'fieldtype': 'Link', - 'idx': 71, + 'idx': 72, 'label': 'Campaign', 'oldfieldname': 'campaign', 'oldfieldtype': 'Link', @@ -1198,7 +1215,7 @@ 'doctype': 'DocField', 'fieldname': 'note', 'fieldtype': 'Text', - 'idx': 72, + 'idx': 73, 'label': 'Note', 'oldfieldname': 'note', 'oldfieldtype': 'Text', @@ -1213,7 +1230,7 @@ 'doctype': 'DocField', 'fieldname': 'cancel_reason', 'fieldtype': 'Data', - 'idx': 73, + 'idx': 74, 'label': 'Cancel Reason', 'no_column': 0, 'no_copy': 1, @@ -1229,7 +1246,7 @@ 'fieldname': 'delivery_status', 'fieldtype': 'Select', 'hidden': 1, - 'idx': 74, + 'idx': 75, 'label': 'Delivery Status', 'no_column': 0, 'no_copy': 1, @@ -1244,7 +1261,7 @@ 'fieldname': 'billing_status', 'fieldtype': 'Select', 'hidden': 1, - 'idx': 75, + 'idx': 76, 'label': 'Billing Status', 'no_column': 0, 'no_copy': 1, @@ -1260,7 +1277,7 @@ 'doctype': 'DocField', 'fieldtype': 'Section Break', 'hidden': 0, - 'idx': 76, + 'idx': 77, 'label': 'Packing List', 'oldfieldtype': 'Section Break', 'permlevel': 0, @@ -1273,7 +1290,7 @@ 'doctype': 'DocField', 'fieldname': 'packing_details', 'fieldtype': 'Table', - 'idx': 77, + 'idx': 78, 'label': 'Packing Details', 'oldfieldname': 'packing_details', 'oldfieldtype': 'Table', @@ -1286,7 +1303,7 @@ { 'doctype': 'DocField', 'fieldtype': 'Section Break', - 'idx': 78, + 'idx': 79, 'label': 'Sales Team', 'oldfieldtype': 'Section Break', 'permlevel': 0, @@ -1300,7 +1317,7 @@ 'doctype': 'DocField', 'fieldname': 'sales_partner', 'fieldtype': 'Link', - 'idx': 79, + 'idx': 80, 'in_filter': 1, 'label': 'Sales Partner', 'oldfieldname': 'sales_partner', @@ -1318,7 +1335,7 @@ 'doctype': 'DocField', 'fieldname': 'commission_rate', 'fieldtype': 'Currency', - 'idx': 80, + 'idx': 81, 'label': 'Commission Rate', 'oldfieldname': 'commission_rate', 'oldfieldtype': 'Currency', @@ -1333,7 +1350,7 @@ 'doctype': 'DocField', 'fieldname': 'total_commission', 'fieldtype': 'Currency', - 'idx': 81, + 'idx': 82, 'label': 'Total Commission', 'oldfieldname': 'total_commission', 'oldfieldtype': 'Currency', @@ -1347,7 +1364,7 @@ 'doctype': 'DocField', 'fieldname': 'sales_team', 'fieldtype': 'Table', - 'idx': 82, + 'idx': 83, 'label': 'Sales Team1', 'oldfieldname': 'sales_team', 'oldfieldtype': 'Table', @@ -1361,7 +1378,7 @@ 'allow_on_submit': 1, 'doctype': 'DocField', 'fieldtype': 'Button', - 'idx': 83, + 'idx': 84, 'label': 'Repair Sales Order', 'oldfieldtype': 'Button', 'options': 'repair_sales_order', diff --git a/setup/doctype/email_settings/email_settings.py b/setup/doctype/email_settings/email_settings.py index 37de7bcb18d..ef0a7631d89 100644 --- a/setup/doctype/email_settings/email_settings.py +++ b/setup/doctype/email_settings/email_settings.py @@ -13,7 +13,7 @@ class DocType: for r in res: ret[cstr(r[0])]=r[1] and cstr(r[1]) or '' - return str(ret) + return ret def set_cp_value(self, key): """ diff --git a/setup/doctype/personalize/personalize.py b/setup/doctype/personalize/personalize.py index 6a15102f41a..3264546337d 100644 --- a/setup/doctype/personalize/personalize.py +++ b/setup/doctype/personalize/personalize.py @@ -28,4 +28,4 @@ class DocType: # def set_html_from_image(self): file_name = self.doc.file_list.split(',')[0] - self.doc.header_html = '
' + self.doc.header_html = '
' diff --git a/setup/doctype/workflow_rule/workflow_rule.py b/setup/doctype/workflow_rule/workflow_rule.py index 3a8cc821868..792cbf00903 100644 --- a/setup/doctype/workflow_rule/workflow_rule.py +++ b/setup/doctype/workflow_rule/workflow_rule.py @@ -281,4 +281,4 @@ class DocType: elif cond_hold =='Yes': all_cond_hold ='Yes' - return all_cond_hold \ No newline at end of file + return all_cond_hold diff --git a/setup/page/import_data/import_data.html b/setup/page/import_data/import_data.html index a4b30f425fd..5b30dd28cf5 100644 --- a/setup/page/import_data/import_data.html +++ b/setup/page/import_data/import_data.html @@ -32,7 +32,7 @@ -
+

Data Import Guide

  1. Get the template of the DocType for which you want to import in CSV (Comma seperated values) format.
  2. diff --git a/setup/page/import_data/import_data.js b/setup/page/import_data/import_data.js index aa0bdbd5322..f1601e79c71 100644 --- a/setup/page/import_data/import_data.js +++ b/setup/page/import_data/import_data.js @@ -1,45 +1,55 @@ pscript['onload_Import Data'] = function() { - - //alert(profile.can_get_report); + + //alert(profile.can_get_report); - callback = function(r,rt) { - var h = new PageHeader('di_header','Import Data','Tool to download template and upload data'); - var sel = $i('import_template'); - if(r.message){ - add_sel_options(sel, r.message); - sel.onchange=function(){ - $i('child_tab_lst').innerHTML =''; - if(sel.value != 'Select Master...'){ - $c_obj('Import Data Control','get_child_lst',sel.value, - function(r,rt){ - var me = this; - $y($i('child_tab_lst'),{backgroundColor:'#EEEEEE'}) - var desc = $a($i('child_tab_lst'), 'div', '', {padding:'8px'}); - - desc.innerHTML = "

    Please click on following link(s) to download template.

    "; + callback = function(r,rt) { + var h = new PageHeader('di_header','Import Data','Tool to download template and upload data'); + var sel = $i('import_template'); + if(r.message){ + add_sel_options(sel, r.message); + + // please collapse here when editing :) + sel.onchange=function(){ + $i('child_tab_lst').innerHTML =''; + if(sel.value != 'Select Master...'){ + $c_obj('Import Data Control','get_child_lst',sel.value, + function(r,rt){ + var me = this; + $y($i('child_tab_lst'),{backgroundColor:'#EEEEEE', margin: '17px 17px', padding: '13px'}) + var desc = $a($i('child_tab_lst'), 'div', '', {padding:'4px'}); + + desc.innerHTML = "Download template(s) for importing "+sel_val(sel)+""; - - var parent = $a($i('child_tab_lst'), 'div'); - var tab = make_table(parent,r.message.length,1,'100%',[],{padding:'8px',fontSize:'15px',borderCollapse: 'collapse'}); - - for(var i=0;i\n\n\n\n\n\n\n\n\n\n", + 'module': 'Stock', + 'name': '__common__', + 'standard': 'Yes' + }, + + # Print Format, Delivery Note Packing List Wise + { + 'doctype': 'Print Format', + 'name': 'Delivery Note Packing List Wise' + } +] \ No newline at end of file diff --git a/stock/doctype/bin/bin.py b/stock/doctype/bin/bin.py index 1a1eb701aba..fc51d768294 100644 --- a/stock/doctype/bin/bin.py +++ b/stock/doctype/bin/bin.py @@ -37,9 +37,13 @@ class DocType: self.doc.projected_qty = flt(self.doc.actual_qty) + flt(self.doc.ordered_qty) + flt(self.doc.indented_qty) + flt(self.doc.planned_qty) - flt(self.doc.reserved_qty) self.doc.save() - + + # update valuation for post dated entry if actual_qty: + # check actual qty with total number of serial no + self.check_qty_with_serial_no() + prev_sle = self.get_prev_sle(dt, posting_time, sle_id) cqty = flt(prev_sle.get('bin_aqat', 0)) # Block if actual qty becomes negative @@ -48,6 +52,18 @@ class DocType: self.update_item_valuation(sle_id, dt, posting_time, serial_no, prev_sle) + def check_qty_with_serial_no(self): + """ + check actual qty with total number of serial no in store + Temporary validation added on: 18-07-2011 + """ + if sql("select name from `tabItem` where ifnull(has_serial_no, 'No') = 'Yes' and name = '%s'" % self.doc.item_code): + sr_count = sql("select count(name) from `tabSerial No` where item_code = '%s' and warehouse = '%s' and status ='In Store' and docstatus != 2" % (self.doc.item_code, self.doc.warehouse))[0][0] + if sr_count != self.doc.actual_qty: + msg = "Actual Qty(%s) in Bin is mismatched with total number(%s) of serial no in store for item: '%s' and warehouse: '%s'" % (self.doc.actual_qty, sr_count, self.doc.item_code, self.doc.warehouse) + msgprint(msg, raise_exception=1) + sendmail(['developer@iwebnotes.com'], sender='automail@webnotestech.com', subject='Serial No Count vs Bin Actual Qty', parts=[['text/plain', msg]]) + # -------------------------------- # get first stock ledger entry # -------------------------------- diff --git a/stock/doctype/delivery_note/delivery_note.py b/stock/doctype/delivery_note/delivery_note.py index 74e6f8a97f2..e5acd163a75 100644 --- a/stock/doctype/delivery_note/delivery_note.py +++ b/stock/doctype/delivery_note/delivery_note.py @@ -13,7 +13,7 @@ sql = webnotes.conn.sql get_value = webnotes.conn.get_value in_transaction = webnotes.conn.in_transaction convert_to_lists = webnotes.conn.convert_to_lists - + # ----------------------------------------------------------------------------------------- from utilities.transaction_base import TransactionBase @@ -24,7 +24,7 @@ class DocType(TransactionBase): self.doclist = doclist self.tname = 'Delivery Note Detail' self.fname = 'delivery_note_details' - + # Notification objects self.notify_obj = get_obj('Notification Control') @@ -33,41 +33,36 @@ class DocType(TransactionBase): def autoname(self): self.doc.name = make_autoname(self.doc.naming_series+'.#####') - + # DOCTYPE TRIGGERS FUNCTIONS # ============================================================================== #************Fiscal Year Validation***************************** def validate_fiscal_year(self): get_obj('Sales Common').validate_fiscal_year(self.doc.fiscal_year,self.doc.posting_date,'Posting Date') - # ******************* Get Customer Details *********************** - #def get_customer_details(self): - # sales_com_obj = get_obj('Sales Common') - # sales_com_obj.get_customer_details(self) - # sales_com_obj.get_shipping_details(self) # ****** Get contact person details based on customer selected **** def get_contact_details(self): - return cstr(get_obj('Sales Common').get_contact_details(self,0)) + return get_obj('Sales Common').get_contact_details(self,0) # *********** Get Commission rate of Sales Partner **************** def get_comm_rate(self, sales_partner): return get_obj('Sales Common').get_comm_rate(sales_partner, self) - + # *************** Pull Sales Order Details ************************ def pull_sales_order_details(self): self.validate_prev_docname() self.doc.clear_table(self.doclist,'other_charges') - - if self.doc.sales_order_no: + + if self.doc.sales_order_no: get_obj('DocType Mapper', 'Sales Order-Delivery Note').dt_map('Sales Order', 'Delivery Note', self.doc.sales_order_no, self.doc, self.doclist, "[['Sales Order', 'Delivery Note'],['Sales Order Detail', 'Delivery Note Detail'],['RV Tax Detail','RV Tax Detail'],['Sales Team','Sales Team']]") else: - msgprint("Please select Sales Order No. whose details need to be pulled") + msgprint("Please select Sales Order No. whose details need to be pulled") return cstr(self.doc.sales_order_no) - - + + #-------------------set item details -uom and item group---------------- def set_item_details(self): for d in getlist(self.doclist,'delivery_note_details'): @@ -75,14 +70,14 @@ class DocType(TransactionBase): if not d.stock_uom: d.stock_uom = res and cstr(res[0][0]) or '' if not d.item_group: d.item_group = res and cstr(res[0][1]) or '' d.save() - + # ::::: Validates that Sales Order is not pulled twice ::::::: def validate_prev_docname(self): - for d in getlist(self.doclist, 'delivery_note_details'): + for d in getlist(self.doclist, 'delivery_note_details'): if self.doc.sales_order_no == d.prevdoc_docname: msgprint(cstr(self.doc.sales_order_no) + " sales order details have already been pulled. ") raise Exception, "Validation Error. " - + #Set Actual Qty based on item code and warehouse #------------------------------------------------------ def set_actual_qty(self): @@ -96,14 +91,14 @@ class DocType(TransactionBase): # ------------------------------------- def get_tc_details(self): return get_obj('Sales Common').get_tc_details(self) - + #pull project customer #------------------------- def pull_project_customer(self): res = sql("select customer from `tabProject` where name = '%s'"%self.doc.project_name) if res: get_obj('DocType Mapper', 'Project-Delivery Note').dt_map('Project', 'Delivery Note', self.doc.project_name, self.doc, self.doclist, "[['Project', 'Delivery Note']]") - + # DELIVERY NOTE DETAILS TRIGGER FUNCTIONS # ================================================================================ @@ -122,12 +117,12 @@ class DocType(TransactionBase): ret = { 'actual_qty' : actual_qty and flt(actual_qty[0]['actual_qty']) or 0 } - return cstr(ret) + return ret + - # OTHER CHARGES TRIGGER FUNCTIONS # ==================================================================================== - + # *********** Get Tax rate if account type is TAX ******************** def get_rate(self,arg): return get_obj('Sales Common').get_rate(arg) @@ -142,7 +137,7 @@ class DocType(TransactionBase): def get_other_charges(self): return get_obj('Sales Common').get_other_charges(self) - + #check in manage account if sales order required or not. # ==================================================================================== def so_required(self): @@ -152,9 +147,9 @@ class DocType(TransactionBase): if not d.prevdoc_docname: msgprint("Sales Order No. required against item %s"%d.item_code) raise Exception - - + + # VALIDATE # ==================================================================================== def validate(self): @@ -172,13 +167,16 @@ class DocType(TransactionBase): sales_com_obj.make_packing_list(self,'delivery_note_details') get_obj('Stock Ledger').validate_serial_no(self, 'packing_details') sales_com_obj.validate_max_discount(self, 'delivery_note_details') #verify whether rate is not greater than max discount - sales_com_obj.get_allocated_sum(self) # this is to verify that the allocated % of sales persons is 100% + sales_com_obj.get_allocated_sum(self) # this is to verify that the allocated % of sales persons is 100% sales_com_obj.check_conversion_rate(self) # ::::::: Get total in Words :::::::: dcc = TransactionBase().get_company_currency(self.doc.company) self.doc.in_words = sales_com_obj.get_total_in_words(dcc, self.doc.rounded_total) self.doc.in_words_export = sales_com_obj.get_total_in_words(self.doc.currency, self.doc.rounded_total_export) - + + # ::::::: Set Net Weight of each Packing + self.update_pack_nett_weight() + self.print_packing_slip() # ::::::: Set actual qty for each item in selected warehouse ::::::: self.update_current_stock() # :::::: set DN status ::::::: @@ -186,8 +184,7 @@ class DocType(TransactionBase): self.doc.status = 'Draft' if not self.doc.billing_status: self.doc.billing_status = 'Not Billed' if not self.doc.installation_status: self.doc.installation_status = 'Not Installed' - - + # ************** Validate Mandatory ************************* def validate_mandatory(self): # :::::::::: Amendment Date :::::::::::::: @@ -203,20 +200,20 @@ class DocType(TransactionBase): if not res: msgprint("Customer - %s does not belong to project - %s. \n\nIf you want to use project for multiple customers then please make customer details blank in project - %s."%(self.doc.customer,self.doc.project_name,self.doc.project_name)) raise Exception - + # Validate values with reference document #---------------------------------------- def validate_reference_value(self): get_obj('DocType Mapper', 'Sales Order-Delivery Note', with_children = 1).validate_reference_value(self, self.doc.name) - - + + # ******* Validate Previous Document Details ************ def validate_prevdoc_details(self): for d in getlist(self.doclist,'delivery_note_details'): - + prevdoc = d.prevdoc_doctype prevdoc_docname = d.prevdoc_docname - + if prevdoc_docname and prevdoc: # ::::::::::: Validates Transaction Date of DN and previous doc (i.e. SO , PO, PR) ********* trans_date = sql("select transaction_date from `tab%s` where name = '%s'" %(prevdoc,prevdoc_docname))[0][0] @@ -264,7 +261,7 @@ class DocType(TransactionBase): ch = sql("select is_stock_item from `tabItem` where name = '%s'"%d.item_code) if d.prevdoc_doctype and d.prevdoc_detail_docname and ch and ch[0][0]=='Yes': self.validate_items_with_prevdoc(d) - + # validates whether item is not entered twice e = [d.item_code, d.description, d.warehouse, d.prevdoc_docname or '', d.batch_no or ''] f = [d.item_code, d.description, d.prevdoc_docname or ''] @@ -302,8 +299,8 @@ class DocType(TransactionBase): for d in getlist(self.doclist, 'packing_details'): bin = sql("select actual_qty, projected_qty from `tabBin` where item_code = %s and warehouse = %s", (d.item_code, d.warehouse), as_dict = 1) d.actual_qty = bin and flt(bin[0]['actual_qty']) or 0 - d.projected_qty = bin and flt(bin[0]['projected_qty']) or 0 - + d.projected_qty = bin and flt(bin[0]['projected_qty']) or 0 + # ON SUBMIT # ================================================================================================= @@ -327,7 +324,7 @@ class DocType(TransactionBase): # on submit notification self.notify_obj.notify_contact('Delivery Note',self.doc.doctype,self.doc.name, self.doc.email_id, self.doc.contact_person) - + # *********** Checks whether actual quantity is present in warehouse ************* def check_qty_in_stock(self): for d in getlist(self.doclist, 'packing_details'): @@ -339,7 +336,7 @@ class DocType(TransactionBase): # ON CANCEL -# ================================================================================================= +# ================================================================================================= def on_cancel(self): sales_com_obj = get_obj(dt = 'Sales Common') sales_com_obj.check_stop_sales_order(self) @@ -350,14 +347,14 @@ class DocType(TransactionBase): # :::::: set DN status ::::::: set(self.doc, 'status', 'Cancelled') - + # ******************** Check Next DocStatus ************************** def check_next_docstatus(self): submit_rv = sql("select t1.name from `tabReceivable Voucher` t1,`tabRV Detail` t2 where t1.name = t2.parent and t2.delivery_note = '%s' and t1.docstatus = 1" % (self.doc.name)) if submit_rv: msgprint("Sales Invoice : " + cstr(submit_rv[0][0]) + " has already been submitted !") raise Exception , "Validation Error." - + submit_in = sql("select t1.name from `tabInstallation Note` t1, `tabInstalled Item Details` t2 where t1.name = t2.parent and t2.prevdoc_docname = '%s' and t1.docstatus = 1" % (self.doc.name)) if submit_in: msgprint("Installation Note : "+cstr(submit_in[0][0]) +" has already been submitted !") @@ -374,11 +371,11 @@ class DocType(TransactionBase): if not d[0]: msgprint("Message: Please enter Warehouse for item %s as it is stock item."% d[1]) raise Exception - # if prevdoc_doctype = "Sales Order" + # if prevdoc_doctype = "Sales Order" if d[3] < 0 : # Reduce Reserved Qty from warehouse bin = get_obj('Warehouse', d[0]).update_bin(0, flt(update_stock) * flt(d[3]), 0, 0, 0, d[1], self.doc.transaction_date) - + # Reduce actual qty from warehouse self.make_sl_entry(d, d[0], - flt(d[2]) , 0, update_stock) get_obj('Stock Ledger', 'Stock Ledger').update_stock(self.values) @@ -388,7 +385,7 @@ class DocType(TransactionBase): def get_item_list(self, is_stopped): return get_obj('Sales Common').get_item_list(self, is_stopped) - + # ********************** Make Stock Entry ************************************ def make_sl_entry(self, d, wh, qty, in_value, update_stock): self.values.append({ @@ -399,8 +396,8 @@ class DocType(TransactionBase): 'posting_time' : self.doc.posting_time, 'voucher_type' : 'Delivery Note', 'voucher_no' : self.doc.name, - 'voucher_detail_no' : '', - 'actual_qty' : qty, + 'voucher_detail_no' : '', + 'actual_qty' : qty, 'stock_uom' : d[4], 'incoming_rate' : in_value, 'company' : self.doc.company, @@ -408,9 +405,9 @@ class DocType(TransactionBase): 'is_cancelled' : (update_stock==1) and 'No' or 'Yes', 'batch_no' : d[5], 'serial_no' : d[6] - }) + }) + - # SEND SMS # ============================================================================================ def send_sms(self): @@ -441,3 +438,44 @@ class DocType(TransactionBase): # =========================================== def repair_delivery_note(self): get_obj('Sales Common', 'Sales Common').repair_curr_doctype_details(self) + + # Packing Slip Related + # ========================================== + def update_pack_nett_weight(self): + for d in getlist(self.doclist, 'delivery_note_details'): + if d.item_name: + item_wt = sql("select nett_weight from `tabItem` where item_name = '%s'" % (d.item_name)) + d.pack_nett_wt = item_wt and flt(item_wt[0][0])*flt(d.qty) or 0 + + # ========================================== + def print_packing_slip(self): + prev_pack='0' + sno=0 + html='' + tot_nett_wt,tot_gross_wt=0,0 + for d in getlist(self.doclist, 'delivery_note_details'): + sno=sno+1 + if sno!=1:#Footer goes here + html+='
    CASE NO'+cstr(d.pack_no)+'NETT WT'+cstr(tot_nett_wt)+'CHECKED BY
    SIZEGROSS WT'+cstr(tot_gross_wt)+'PACKED BY
    ' + if prev_pack!=d.pack_no: #Prepare Header Here + #Header code goes here + html+='
    [HEADER GOES HERE]

    Packing Slip

    Order No.'+cstr(self.doc.sales_order_no)+'Shipping Marks'+cstr(d.pack_no)+'
    ' + html+='' + sno=0 + tot_nett_wt,to_gross_wt=flt(d.pack_nett_wt),flt(d.pack_gross_wt) + #Body code goes here + html+='' + prev_pack=d.pack_no + tot_nett_wt+=flt(d.pack_nett_wt) + tot_gross_wt+=flt(d.pack_gross_wt) + html+='' + self.doc.print_packing_slip=html + + + + + + + + + diff --git a/stock/doctype/delivery_note/delivery_note.txt b/stock/doctype/delivery_note/delivery_note.txt index 97280e99831..1ab19e070c9 100644 --- a/stock/doctype/delivery_note/delivery_note.txt +++ b/stock/doctype/delivery_note/delivery_note.txt @@ -3,16 +3,25 @@ # These values are common in all dictionaries { - 'creation': '2010-08-08 17:08:57', + 'creation': '2011-04-18 15:58:20', 'docstatus': 0, - 'modified': '2011-06-27 16:42:01', + 'modified': '2011-08-23 15:26:57', 'modified_by': 'Administrator', 'owner': 'Administrator' }, + # These values are common for all DocField + { + 'doctype': 'DocField', + 'name': '__common__', + 'parent': 'Delivery Note', + 'parentfield': 'fields', + 'parenttype': 'DocType' + }, + # These values are common for all DocType { - '_last_update': '1309173122', + '_last_update': '1313665263', 'colour': 'White:FFF', 'doctype': 'DocType', 'document_type': 'Transaction', @@ -27,15 +36,16 @@ 'show_in_menu': 0, 'subject': 'To %(customer_name)s on %(transaction_date)s | %(per_billed)s% billed', 'tag_fields': 'billing_status', - 'version': 444 + 'version': 449 }, - # These values are common for all DocField + # These values are common for all DocFormat { - 'doctype': 'DocField', + 'doctype': 'DocFormat', + 'format': 'Delivery Note Packing List Wise', 'name': '__common__', 'parent': 'Delivery Note', - 'parentfield': 'fields', + 'parentfield': 'formats', 'parenttype': 'DocType' }, @@ -70,15 +80,15 @@ # DocPerm { - 'amend': 0, - 'cancel': 0, - 'create': 0, + 'amend': 1, + 'cancel': 1, + 'create': 1, 'doctype': 'DocPerm', 'idx': 2, - 'permlevel': 1, - 'role': 'Material User', - 'submit': 0, - 'write': 0 + 'permlevel': 0, + 'role': 'Sales User', + 'submit': 1, + 'write': 1 }, # DocPerm @@ -89,86 +99,50 @@ 'doctype': 'DocPerm', 'idx': 3, 'permlevel': 0, - 'role': 'Material Manager', + 'role': 'Material Master Manager', 'submit': 1, 'write': 1 }, - # DocPerm - { - 'amend': 0, - 'cancel': 0, - 'create': 0, - 'doctype': 'DocPerm', - 'idx': 4, - 'permlevel': 1, - 'role': 'Material Manager', - 'submit': 0, - 'write': 0 - }, - # DocPerm { 'amend': 1, 'cancel': 1, 'create': 1, 'doctype': 'DocPerm', - 'idx': 5, + 'idx': 4, 'permlevel': 0, - 'role': 'Sales User', + 'role': 'Material Manager', 'submit': 1, 'write': 1 }, # DocPerm { - 'amend': 0, - 'cancel': 0, - 'create': 0, + 'doctype': 'DocPerm', + 'idx': 5, + 'permlevel': 1, + 'role': 'All' + }, + + # DocPerm + { 'doctype': 'DocPerm', 'idx': 6, - 'permlevel': 1, - 'role': 'Sales User', - 'submit': 0, - 'write': 0 - }, - - # DocPerm - { - 'cancel': 0, - 'create': 0, - 'doctype': 'DocPerm', - 'idx': 7, - 'permlevel': 0, - 'role': 'Accounts User', - 'submit': 0, - 'write': 0 - }, - - # DocPerm - { - 'doctype': 'DocPerm', - 'idx': 8, - 'permlevel': 1, - 'role': 'Accounts User' - }, - - # DocPerm - { - 'doctype': 'DocPerm', - 'idx': 9, - 'match': 'customer_name', - 'permlevel': 0, - 'role': 'Customer' - }, - - # DocPerm - { - 'doctype': 'DocPerm', - 'idx': 10, 'permlevel': 2, - 'role': 'All', - 'write': 1 + 'role': 'All' + }, + + # DocFormat + { + 'doctype': 'DocFormat', + 'idx': 1 + }, + + # DocFormat + { + 'doctype': 'DocFormat', + 'idx': 2 }, # DocField @@ -332,7 +306,7 @@ 'permlevel': 0, 'print_hide': 0, 'reqd': 1, - 'search_index': 0, + 'search_index': 1, 'width': '100px' }, @@ -352,7 +326,7 @@ 'permlevel': 1, 'print_hide': 1, 'reqd': 1, - 'search_index': 0, + 'search_index': 1, 'width': '150px' }, @@ -366,13 +340,13 @@ 'fieldtype': 'Currency', 'idx': 15, 'in_filter': 1, - 'label': '% Qty Billed', + 'label': '% Amount Billed', 'no_copy': 1, 'oldfieldname': 'per_billed', 'oldfieldtype': 'Currency', 'permlevel': 1, 'print_hide': 1, - 'search_index': 0 + 'search_index': 1 }, # DocField @@ -391,7 +365,7 @@ 'oldfieldtype': 'Currency', 'permlevel': 1, 'print_hide': 1, - 'search_index': 0 + 'search_index': 1 }, # DocField @@ -439,7 +413,7 @@ 'permlevel': 0, 'print_hide': 1, 'reqd': 1, - 'search_index': 0 + 'search_index': 1 }, # DocField @@ -453,7 +427,7 @@ 'options': 'Customer Group', 'permlevel': 0, 'print_hide': 1, - 'search_index': 0 + 'search_index': 1 }, # DocField @@ -1014,7 +988,7 @@ 'permlevel': 0, 'print_hide': 1, 'reqd': 1, - 'search_index': 0, + 'search_index': 1, 'width': '150px' }, @@ -1032,7 +1006,7 @@ 'permlevel': 0, 'print_hide': 1, 'reqd': 1, - 'search_index': 0, + 'search_index': 1, 'width': '150px' }, @@ -1506,5 +1480,18 @@ 'options': 'repair_delivery_note', 'permlevel': 0, 'print_hide': 1 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'print_packing_slip', + 'fieldtype': 'Text', + 'hidden': 1, + 'idx': 95, + 'in_filter': 0, + 'label': 'Print Packing Slip', + 'permlevel': 0, + 'print_hide': 0 } ] \ No newline at end of file diff --git a/stock/doctype/delivery_note/tests.py b/stock/doctype/delivery_note/tests.py deleted file mode 100644 index df04c417fae..00000000000 --- a/stock/doctype/delivery_note/tests.py +++ /dev/null @@ -1,25 +0,0 @@ -import unittest -import webnotes - -from webnotes.model.code import get_obj - -class SubmissionTest(unittest.TestCase): - def setUp(self): - self.dn = webnotes.testing.create('Delivery Note') - self.dn_items = [] - - # get a line item for testing - for d in self.dn.doclist: - if d.doctype=='Delivery Note Detail': - self.dn_items.append(d) - - self.old_bin = get_obj('Warehouse', self.line_item[0].warehouse).get_bin(self.line_item[0].item_code) - self.dn.on_submit() - - def test_bin_is_updated(self): - "tests if bin quantity is affected when on submission" - bin = get_obj('Warehouse', self.line_item.warehouse).get_bin(self.line_item[0].item_code) - self.assertTrue(bin.actual_qty == self.old_bin.actual_qty - self.line_item[0].qty) - - def test_sales_order_is_updated(self): - "tests if" \ No newline at end of file diff --git a/stock/doctype/delivery_note_detail/delivery_note_detail.txt b/stock/doctype/delivery_note_detail/delivery_note_detail.txt index 78aea3267f0..a8fea209c46 100644 --- a/stock/doctype/delivery_note_detail/delivery_note_detail.txt +++ b/stock/doctype/delivery_note_detail/delivery_note_detail.txt @@ -5,7 +5,7 @@ { 'creation': '2010-08-08 17:08:58', 'docstatus': 0, - 'modified': '2011-03-01 10:35:06', + 'modified': '2011-08-22 12:11:51', 'modified_by': 'Administrator', 'owner': 'Administrator' }, @@ -21,7 +21,7 @@ 'section_style': 'Tray', 'server_code_error': ' ', 'show_in_menu': 0, - 'version': 35 + 'version': 38 }, # These values are common for all DocField @@ -102,27 +102,13 @@ 'width': '50px' }, - # DocField - { - 'doctype': 'DocField', - 'fieldname': 'no_of_packs', - 'fieldtype': 'Int', - 'idx': 5, - 'label': 'No of Packs', - 'oldfieldname': 'no_of_packs', - 'oldfieldtype': 'Int', - 'permlevel': 0, - 'print_hide': 1, - 'width': '100px' - }, - # DocField { 'default': '0.00', 'doctype': 'DocField', 'fieldname': 'qty', 'fieldtype': 'Currency', - 'idx': 6, + 'idx': 5, 'label': 'Quantity', 'oldfieldname': 'qty', 'oldfieldtype': 'Currency', @@ -138,7 +124,7 @@ 'doctype': 'DocField', 'fieldname': 'ref_rate', 'fieldtype': 'Currency', - 'idx': 7, + 'idx': 6, 'label': 'Ref Rate', 'no_copy': 0, 'oldfieldname': 'ref_rate', @@ -156,7 +142,7 @@ 'doctype': 'DocField', 'fieldname': 'adj_rate', 'fieldtype': 'Float', - 'idx': 8, + 'idx': 7, 'label': 'Discount (%)', 'oldfieldname': 'adj_rate', 'oldfieldtype': 'Float', @@ -171,7 +157,7 @@ 'doctype': 'DocField', 'fieldname': 'export_rate', 'fieldtype': 'Currency', - 'idx': 9, + 'idx': 8, 'label': 'Rate', 'oldfieldname': 'export_rate', 'oldfieldtype': 'Currency', @@ -187,7 +173,7 @@ 'doctype': 'DocField', 'fieldname': 'export_amount', 'fieldtype': 'Currency', - 'idx': 10, + 'idx': 9, 'label': 'Amount', 'oldfieldname': 'export_amount', 'oldfieldtype': 'Currency', @@ -202,7 +188,7 @@ 'doctype': 'DocField', 'fieldname': 'base_ref_rate', 'fieldtype': 'Currency', - 'idx': 11, + 'idx': 10, 'label': 'Ref Rate*', 'oldfieldname': 'base_ref_rate', 'oldfieldtype': 'Currency', @@ -217,7 +203,7 @@ 'doctype': 'DocField', 'fieldname': 'basic_rate', 'fieldtype': 'Currency', - 'idx': 12, + 'idx': 11, 'label': 'Rate*', 'oldfieldname': 'basic_rate', 'oldfieldtype': 'Currency', @@ -233,7 +219,7 @@ 'doctype': 'DocField', 'fieldname': 'amount', 'fieldtype': 'Currency', - 'idx': 13, + 'idx': 12, 'label': 'Amount*', 'oldfieldname': 'amount', 'oldfieldtype': 'Currency', @@ -248,7 +234,7 @@ 'doctype': 'DocField', 'fieldname': 'warehouse', 'fieldtype': 'Link', - 'idx': 14, + 'idx': 13, 'label': 'Warehouse', 'oldfieldname': 'warehouse', 'oldfieldtype': 'Link', @@ -264,7 +250,8 @@ 'doctype': 'DocField', 'fieldname': 'serial_no', 'fieldtype': 'Text', - 'idx': 15, + 'idx': 14, + 'in_filter': 1, 'label': 'Serial No', 'no_copy': 1, 'oldfieldname': 'serial_no', @@ -279,14 +266,13 @@ 'doctype': 'DocField', 'fieldname': 'batch_no', 'fieldtype': 'Link', - 'idx': 16, + 'idx': 15, 'label': 'Batch No', 'oldfieldname': 'batch_no', 'oldfieldtype': 'Link', 'options': 'Batch', 'permlevel': 0, - 'print_hide': 1, - 'search_index': 0 + 'print_hide': 1 }, # DocField @@ -294,14 +280,13 @@ 'doctype': 'DocField', 'fieldname': 'item_group', 'fieldtype': 'Link', - 'idx': 17, + 'idx': 16, 'label': 'Item Group', 'oldfieldname': 'item_group', 'oldfieldtype': 'Link', 'options': 'Item Group', 'permlevel': 1, - 'print_hide': 1, - 'search_index': 0 + 'print_hide': 1 }, # DocField @@ -309,23 +294,77 @@ 'doctype': 'DocField', 'fieldname': 'brand', 'fieldtype': 'Link', - 'idx': 18, + 'idx': 17, 'label': 'Brand Name', 'oldfieldname': 'brand', 'oldfieldtype': 'Link', 'options': 'Brand', 'permlevel': 1, 'print_hide': 1, - 'search_index': 0, 'width': '150px' }, + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'pack_no', + 'fieldtype': 'Data', + 'idx': 18, + 'label': 'Pack No', + 'permlevel': 0 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'pack_gross_wt', + 'fieldtype': 'Float', + 'idx': 19, + 'label': 'Pack Gross Wt', + 'permlevel': 0 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'weight_uom', + 'fieldtype': 'Link', + 'idx': 20, + 'label': 'Weight UOM', + 'options': 'UOM', + 'permlevel': 0 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'pack_nett_wt', + 'fieldtype': 'Float', + 'idx': 21, + 'label': 'Pack Nett Wt', + 'permlevel': 0 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'no_of_packs', + 'fieldtype': 'Int', + 'idx': 22, + 'label': 'No of Packs', + 'oldfieldname': 'no_of_packs', + 'oldfieldtype': 'Int', + 'permlevel': 0, + 'print_hide': 1, + 'width': '100px' + }, + # DocField { 'doctype': 'DocField', 'fieldname': 'pack_unit', 'fieldtype': 'Data', - 'idx': 19, + 'idx': 23, 'label': 'Pack Unit', 'oldfieldname': 'pack_unit', 'oldfieldtype': 'Data', @@ -339,7 +378,7 @@ 'doctype': 'DocField', 'fieldname': 'installed_qty', 'fieldtype': 'Currency', - 'idx': 20, + 'idx': 24, 'label': 'Installed Qty', 'no_copy': 1, 'oldfieldname': 'installed_qty', @@ -354,7 +393,7 @@ 'doctype': 'DocField', 'fieldname': 'actual_qty', 'fieldtype': 'Currency', - 'idx': 21, + 'idx': 25, 'label': 'Available Qty at Warehouse', 'no_copy': 1, 'oldfieldname': 'actual_qty', @@ -364,29 +403,12 @@ 'width': '150px' }, - # DocField - { - 'colour': 'White:FFF', - 'default': '0.00', - 'doctype': 'DocField', - 'fieldname': 'billed_qty', - 'fieldtype': 'Currency', - 'idx': 22, - 'label': 'Billed Qty', - 'no_copy': 1, - 'oldfieldname': 'billed_qty', - 'oldfieldtype': 'Currency', - 'permlevel': 1, - 'print_hide': 1, - 'width': '100px' - }, - # DocField { 'doctype': 'DocField', 'fieldname': 'billed_amt', 'fieldtype': 'Currency', - 'idx': 23, + 'idx': 26, 'label': 'Billed Amt', 'no_copy': 1, 'permlevel': 1, @@ -401,7 +423,7 @@ 'fieldname': 'prevdoc_docname', 'fieldtype': 'Data', 'hidden': 0, - 'idx': 24, + 'idx': 27, 'in_filter': 1, 'label': 'Against Document No', 'no_copy': 1, @@ -419,14 +441,14 @@ 'fieldname': 'prevdoc_doctype', 'fieldtype': 'Data', 'hidden': 1, - 'idx': 25, + 'idx': 28, 'in_filter': 1, 'label': 'Document Type', 'oldfieldname': 'prevdoc_doctype', 'oldfieldtype': 'Data', 'permlevel': 1, 'print_hide': 1, - 'search_index': 0, + 'search_index': 1, 'width': '150px' }, @@ -436,7 +458,7 @@ 'fieldname': 'prevdoc_date', 'fieldtype': 'Date', 'hidden': 1, - 'idx': 26, + 'idx': 29, 'in_filter': 1, 'label': 'Against Document Date', 'oldfieldname': 'prevdoc_date', @@ -451,14 +473,14 @@ 'fieldname': 'prevdoc_detail_docname', 'fieldtype': 'Data', 'hidden': 1, - 'idx': 27, + 'idx': 30, 'in_filter': 1, 'label': 'Against Document Detail No', 'oldfieldname': 'prevdoc_detail_docname', 'oldfieldtype': 'Data', 'permlevel': 1, 'print_hide': 1, - 'search_index': 1, + 'search_index': 0, 'width': '150px' }, @@ -468,7 +490,7 @@ 'fieldname': 'item_tax_rate', 'fieldtype': 'Small Text', 'hidden': 1, - 'idx': 28, + 'idx': 31, 'label': 'Item Tax Rate', 'oldfieldname': 'item_tax_rate', 'oldfieldtype': 'Small Text', @@ -482,7 +504,7 @@ 'doctype': 'DocField', 'fieldname': 'page_break', 'fieldtype': 'Check', - 'idx': 29, + 'idx': 32, 'label': 'Page Break', 'oldfieldname': 'page_break', 'oldfieldtype': 'Check', diff --git a/stock/doctype/item/item.js b/stock/doctype/item/item.js index 3c0262979e3..6dd7377ed7e 100644 --- a/stock/doctype/item/item.js +++ b/stock/doctype/item/item.js @@ -1,17 +1,17 @@ cur_frm.cscript.refresh = function(doc) { // make sensitive fields(has_serial_no, is_stock_item, valuation_method) // read only if any stock ledger entry exists - + if ((!doc.__islocal) && (doc.is_stock_item == 'Yes')) { var callback = function(r, rt) { if (r.message == 'exists') permlevel = 1; else permlevel = 0; - + set_field_permlevel('has_serial_no', permlevel); set_field_permlevel('is_stock_item', permlevel); set_field_permlevel('valuation_method', permlevel); } - $c_obj(make_doclist(doc.doctype, doc.name),'check_if_sle_exists','',callback); + $c_obj(make_doclist(doc.doctype, doc.name),'check_if_sle_exists','',callback); } } @@ -24,25 +24,25 @@ cur_frm.fields_dict['default_bom'].get_query = function(doc) { // Expense Account // --------------------------------- -cur_frm.fields_dict['purchase_account'].get_query = function(doc){ +cur_frm.fields_dict['purchase_account'].get_query = function(doc){ return 'SELECT DISTINCT `tabAccount`.`name` FROM `tabAccount` WHERE `tabAccount`.`debit_or_credit`="Debit" AND `tabAccount`.`group_or_ledger`="Ledger" AND `tabAccount`.`docstatus`!=2 AND `tabAccount`.`is_pl_account` = "Yes" AND `tabAccount`.%(key)s LIKE "%s" ORDER BY `tabAccount`.`name` LIMIT 50' } -// Income Account +// Income Account // -------------------------------- cur_frm.fields_dict['default_income_account'].get_query = function(doc) { return 'SELECT DISTINCT `tabAccount`.`name` FROM `tabAccount` WHERE `tabAccount`.`debit_or_credit`="Credit" AND `tabAccount`.`group_or_ledger`="Ledger" AND `tabAccount`.`is_pl_account` = "Yes" AND `tabAccount`.`docstatus`!=2 AND `tabAccount`.`account_type` ="Income Account" AND `tabAccount`.%(key)s LIKE "%s" ORDER BY `tabAccount`.`name` LIMIT 50' } -// Purchase Cost Center +// Purchase Cost Center // ----------------------------- cur_frm.fields_dict['cost_center'].get_query = function(doc) { return 'SELECT `tabCost Center`.`name` FROM `tabCost Center` WHERE `tabCost Center`.%(key)s LIKE "%s" AND `tabCost Center`.`group_or_ledger` = "Ledger" AND `tabCost Center`.`docstatus`!= 2 ORDER BY `tabCost Center`.`name` ASC LIMIT 50' } -// Sales Cost Center +// Sales Cost Center // ----------------------------- cur_frm.fields_dict['default_sales_cost_center'].get_query = function(doc) { return 'SELECT `tabCost Center`.`name` FROM `tabCost Center` WHERE `tabCost Center`.%(key)s LIKE "%s" AND `tabCost Center`.`group_or_ledger` = "Ledger" AND `tabCost Center`.`docstatus`!= 2 ORDER BY `tabCost Center`.`name` ASC LIMIT 50' @@ -66,7 +66,7 @@ cur_frm.fields_dict['item_group'].get_query = function(doc,cdt,cdn) { cur_frm.cscript.IGHelp = function(doc,dt,dn){ var call_back = function(){ - var sb_obj = new SalesBrowser(); + var sb_obj = new SalesBrowser(); sb_obj.set_val('Item Group'); } @@ -79,21 +79,34 @@ cur_frm.cscript.IGHelp = function(doc,dt,dn){ // in the "alternate_description" field cur_frm.cscript['Add Image'] = function(doc, dt, dn) { if(!doc.file_list) { - msgprint('Please attach a file first!'); + msgprint('Please attach a file first!'); } - + var f = doc.file_list.split('\n')[0]; var fname = f.split(',')[0]; var fid = f.split(',')[1]; if(!in_list(['jpg','jpeg','gif','png'], fname.split('.')[1].toLowerCase())) { msgprint('File must be of extension jpg, jpeg, gif or png'); return; } - + doc.description_html = repl('
    S.NO.QUANTITYCS.NO.DESCRIPTIONWEIGHT
    '+cstr(sno+1)+''+cstr(d.qty)+''+d.item_code+''+cstr(d.pack_nett_wt)+'
    '+ ''+ ''+ '
    %(desc)s
    ', {imgurl: wn.urllib.get_file_url(fid), desc:doc.description}); - + refresh_field('description_html'); } +//===================== Quotation to validation - either customer or lead mandatory ==================== +cur_frm.cscript.weight_to_validate = function(doc,cdt,cdn){ + if((doc.nett_weight || doc.gross_weight) && !doc.weight_uom) + { + alert('Weight is mentioned,\nPlease mention "Weight UOM" too'); + validated=0; + } +} +//===================validation function ================================= + +cur_frm.cscript.validate = function(doc,cdt,cdn){ + cur_frm.cscript.weight_to_validate(doc,cdt,cdn); +} diff --git a/stock/doctype/item/item.py b/stock/doctype/item/item.py index ae677493b5f..28f1d12e855 100644 --- a/stock/doctype/item/item.py +++ b/stock/doctype/item/item.py @@ -13,7 +13,7 @@ sql = webnotes.conn.sql get_value = webnotes.conn.get_value in_transaction = webnotes.conn.in_transaction convert_to_lists = webnotes.conn.convert_to_lists - + # ----------------------------------------------------------------------------------------- @@ -21,13 +21,13 @@ class DocType: def __init__(self, doc, doclist=[]): self.doc = doc self.doclist = doclist - + def get_tax_rate(self, tax_type): rate = sql("select tax_rate from tabAccount where name = %s", tax_type) ret = { 'tax_rate' : rate and flt(rate[0][0]) or 0 } - return str(ret) + return ret def on_update(self): bin = sql("select stock_uom from `tabBin` where item_code = '%s' " % self.doc.item_code) @@ -39,14 +39,14 @@ class DocType: if not self.doc.stock_uom: msgprint("Please enter Stock UOM first.") raise Exception - + if cstr(d.uom) in check_list: msgprint("UOM %s has been entered more than once in Conversion Factor Details." % cstr(d.uom)) raise Exception - + if not cstr(d.uom) in check_list: check_list.append(cstr(d.uom)) - + if cstr(d.uom) == cstr(self.doc.stock_uom): if flt(d.conversion_factor) != 1: msgprint("Conversion Fator of UOM : %s should be equal to 1. As UOM : %s is Stock UOM of Item: %s." % ( cstr(d.uom), cstr(d.uom), cstr(self.doc.name))) @@ -56,14 +56,14 @@ class DocType: elif cstr(d.uom) != cstr(self.doc.stock_uom) and flt(d.conversion_factor) == 1: msgprint("Conversion Factor of UOM : %s should not be equal to 1. As UOM : %s is not Stock UOM of Item: %s." % ( cstr(d.uom), cstr(d.uom), cstr(self.doc.name))) raise Exception - + if not cstr(self.doc.stock_uom) in check_list : child = addchild( self.doc, 'uom_conversion_details', 'UOM Conversion Detail', 1, self.doclist) child.uom = self.doc.stock_uom child.conversion_factor = 1 child.save() - + # Check whether Ref Rate is not entered twice for same Price List and Currency def check_ref_rate_detail(self): check_list=[] @@ -73,7 +73,13 @@ class DocType: raise Exception else: check_list.append([cstr(d.price_list_name),cstr(d.ref_currency)]) - + + # Append all the customer codes and insert into "customer_code" field of item table + def fill_customer_code(self): + cust_code=[] + for d in getlist(self.doclist,'item_customer_details'): + cust_code.append(d.ref_code) + self.doc.customer_code=','.join(cust_code) # Check whether Tax Rate is not entered twice for same Tax Type def check_item_tax(self): @@ -89,7 +95,7 @@ class DocType: msgprint("Rate is entered twice for Tax : '%s'." % (d.tax_type)) raise Exception else: - check_list.append(d.tax_type) + check_list.append(d.tax_type) def check_for_active_boms(self, check): if check in ['Is Active', 'Is Purchase Item']: @@ -102,7 +108,7 @@ class DocType: if bom and bom[0][0]: msgprint("%s should be 'Yes'. As Item %s is present in one or many Active BOMs." % (cstr(check), cstr(self.doc.name))) raise Exception - + def validate(self): fl = {'is_manufactured_item' :'Is Manufactured Item', 'is_sub_contracted_item':'Is Sub Contracted Item', @@ -112,18 +118,19 @@ class DocType: if cstr(self.doc.fields[d]) != 'Yes': self.check_for_active_boms(check = fl[d]) self.check_ref_rate_detail() + self.fill_customer_code() self.check_item_tax() if not self.doc.min_order_qty: self.doc.min_order_qty = 0 self.check_non_asset_warehouse() - + if self.doc.is_pro_applicable == 'Yes' and self.doc.is_manufactured_item != 'Yes': msgprint("If making Production Order is allowed then, it should also allow to make Bill of Materials. Refer Manufacturing section.") raise Exception - + if self.doc.is_pro_applicable == 'Yes' and self.doc.is_stock_item == 'No': msgprint("As Production Order can be made for this Item, then Is Stock Item Should be 'Yes' as we maintain it's stock. Refer Manufacturing and Inventory section.", raise_exception=1) - + if self.doc.is_stock_item == "Yes" and not self.doc.default_warehouse: msgprint("As we maintain stock of this item, its better to maintain default warehouse. To add default warehouse please go to 'Inventory' section. It will be fetched automatically while making Sales Order, Delivery Note, etc.. ", 1) @@ -146,7 +153,7 @@ class DocType: if flt(total_qty) < flt(self.doc.minimum_inventory_level): msgprint("Your minimum inventory level is reached") send_to = [] - send = sql("select t1.email from `tabProfile` t1,`tabUserRole` t2 where t2.role IN ('Material Master Manager','Purchase Manager') and t2.parent = t1.name") + send = sql("select t1.email from `tabProfile` t1,`tabUserRole` t2 where t2.role IN ('Material Master Manager','Purchase Manager') and t2.parent = t1.name") for d in send: send_to.append(d[0]) msg = ''' @@ -167,10 +174,10 @@ Total Available Qty: %s ret = { 'file_group' : file and file[0]['file_group'] or '', 'description' : file and file[0]['description'] or '' - + } - return str(ret) - + return ret + def check_if_sle_exists(self): """ checks if any stock ledger entry exists for this item @@ -178,3 +185,7 @@ Total Available Qty: %s sle = 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)) + diff --git a/stock/doctype/item/item.txt b/stock/doctype/item/item.txt index ec42ff4a589..0d20f7b5311 100644 --- a/stock/doctype/item/item.txt +++ b/stock/doctype/item/item.txt @@ -5,14 +5,14 @@ { 'creation': '2010-08-08 17:09:05', 'docstatus': 0, - 'modified': '2011-05-30 15:22:32', + 'modified': '2011-08-18 13:03:31', 'modified_by': 'Administrator', 'owner': 'Administrator' }, # These values are common for all DocType { - '_last_update': '1309508838', + '_last_update': '1313651083', 'allow_attach': 1, 'allow_trash': 1, 'autoname': 'field:item_code', @@ -22,13 +22,13 @@ 'max_attachments': 1, 'module': 'Stock', 'name': '__common__', - 'search_fields': 'item_name,description,item_group', + 'search_fields': 'item_name,description,item_group,customer_code', 'section_style': 'Tray', 'server_code_error': ' ', 'show_in_menu': 0, 'subject': '%(item_name)s', 'tag_fields': 'item_group', - 'version': 153 + 'version': 161 }, # These values are common for all DocField @@ -42,14 +42,12 @@ # These values are common for all DocPerm { - 'amend': 0, 'doctype': 'DocPerm', 'name': '__common__', 'parent': 'Item', 'parentfield': 'permissions', 'parenttype': 'DocType', - 'read': 1, - 'submit': 0 + 'read': 1 }, # DocType, Item @@ -60,44 +58,53 @@ # DocPerm { - 'cancel': 0, - 'create': 0, - 'doctype': 'DocPerm', - 'permlevel': 0, - 'role': 'Material User', - 'write': 0 - }, - - # DocPerm - { + 'amend': 0, 'cancel': 0, 'create': 0, 'doctype': 'DocPerm', 'idx': 1, 'permlevel': 1, 'role': 'Material Manager', + 'submit': 0, 'write': 0 }, # DocPerm { + 'amend': 0, 'cancel': 0, 'create': 0, 'doctype': 'DocPerm', 'idx': 2, 'permlevel': 0, 'role': 'Material Manager', + 'submit': 0, 'write': 0 }, # DocPerm { + 'amend': 0, 'cancel': 0, 'create': 0, 'doctype': 'DocPerm', 'idx': 3, 'permlevel': 1, 'role': 'Material User', + 'submit': 0, + 'write': 0 + }, + + # DocPerm + { + 'amend': 0, + 'cancel': 0, + 'create': 0, + 'doctype': 'DocPerm', + 'idx': 4, + 'permlevel': 0, + 'role': 'Material User', + 'submit': 0, 'write': 0 }, @@ -114,7 +121,6 @@ # DocPerm { - 'cancel': 0, 'create': 0, 'doctype': 'DocPerm', 'idx': 6, @@ -136,13 +142,10 @@ # DocPerm { - 'cancel': 0, - 'create': 0, 'doctype': 'DocPerm', 'idx': 8, 'permlevel': 1, - 'role': 'System Manager', - 'write': 0 + 'role': 'System Manager' }, # DocField @@ -197,7 +200,7 @@ 'oldfieldtype': 'Data', 'permlevel': 0, 'reqd': 1, - 'search_index': 0 + 'search_index': 1 }, # DocField @@ -241,8 +244,7 @@ 'options': 'Brand', 'permlevel': 0, 'print_hide': 1, - 'reqd': 0, - 'search_index': 0 + 'reqd': 0 }, # DocField @@ -285,7 +287,7 @@ 'description': 'Generates HTML to include image (1st attachment) in the description', 'doctype': 'DocField', 'fieldtype': 'Button', - 'idx': 12, + 'idx': 11, 'label': 'Add Image', 'permlevel': 0 }, @@ -294,7 +296,7 @@ { 'doctype': 'DocField', 'fieldtype': 'Section Break', - 'idx': 13, + 'idx': 12, 'label': 'Inventory', 'oldfieldtype': 'Section Break', 'permlevel': 0 @@ -307,14 +309,13 @@ 'doctype': 'DocField', 'fieldname': 'stock_uom', 'fieldtype': 'Link', - 'idx': 14, + 'idx': 13, 'label': 'Default UoM', 'oldfieldname': 'stock_uom', 'oldfieldtype': 'Link', 'options': 'UOM', 'permlevel': 0, - 'reqd': 1, - 'search_index': 0 + 'reqd': 1 }, # DocField @@ -325,7 +326,7 @@ 'doctype': 'DocField', 'fieldname': 'is_stock_item', 'fieldtype': 'Select', - 'idx': 15, + 'idx': 14, 'label': 'Is Stock Item', 'oldfieldname': 'is_stock_item', 'oldfieldtype': 'Select', @@ -339,7 +340,7 @@ 'doctype': 'DocField', 'fieldname': 'valuation_method', 'fieldtype': 'Select', - 'idx': 16, + 'idx': 15, 'label': 'Valuation Method', 'oldfieldname': 'valuation_method', 'oldfieldtype': 'Select', @@ -352,13 +353,12 @@ 'doctype': 'DocField', 'fieldname': 'default_warehouse', 'fieldtype': 'Link', - 'idx': 17, + 'idx': 16, 'label': 'Default Warehouse', 'oldfieldname': 'default_warehouse', 'oldfieldtype': 'Link', 'options': 'Warehouse', - 'permlevel': 0, - 'search_index': 0 + 'permlevel': 0 }, # DocField @@ -368,7 +368,7 @@ 'doctype': 'DocField', 'fieldname': 'tolerance', 'fieldtype': 'Currency', - 'idx': 18, + 'idx': 17, 'label': 'Allowance Percent', 'oldfieldname': 'tolerance', 'oldfieldtype': 'Currency', @@ -380,7 +380,7 @@ 'doctype': 'DocField', 'fieldname': 're_order_level', 'fieldtype': 'Currency', - 'idx': 19, + 'idx': 18, 'label': 'Re-Order Level', 'oldfieldname': 're_order_level', 'oldfieldtype': 'Currency', @@ -395,7 +395,7 @@ 'doctype': 'DocField', 'fieldname': 'minimum_inventory_level', 'fieldtype': 'Currency', - 'idx': 20, + 'idx': 19, 'label': 'Minimum Inventory Level', 'oldfieldname': 'minimum_inventory_level', 'oldfieldtype': 'Currency', @@ -412,7 +412,7 @@ 'fieldname': 'min_order_qty', 'fieldtype': 'Currency', 'hidden': 0, - 'idx': 21, + 'idx': 20, 'label': 'Minimum Order Qty', 'oldfieldname': 'min_order_qty', 'oldfieldtype': 'Currency', @@ -423,7 +423,7 @@ { 'doctype': 'DocField', 'fieldtype': 'Column Break', - 'idx': 22, + 'idx': 21, 'oldfieldtype': 'Column Break', 'permlevel': 0, 'width': '50%' @@ -437,7 +437,7 @@ 'doctype': 'DocField', 'fieldname': 'is_asset_item', 'fieldtype': 'Select', - 'idx': 23, + 'idx': 22, 'label': 'Is Asset Item', 'oldfieldname': 'is_asset_item', 'oldfieldtype': 'Select', @@ -453,7 +453,7 @@ 'doctype': 'DocField', 'fieldname': 'has_batch_no', 'fieldtype': 'Select', - 'idx': 24, + 'idx': 23, 'label': 'Has Batch No', 'oldfieldname': 'has_batch_no', 'oldfieldtype': 'Select', @@ -470,7 +470,8 @@ 'doctype': 'DocField', 'fieldname': 'has_serial_no', 'fieldtype': 'Select', - 'idx': 25, + 'idx': 24, + 'in_filter': 1, 'label': 'Has Serial No', 'oldfieldname': 'has_serial_no', 'oldfieldtype': 'Select', @@ -484,7 +485,7 @@ 'doctype': 'DocField', 'fieldname': 'warranty_period', 'fieldtype': 'Data', - 'idx': 26, + 'idx': 25, 'label': 'Warranty Period (in days)', 'oldfieldname': 'warranty_period', 'oldfieldtype': 'Data', @@ -496,19 +497,50 @@ 'doctype': 'DocField', 'fieldname': 'end_of_life', 'fieldtype': 'Date', - 'idx': 27, + 'idx': 26, 'label': 'End of Life', 'oldfieldname': 'end_of_life', 'oldfieldtype': 'Date', 'permlevel': 0 }, + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'nett_weight', + 'fieldtype': 'Float', + 'idx': 27, + 'label': 'Nett Weight', + 'permlevel': 0 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'gross_weight', + 'fieldtype': 'Float', + 'idx': 28, + 'label': 'Gross Weight', + 'permlevel': 0 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'weight_uom', + 'fieldtype': 'Link', + 'idx': 29, + 'label': 'Weight UOM', + 'options': 'UOM', + 'permlevel': 0 + }, + # DocField { 'colour': 'White:FFF', 'doctype': 'DocField', 'fieldtype': 'Section Break', - 'idx': 28, + 'idx': 30, 'label': 'Purchase Details', 'oldfieldtype': 'Section Break', 'permlevel': 0 @@ -522,7 +554,7 @@ 'doctype': 'DocField', 'fieldname': 'is_purchase_item', 'fieldtype': 'Select', - 'idx': 29, + 'idx': 31, 'label': 'Is Purchase Item', 'oldfieldname': 'is_purchase_item', 'oldfieldtype': 'Select', @@ -538,7 +570,7 @@ 'doctype': 'DocField', 'fieldname': 'lead_time_days', 'fieldtype': 'Int', - 'idx': 30, + 'idx': 32, 'label': 'Lead Time Days', 'no_copy': 1, 'oldfieldname': 'lead_time_days', @@ -553,13 +585,12 @@ 'doctype': 'DocField', 'fieldname': 'purchase_account', 'fieldtype': 'Link', - 'idx': 31, + 'idx': 33, 'label': 'Default Expense Account', 'oldfieldname': 'purchase_account', 'oldfieldtype': 'Link', 'options': 'Account', 'permlevel': 0, - 'search_index': 0, 'trigger': 'Client' }, @@ -570,13 +601,12 @@ 'doctype': 'DocField', 'fieldname': 'cost_center', 'fieldtype': 'Link', - 'idx': 32, + 'idx': 34, 'label': 'Default Cost Center', 'oldfieldname': 'cost_center', 'oldfieldtype': 'Link', 'options': 'Cost Center', - 'permlevel': 0, - 'search_index': 0 + 'permlevel': 0 }, # DocField @@ -586,7 +616,7 @@ 'doctype': 'DocField', 'fieldname': 'buying_cost', 'fieldtype': 'Currency', - 'idx': 33, + 'idx': 35, 'label': 'Buying Cost', 'no_copy': 1, 'oldfieldname': 'buying_cost', @@ -600,7 +630,7 @@ 'doctype': 'DocField', 'fieldname': 'last_purchase_rate', 'fieldtype': 'Currency', - 'idx': 34, + 'idx': 36, 'label': 'Last Purchase Rate', 'no_copy': 1, 'oldfieldname': 'last_purchase_rate', @@ -613,7 +643,7 @@ 'doctype': 'DocField', 'fieldname': 'standard_rate', 'fieldtype': 'Currency', - 'idx': 35, + 'idx': 37, 'label': 'Standard Rate', 'oldfieldname': 'standard_rate', 'oldfieldtype': 'Currency', @@ -624,7 +654,7 @@ { 'doctype': 'DocField', 'fieldtype': 'Column Break', - 'idx': 36, + 'idx': 38, 'oldfieldtype': 'Column Break', 'permlevel': 0, 'width': '50%' @@ -635,7 +665,7 @@ 'doctype': 'DocField', 'fieldname': 'uom_conversion_details', 'fieldtype': 'Table', - 'idx': 37, + 'idx': 39, 'label': 'UOM Conversion Details', 'oldfieldname': 'uom_conversion_details', 'oldfieldtype': 'Table', @@ -647,7 +677,7 @@ { 'doctype': 'DocField', 'fieldtype': 'Section Break', - 'idx': 38, + 'idx': 40, 'label': 'Sales Details', 'oldfieldtype': 'Section Break', 'permlevel': 0 @@ -661,7 +691,8 @@ 'doctype': 'DocField', 'fieldname': 'is_sales_item', 'fieldtype': 'Select', - 'idx': 39, + 'idx': 41, + 'in_filter': 1, 'label': 'Is Sales Item', 'oldfieldname': 'is_sales_item', 'oldfieldtype': 'Select', @@ -678,7 +709,8 @@ 'doctype': 'DocField', 'fieldname': 'is_service_item', 'fieldtype': 'Select', - 'idx': 40, + 'idx': 42, + 'in_filter': 1, 'label': 'Is Service Item', 'oldfieldname': 'is_service_item', 'oldfieldtype': 'Select', @@ -695,7 +727,7 @@ 'doctype': 'DocField', 'fieldname': 'is_sample_item', 'fieldtype': 'Select', - 'idx': 41, + 'idx': 43, 'label': 'Allow Samples', 'oldfieldname': 'is_sample_item', 'oldfieldtype': 'Select', @@ -709,7 +741,7 @@ 'doctype': 'DocField', 'fieldname': 'max_discount', 'fieldtype': 'Currency', - 'idx': 42, + 'idx': 44, 'label': 'Max Discount (%)', 'oldfieldname': 'max_discount', 'oldfieldtype': 'Currency', @@ -721,11 +753,10 @@ 'doctype': 'DocField', 'fieldname': 'default_income_account', 'fieldtype': 'Link', - 'idx': 43, + 'idx': 45, 'label': 'Default Income Account', 'options': 'Account', - 'permlevel': 0, - 'search_index': 0 + 'permlevel': 0 }, # DocField @@ -733,11 +764,10 @@ 'doctype': 'DocField', 'fieldname': 'default_sales_cost_center', 'fieldtype': 'Link', - 'idx': 44, + 'idx': 46, 'label': 'Cost Center', 'options': 'Cost Center', - 'permlevel': 0, - 'search_index': 0 + 'permlevel': 0 }, # DocField @@ -746,7 +776,7 @@ 'fieldname': 'sales_rate', 'fieldtype': 'Currency', 'hidden': 1, - 'idx': 45, + 'idx': 47, 'label': 'Sales Rate', 'oldfieldname': 'sales_rate', 'oldfieldtype': 'Currency', @@ -757,7 +787,7 @@ { 'doctype': 'DocField', 'fieldtype': 'Column Break', - 'idx': 46, + 'idx': 48, 'oldfieldtype': 'Column Break', 'permlevel': 0, 'width': '50%' @@ -770,7 +800,7 @@ 'doctype': 'DocField', 'fieldname': 'ref_rate_details', 'fieldtype': 'Table', - 'idx': 47, + 'idx': 49, 'label': 'Ref Rate Details', 'oldfieldname': 'ref_rate_details', 'oldfieldtype': 'Table', @@ -778,11 +808,23 @@ 'permlevel': 0 }, + # DocField + { + 'description': 'For the convenience of customers, these codes can be used in print formats like Invoices and Delivery Notes', + 'doctype': 'DocField', + 'fieldname': 'item_customer_details', + 'fieldtype': 'Table', + 'idx': 50, + 'label': 'Customer Codes', + 'options': 'Item Customer Detail', + 'permlevel': 0 + }, + # DocField { 'doctype': 'DocField', 'fieldtype': 'Section Break', - 'idx': 48, + 'idx': 51, 'label': 'Item Tax', 'oldfieldtype': 'Section Break', 'permlevel': 0 @@ -793,7 +835,7 @@ 'doctype': 'DocField', 'fieldname': 'item_tax', 'fieldtype': 'Table', - 'idx': 49, + 'idx': 52, 'label': 'Item Tax1', 'oldfieldname': 'item_tax', 'oldfieldtype': 'Table', @@ -805,7 +847,7 @@ { 'doctype': 'DocField', 'fieldtype': 'Section Break', - 'idx': 50, + 'idx': 53, 'label': 'Inspection Criteria', 'oldfieldtype': 'Section Break', 'permlevel': 0 @@ -817,7 +859,7 @@ 'doctype': 'DocField', 'fieldname': 'inspection_required', 'fieldtype': 'Select', - 'idx': 51, + 'idx': 54, 'label': 'Inspection Required', 'no_copy': 0, 'oldfieldname': 'inspection_required', @@ -832,7 +874,7 @@ 'doctype': 'DocField', 'fieldname': 'item_specification_details', 'fieldtype': 'Table', - 'idx': 52, + 'idx': 55, 'label': 'Item Specification Detail', 'oldfieldname': 'item_specification_details', 'oldfieldtype': 'Table', @@ -844,7 +886,7 @@ { 'doctype': 'DocField', 'fieldtype': 'Section Break', - 'idx': 53, + 'idx': 56, 'label': 'Manufacturing', 'oldfieldtype': 'Section Break', 'permlevel': 0 @@ -858,7 +900,7 @@ 'doctype': 'DocField', 'fieldname': 'is_manufactured_item', 'fieldtype': 'Select', - 'idx': 54, + 'idx': 57, 'label': 'Allow Bill of Materials', 'oldfieldname': 'is_manufactured_item', 'oldfieldtype': 'Select', @@ -873,14 +915,13 @@ 'doctype': 'DocField', 'fieldname': 'default_bom', 'fieldtype': 'Link', - 'idx': 55, + 'idx': 58, 'label': 'Default BOM', 'no_copy': 1, 'oldfieldname': 'default_bom', 'oldfieldtype': 'Link', 'options': 'Bill Of Materials', - 'permlevel': 1, - 'search_index': 0 + 'permlevel': 1 }, # DocField @@ -891,7 +932,7 @@ 'doctype': 'DocField', 'fieldname': 'is_pro_applicable', 'fieldtype': 'Select', - 'idx': 56, + 'idx': 59, 'label': 'Allow Production Order', 'oldfieldname': 'is_pro_applicable', 'oldfieldtype': 'Select', @@ -908,7 +949,7 @@ 'doctype': 'DocField', 'fieldname': 'is_sub_contracted_item', 'fieldtype': 'Select', - 'idx': 57, + 'idx': 60, 'label': 'Is Sub Contracted Item', 'oldfieldname': 'is_sub_contracted_item', 'oldfieldtype': 'Select', @@ -923,9 +964,23 @@ 'fieldname': 'file_list', 'fieldtype': 'Text', 'hidden': 1, - 'idx': 59, + 'idx': 61, 'label': 'File List', 'permlevel': 0, 'print_hide': 1 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'customer_code', + 'fieldtype': 'Data', + 'hidden': 1, + 'idx': 62, + 'in_filter': 1, + 'label': 'Customer Code', + 'no_copy': 1, + 'permlevel': 0, + 'print_hide': 1 } ] \ No newline at end of file diff --git a/hr/doctype/salary_slip_control_panel/__init__.py b/stock/doctype/item_customer_detail/__init__.py similarity index 100% rename from hr/doctype/salary_slip_control_panel/__init__.py rename to stock/doctype/item_customer_detail/__init__.py diff --git a/stock/doctype/item_customer_detail/item_customer_detail.txt b/stock/doctype/item_customer_detail/item_customer_detail.txt new file mode 100644 index 00000000000..f53f18ecaa2 --- /dev/null +++ b/stock/doctype/item_customer_detail/item_customer_detail.txt @@ -0,0 +1,73 @@ +# DocType, Item Customer Detail +[ + + # These values are common in all dictionaries + { + 'creation': '2011-08-18 11:38:43', + 'docstatus': 0, + 'modified': '2011-08-18 11:54:36', + 'modified_by': 'Administrator', + 'owner': 'Administrator' + }, + + # These values are common for all DocType + { + 'autoname': 'ITEMCUST/.#####', + 'colour': 'White:FFF', + 'description': 'For the convenience of customers, these codes can be used in print formats like Invoices and Delivery Notes', + 'doctype': 'DocType', + 'in_create': 1, + 'istable': 1, + 'module': 'Stock', + 'name': '__common__', + 'read_only': 0, + 'section_style': 'Tray', + 'server_code_error': ' ', + 'show_in_menu': 0, + 'version': 7 + }, + + # These values are common for all DocField + { + 'doctype': 'DocField', + 'in_filter': 1, + 'name': '__common__', + 'parent': 'Item Customer Detail', + 'parentfield': 'fields', + 'parenttype': 'DocType', + 'permlevel': 0, + 'reqd': 1, + 'search_index': 1 + }, + + # DocType, Item Customer Detail + { + 'doctype': 'DocType', + 'name': 'Item Customer Detail' + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'customer_name', + 'fieldtype': 'Link', + 'idx': 1, + 'label': 'Customer Name', + 'oldfieldname': 'price_list_name', + 'oldfieldtype': 'Select', + 'options': 'Customer', + 'width': '180px' + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'ref_code', + 'fieldtype': 'Data', + 'idx': 2, + 'label': 'Ref Code', + 'oldfieldname': 'ref_rate', + 'oldfieldtype': 'Currency', + 'width': '120px' + } +] \ No newline at end of file diff --git a/stock/doctype/purchase_receipt/purchase_receipt.py b/stock/doctype/purchase_receipt/purchase_receipt.py index 0eda680cae1..bb2b456111a 100644 --- a/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/stock/doctype/purchase_receipt/purchase_receipt.py @@ -13,7 +13,7 @@ sql = webnotes.conn.sql get_value = webnotes.conn.get_value in_transaction = webnotes.conn.in_transaction convert_to_lists = webnotes.conn.convert_to_lists - + # ----------------------------------------------------------------------------------------- from utilities.transaction_base import TransactionBase @@ -38,23 +38,20 @@ class DocType(TransactionBase): def get_default_schedule_date(self): get_obj(dt = 'Purchase Common').get_default_schedule_date(self) - + #-----------------Validation For Fiscal Year------------------------ def validate_fiscal_year(self): get_obj(dt = 'Purchase Common').validate_fiscal_year(self.doc.fiscal_year,self.doc.transaction_date,'Transaction Date') - - # Get Supplier Details - #def get_supplier_details(self, name = ''): - # return cstr(get_obj(dt='Purchase Common').get_supplier_details(name)) - + + # Get Item Details def get_item_details(self, arg = ''): - return cstr(get_obj(dt='Purchase Common').get_item_details(self,arg)) - + return get_obj(dt='Purchase Common').get_item_details(self,arg) + # Get UOM Details def get_uom_details(self, arg = ''): - return cstr(get_obj(dt='Purchase Common').get_uom_details(arg)) - + return get_obj(dt='Purchase Common').get_uom_details(arg) + # GET TERMS & CONDITIONS # ===================================================================================== def get_tc_details(self): @@ -62,16 +59,16 @@ class DocType(TransactionBase): # get available qty at warehouse def get_bin_details(self, arg = ''): - return cstr(get_obj(dt='Purchase Common').get_bin_details(arg)) + return get_obj(dt='Purchase Common').get_bin_details(arg) # Pull Purchase Order def get_po_details(self): self.validate_prev_docname() get_obj('DocType Mapper', 'Purchase Order-Purchase Receipt').dt_map('Purchase Order', 'Purchase Receipt', self.doc.purchase_order_no, self.doc, self.doclist, "[['Purchase Order','Purchase Receipt'],['PO Detail', 'Purchase Receipt Detail'],['Purchase Tax Detail','Purchase Tax Detail']]") - + # validate if PO has been pulled twice def validate_prev_docname(self): - for d in getlist(self.doclist, 'purchase_receipt_details'): + for d in getlist(self.doclist, 'purchase_receipt_details'): if self.doc.purchase_order_no and d.prevdoc_docname and self.doc.purchase_order_no == d.prevdoc_docname: msgprint(cstr(self.doc.purchase_order_no) + " Purchase Order details have already been pulled. ") raise Exception @@ -82,15 +79,15 @@ class DocType(TransactionBase): # validate accepted and rejected qty def validate_accepted_rejected_qty(self): for d in getlist(self.doclist, "purchase_receipt_details"): - - # If Reject Qty than Rejected warehouse is mandatory + + # If Reject Qty than Rejected warehouse is mandatory if flt(d.rejected_qty) and (not self.doc.rejected_warehouse): msgprint("Rejected Warehouse is necessary if there are rejections. See 'Receipt Items'") raise Exception - # Check Received Qty = Accepted Qty + Rejected Qty + # Check Received Qty = Accepted Qty + Rejected Qty if ((flt(d.qty) + flt(d.rejected_qty)) != flt(d.received_qty)): - + msgprint("Sum of Accepted Qty and Rejected Qty must be equal to Received quantity. Error for Item: " + cstr(d.item_code)) raise Exception @@ -102,8 +99,8 @@ class DocType(TransactionBase): if flt(self.doc.net_total) and flt(d.qty): #d.valuation_rate = (flt(d.purchase_rate) + ((flt(d.amount) * (total_b_cost)) / (self.doc.net_total * flt(d.qty))) + (flt(d.rm_supp_cost) / flt(d.qty))) / flt(d.conversion_factor) d.valuation_rate = (flt(d.purchase_rate) + ((flt(d.amount) * (total_b_cost)) / (self.doc.net_total * flt(d.qty))) + (flt(d.rm_supp_cost) / flt(d.qty)) + (flt(d.item_tax_amount)/flt(d.qty))) / flt(d.conversion_factor) - - # Check for Stopped status + + # Check for Stopped status def check_for_stopped_status(self, pc_obj): check_list =[] for d in getlist(self.doclist, 'purchase_receipt_details'): @@ -120,8 +117,8 @@ class DocType(TransactionBase): if not d.prevdoc_docname: msgprint("Purchse Order No. required against item %s"%d.item_code) raise Exception - - + + # validate def validate(self): self.po_required() @@ -140,20 +137,20 @@ class DocType(TransactionBase): self.check_for_stopped_status(pc_obj) # get total in words - dcc = TransactionBase().get_company_currency(self.doc.company) + dcc = TransactionBase().get_company_currency(self.doc.company) self.doc.in_words = pc_obj.get_total_in_words(dcc, self.doc.grand_total) self.doc.in_words_import = pc_obj.get_total_in_words(self.doc.currency, self.doc.grand_total_import) # update valuation rate self.update_valuation_rate() - + # On Update - # ---------------------------------------------------------------------------------------------------- + # ---------------------------------------------------------------------------------------------------- def on_update(self): if self.doc.rejected_warehouse: for d in getlist(self.doclist,'purchase_receipt_details'): d.rejected_warehouse = self.doc.rejected_warehouse - + self.update_rw_material_detail() get_obj('Stock Ledger').scrub_serial_nos(self) @@ -169,23 +166,23 @@ class DocType(TransactionBase): # Check if is_stock_item == 'Yes' if sql("select is_stock_item from tabItem where name=%s", d.item_code)[0][0]=='Yes': ord_qty = 0 - pr_qty = flt(d.qty) * flt(d.conversion_factor) - - # Check If Prevdoc Doctype is Purchase Order + pr_qty = flt(d.qty) * flt(d.conversion_factor) + + # Check If Prevdoc Doctype is Purchase Order if cstr(d.prevdoc_doctype) == 'Purchase Order': - # get qty and pending_qty of prevdoc + # get qty and pending_qty of prevdoc curr_ref_qty = pc_obj.get_qty( d.doctype, 'prevdoc_detail_docname', d.prevdoc_detail_docname, 'PO Detail', 'Purchase Order - Purchase Receipt', self.doc.name) max_qty, qty, curr_qty = flt(curr_ref_qty.split('~~~')[1]), flt(curr_ref_qty.split('~~~')[0]), 0 - + if flt(qty) + flt(pr_qty) > flt(max_qty): curr_qty = (flt(max_qty) - flt(qty)) * flt(d.conversion_factor) else: curr_qty = flt(pr_qty) - + ord_qty = -flt(curr_qty) # update order qty in bin bin = get_obj('Warehouse', d.warehouse).update_bin(0, 0, (is_submit and 1 or -1) * flt(ord_qty), 0, 0, d.item_code, self.doc.transaction_date) - + # UPDATE actual qty to warehouse by pr_qty self.make_sl_entry(d, d.warehouse, flt(pr_qty), d.valuation_rate, is_submit) # UPDATE actual to rejected warehouse by rejected qty @@ -208,8 +205,8 @@ class DocType(TransactionBase): 'posting_time' : self.doc.posting_time, 'voucher_type' : 'Purchase Receipt', 'voucher_no' : self.doc.name, - 'voucher_detail_no' : d.name, - 'actual_qty' : qty, + 'voucher_detail_no' : d.name, + 'actual_qty' : qty, 'stock_uom' : d.stock_uom, 'incoming_rate' : in_value, 'company' : self.doc.company, @@ -223,11 +220,11 @@ class DocType(TransactionBase): def validate_inspection(self): for d in getlist(self.doclist, 'purchase_receipt_details'): #Enter inspection date for all items that require inspection ins_reqd = sql("select inspection_required from `tabItem` where name = %s", (d.item_code), as_dict = 1) - ins_reqd = ins_reqd and ins_reqd[0]['inspection_required'] or 'No' + ins_reqd = ins_reqd and ins_reqd[0]['inspection_required'] or 'No' if ins_reqd == 'Yes' and not d.qa_no: msgprint("Item: " + d.item_code + " requires QA Inspection. Please enter QA No or report to authorized person to create QA Inspection Report") - # Check for Stopped status + # Check for Stopped status def check_for_stopped_status(self, pc_obj): check_list =[] for d in getlist(self.doclist, 'purchase_receipt_details'): @@ -236,7 +233,7 @@ class DocType(TransactionBase): pc_obj.check_for_stopped_status( d.prevdoc_doctype, d.prevdoc_docname) - # on submit + # on submit def on_submit(self): # Check for Approving Authority get_obj('Authorization Control').validate_approving_authority(self.doc.doctype, self.doc.company, self.doc.grand_total) @@ -244,19 +241,19 @@ class DocType(TransactionBase): # Set status as Submitted set(self.doc,'status', 'Submitted') pc_obj = get_obj('Purchase Common') - + # Update Previous Doc i.e. update pending_qty and Status accordingly pc_obj.update_prevdoc_detail(self, is_submit = 1) - + # Update Serial Record get_obj('Stock Ledger').update_serial_record(self, 'purchase_receipt_details', is_submit = 1, is_incoming = 1) - # Update Stock + # Update Stock self.update_stock(is_submit = 1) - - # Update last purchase rate + + # Update last purchase rate pc_obj.update_last_purchase_rate(self, 1) - + # on submit notification get_obj('Notification Control').notify_contact('Purchase Receipt', self.doc.doctype,self.doc.name, self.doc.email_id, self.doc.contact_person) @@ -274,11 +271,11 @@ class DocType(TransactionBase): def on_cancel(self): pc_obj = get_obj('Purchase Common') - + self.check_for_stopped_status(pc_obj) # 1.Check if Payable Voucher has been submitted against current Purchase Order # pc_obj.check_docstatus(check = 'Next', doctype = 'Payable Voucher', docname = self.doc.name, detail_doctype = 'PV Detail') - + submitted = sql("select t1.name from `tabPayable Voucher` t1,`tabPV Detail` t2 where t1.name = t2.parent and t2.purchase_receipt = '%s' and t1.docstatus = 1" % self.doc.name) if submitted: msgprint("Purchase Invoice : " + cstr(submitted[0][0]) + " has already been submitted !") @@ -286,27 +283,27 @@ class DocType(TransactionBase): # 2.Set Status as Cancelled set(self.doc,'status','Cancelled') - - # 3. Cancel Serial No + + # 3. Cancel Serial No get_obj('Stock Ledger').update_serial_record(self, 'purchase_receipt_details', is_submit = 0, is_incoming = 1) - # 4.Update Bin + # 4.Update Bin self.update_stock(is_submit = 0) - - # 5.Update Indents Pending Qty and accordingly it's Status + + # 5.Update Indents Pending Qty and accordingly it's Status pc_obj.update_prevdoc_detail(self, is_submit = 0) - # 6. Update last purchase rate + # 6. Update last purchase rate pc_obj.update_last_purchase_rate(self, 0) - + #----------- code for Sub-contracted Items ------------------- #--------check for sub-contracted items and accordingly update PR raw material detail table-------- def update_rw_material_detail(self): - + for d in getlist(self.doclist,'purchase_receipt_details'): item_det = sql("select is_sub_contracted_item, is_purchase_item from `tabItem` where name = '%s'"%(d.item_code)) - + if item_det[0][0] == 'Yes': if item_det[0][1] == 'Yes': if not self.doc.is_subcontracted: @@ -315,7 +312,7 @@ class DocType(TransactionBase): if self.doc.is_subcontracted == 'Yes': if not self.doc.supplier_warehouse: msgprint("Please Enter Supplier Warehouse for subcontracted Items") - raise Exception + raise Exception self.add_bom(d) else: self.doc.clear_table(self.doclist,'pr_raw_material_details',1) @@ -325,7 +322,7 @@ class DocType(TransactionBase): msgprint("Please Enter Supplier Warehouse for subcontracted Items") raise Exception self.add_bom(d) - + self.delete_irrelevant_raw_material() #---------------calculate amt in PR Raw Material Detail------------- self.calculate_amount(d) @@ -341,7 +338,7 @@ class DocType(TransactionBase): #-------------- add child function-------------------- chgd_rqd_qty = [] for i in bom_det: - + if i and not sql("select name from `tabPR Raw Material Detail` where reference_name = '%s' and bom_detail_no = '%s' and parent = '%s' " %(d.name, i[6], self.doc.name)): rm_child = addchild(self.doc, 'pr_raw_material_details', 'PR Raw Material Detail', 1, self.doclist) @@ -350,7 +347,7 @@ class DocType(TransactionBase): rm_child.bom_detail_no = i and i[6] or '' rm_child.main_item_code = i and i[0] or '' rm_child.rm_item_code = i and i[1] or '' - rm_child.description = i and i[7] or '' + rm_child.description = i and i[7] or '' rm_child.stock_uom = i and i[5] or '' rm_child.rate = i and flt(i[3]) or flt(i[4]) rm_child.conversion_factor = d.conversion_factor @@ -366,7 +363,7 @@ class DocType(TransactionBase): chgd_rqd_qty.append(cstr(i[1])) pr_rmd.main_item_code = i[0] pr_rmd.rm_item_code = i[1] - pr_rmd.description = i[7] + pr_rmd.description = i[7] pr_rmd.stock_uom = i[5] pr_rmd.required_qty = flt(act_qty) pr_rmd.consumed_qty = flt(act_qty) @@ -375,20 +372,20 @@ class DocType(TransactionBase): pr_rmd.save() if chgd_rqd_qty: msgprint("Please check consumed quantity for Raw Material Item Code: '%s'in Raw materials Detail Table" % ((len(chgd_rqd_qty) > 1 and ','.join(chgd_rqd_qty[:-1]) +' and ' + cstr(chgd_rqd_qty[-1:][0]) ) or cstr(chgd_rqd_qty[0]))) - + # Delete irrelevant raw material from PR Raw material details - #-------------------------------------------------------------- + #-------------------------------------------------------------- def delete_irrelevant_raw_material(self): for d in getlist(self.doclist,'pr_raw_material_details'): if not sql("select name from `tabPurchase Receipt Detail` where name = '%s' and parent = '%s' and item_code = '%s'" % (d.reference_name, self.doc.name, d.main_item_code)): d.parent = 'old_par:'+self.doc.name d.save() - + def calculate_amount(self, d): amt = 0 for i in getlist(self.doclist,'pr_raw_material_details'): - + if(i.reference_name == d.name): #if i.consumed_qty == 0: # msgprint("consumed qty cannot be 0. Please Enter consumed qty ") @@ -397,7 +394,7 @@ class DocType(TransactionBase): amt += i.amount d.rm_supp_cost = amt d.save() - + # --------------- Back Flush function called on submit and on cancel from update stock def bk_flush_supp_wh(self, is_submit): @@ -405,7 +402,7 @@ class DocType(TransactionBase): #--------- -ve quantity is passed as raw material qty has to be decreased when PR is submitted and it has to be increased when PR is cancelled consumed_qty = - flt(d.consumed_qty) self.make_sl_entry(d, self.doc.supplier_warehouse, flt(consumed_qty), 0, is_submit) - + # get current_stock # ---------------- @@ -414,13 +411,13 @@ class DocType(TransactionBase): if self.doc.supplier_warehouse: bin = sql("select actual_qty from `tabBin` where item_code = %s and warehouse = %s", (d.rm_item_code, self.doc.supplier_warehouse), as_dict = 1) d.current_stock = bin and flt(bin[0]['actual_qty']) or 0 - - - + + + # OTHER CHARGES TRIGGER FUNCTIONS # ==================================================================================== - + # *********** Get Tax rate if account type is TAX ******************** def get_rate(self,arg): return get_obj('Purchase Common').get_rate(arg,self) diff --git a/stock/doctype/sales_bom/sales_bom.py b/stock/doctype/sales_bom/sales_bom.py index 3bd6fa520e5..ce4567efb1c 100644 --- a/stock/doctype/sales_bom/sales_bom.py +++ b/stock/doctype/sales_bom/sales_bom.py @@ -38,7 +38,7 @@ class DocType: def get_item_details(self, name): det = sql("select description, stock_uom from `tabItem` where name = '%s' " % cstr(name)) rate = sql("select ref_rate from `tabRef Rate Detail` where price_list_name = %s and parent = %s and ref_currency = %s", (self.doc.price_list, name, self.doc.currency)) - return cstr({'description' : det and det[0][0] or '', 'uom': det and det[0][1] or '', 'rate': rate and flt(rate[0][0]) or 0.00}) + return {'description' : det and det[0][0] or '', 'uom': det and det[0][1] or '', 'rate': rate and flt(rate[0][0]) or 0.00} def get_main_item(self): diff --git a/stock/doctype/serial_no/serial_no.js b/stock/doctype/serial_no/serial_no.js index 32620ddab0a..a41113c313f 100644 --- a/stock/doctype/serial_no/serial_no.js +++ b/stock/doctype/serial_no/serial_no.js @@ -7,15 +7,16 @@ cur_frm.cscript.onload = function(doc, cdt, cdn) { // ************************************** refresh *************************************************** cur_frm.cscript.refresh = function(doc, cdt, cdn) { - if(!doc.__islocal && doc.warehouse) set_field_permlevel('warehouse', 1); - if(!doc.__islocal && doc.item_code) set_field_permlevel('item_code', 1); - if(doc.__islocal) set_field_permlevel('status', 0); + if(!doc.__islocal) { + flds = ['item_code', 'warehouse', 'purchase_document_type', 'purchase_document_no', 'purchase_date', 'purchase_time', 'purchase_rate', 'supplier'] + for(i=0;i= datetime.date.today() and self.doc.maintenance_status == 'Out of AMC': - msgprint("AMC expiry date and maintenance status mismatch. Please verify") - raise Exception - elif (not self.doc.amc_expiry_date or getdate(self.doc.amc_expiry_date) < datetime.date.today()) and self.doc.maintenance_status == 'Under AMC': - msgprint("AMC expiry date and maintenance status mismatch. Please verify") - raise Exception + """ + validate amc status + """ + if (self.doc.maintenance_status == 'Out of AMC' and self.doc.amc_expiry_date and getdate(self.doc.amc_expiry_date) >= datetime.date.today()) or (self.doc.maintenance_status == 'Under AMC' and (not self.doc.amc_expiry_date or getdate(self.doc.amc_expiry_date) < datetime.date.today())): + msgprint("AMC expiry date and maintenance status mismatch. Please verify", raise_exception=1) - - # ------------------------- - # validate warranty status - # ------------------------- def validate_warranty_status(self): - if self.doc.warranty_expiry_date and getdate(self.doc.warranty_expiry_date) >= datetime.date.today() and self.doc.maintenance_status == 'Out of Warranty': - msgprint("Warranty expiry date and maintenance status mismatch. Please verify") - raise Exception - elif (not self.doc.warranty_expiry_date or getdate(self.doc.warranty_expiry_date) < datetime.date.today()) and self.doc.maintenance_status == 'Under Warranty': - msgprint("Warranty expiry date and maintenance status mismatch. Please verify") - raise Exception - - - # ------------------------------- - # validate warranty / amc status - # ------------------------------- - def validate_warranty_amc_status(self): - self.validate_warranty_status() - self.validate_amc_status() + """ + validate warranty status + """ + if (self.doc.maintenance_status == 'Out of Warranty' and self.doc.warranty_expiry_date and getdate(self.doc.warranty_expiry_date) >= datetime.date.today()) or (self.doc.maintenance_status == 'Under Warranty' and (not self.doc.warranty_expiry_date or getdate(self.doc.warranty_expiry_date) < datetime.date.today())): + msgprint("Warranty expiry date and maintenance status mismatch. Please verify", raise_exception=1) def validate_warehouse(self): @@ -56,6 +36,9 @@ class DocType(TransactionBase): msgprint("Warehouse is mandatory if this Serial No is In Store", raise_exception=1) def validate_item(self): + """ + Validate whether serial no is required for this item + """ item = sql("select name, has_serial_no from tabItem where name = '%s'" % self.doc.item_code) if not item: msgprint("Item is not exists in the system", raise_exception=1) @@ -67,7 +50,8 @@ class DocType(TransactionBase): # validate # --------- def validate(self): - self.validate_warranty_amc_status() + self.validate_warranty_status() + self.validate_amc_status() self.validate_warehouse() self.validate_item() @@ -102,7 +86,7 @@ class DocType(TransactionBase): # on update # ---------- def on_update(self): - if self.doc.warehouse and not sql("select name from `tabStock Ledger Entry` where serial_no = '%s'" % (self.doc.name)) and self.doc.status == 'In Store': + if self.doc.localname and self.doc.warehouse and self.doc.status == 'In Store' and not sql("select name from `tabStock Ledger Entry` where serial_no = '%s' and ifnull(is_cancelled, 'No') = 'No'" % (self.doc.name)): self.make_stock_ledger_entry(update_stock = 1) diff --git a/stock/doctype/stock_entry/stock_entry.py b/stock/doctype/stock_entry/stock_entry.py index b380995b347..024bd1f34b8 100644 --- a/stock/doctype/stock_entry/stock_entry.py +++ b/stock/doctype/stock_entry/stock_entry.py @@ -54,7 +54,7 @@ class DocType: 'conversion_factor' : 1, 'batch_no' : '' } - return str(ret) + return ret # Get UOM Details @@ -70,7 +70,7 @@ class DocType: 'conversion_factor' : flt(uom[0]['conversion_factor']), 'transfer_qty' : flt(arg['qty']) * flt(uom[0]['conversion_factor']), } - return str(ret) + return ret # get stock and incoming rate on posting date @@ -355,6 +355,9 @@ class DocType: # ---------------------------------- def update_serial_no(self, is_submit): sl_obj = get_obj('Stock Ledger') + if is_submit: + sl_obj.validate_serial_no_warehouse(self, 'mtn_details') + for d in getlist(self.doclist, 'mtn_details'): if d.serial_no: serial_nos = sl_obj.get_sr_no_list(d.serial_no) @@ -363,7 +366,7 @@ class DocType: if d.s_warehouse: sl_obj.update_serial_delivery_details(self, d, serial_no, is_submit) if d.t_warehouse: - sl_obj.update_serial_purchase_details(self, d, serial_no, is_submit, (self.doc.purpose in ['Material Transfer', 'Sales Return']) and 1 or 0) + sl_obj.update_serial_purchase_details(self, d, serial_no, is_submit, self.doc.purpose) if self.doc.purpose == 'Purchase Return': delete_doc("Serial No", serial_no) @@ -396,7 +399,7 @@ class DocType: 'customer_name' : res and res[0][1] or '', 'customer_address' : res and res[0][2] or ''} - return str(ret) + return ret def get_cust_addr(self): @@ -405,7 +408,7 @@ class DocType: 'customer_name' : res and res[0][0] or '', 'customer_address' : res and res[0][1] or ''} - return str(ret) + return ret @@ -415,7 +418,7 @@ class DocType: 'supplier' : res and res[0][0] or '', 'supplier_name' :res and res[0][1] or '', 'supplier_address' : res and res[0][2] or ''} - return str(ret) + return ret def get_supp_addr(self): @@ -423,4 +426,4 @@ class DocType: ret = { 'supplier_name' : res and res[0][0] or '', 'supplier_address' : res and res[0][1] or ''} - return str(ret) + return ret diff --git a/stock/doctype/stock_entry/stock_entry.txt b/stock/doctype/stock_entry/stock_entry.txt index d7477c223bd..63f718bec13 100644 --- a/stock/doctype/stock_entry/stock_entry.txt +++ b/stock/doctype/stock_entry/stock_entry.txt @@ -5,14 +5,14 @@ { 'creation': '2010-08-08 17:09:25', 'docstatus': 0, - 'modified': '2011-07-11 12:48:52', + 'modified': '2011-08-22 14:36:19', 'modified_by': 'Administrator', 'owner': 'Administrator' }, # These values are common for all DocType { - '_last_update': '1308741898', + '_last_update': '1311621379', 'allow_attach': 0, 'allow_copy': 0, 'allow_email': 0, @@ -40,7 +40,7 @@ 'subject': '%(remarks)s', 'tag_fields': 'purpose', 'use_template': 0, - 'version': 243 + 'version': 245 }, # These values are common for all DocField @@ -70,15 +70,15 @@ # DocPerm { - 'amend': 1, - 'cancel': 1, - 'create': 1, + 'amend': 0, + 'cancel': 0, + 'create': 0, 'doctype': 'DocPerm', 'idx': 1, - 'permlevel': 0, + 'permlevel': 1, 'role': 'Material Manager', - 'submit': 1, - 'write': 1 + 'submit': 0, + 'write': 0 }, # DocPerm @@ -89,7 +89,7 @@ 'doctype': 'DocPerm', 'idx': 2, 'permlevel': 1, - 'role': 'Material Manager', + 'role': 'Material User', 'submit': 0, 'write': 0 }, @@ -102,7 +102,7 @@ 'doctype': 'DocPerm', 'idx': 3, 'permlevel': 0, - 'role': 'Material User', + 'role': 'Production User', 'submit': 1, 'write': 1 }, @@ -115,69 +115,60 @@ 'doctype': 'DocPerm', 'idx': 4, 'permlevel': 1, - 'role': 'Material User', + 'role': 'Production User', 'submit': 0, 'write': 0 }, + # DocPerm + { + 'amend': 0, + 'cancel': 0, + 'create': 0, + 'doctype': 'DocPerm', + 'idx': 5, + 'permlevel': 2, + 'role': 'Production User', + 'submit': 0, + 'write': 1 + }, + # DocPerm { 'amend': 1, 'cancel': 1, 'create': 1, 'doctype': 'DocPerm', - 'idx': 5, + 'idx': 6, 'permlevel': 0, - 'role': 'Production User', + 'role': 'Production Manager', 'submit': 1, 'write': 1 }, # DocPerm { - 'doctype': 'DocPerm', - 'idx': 6, - 'permlevel': 1, - 'role': 'Production User' - }, - - # DocPerm - { + 'amend': 0, + 'cancel': 0, 'create': 0, 'doctype': 'DocPerm', 'idx': 7, - 'permlevel': 2, - 'role': 'Production User', - 'write': 1 + 'permlevel': 1, + 'role': 'Production Manager', + 'submit': 0, + 'write': 0 }, # DocPerm { - 'amend': 1, - 'cancel': 1, - 'create': 1, + 'amend': 0, + 'cancel': 0, + 'create': 0, 'doctype': 'DocPerm', 'idx': 8, - 'permlevel': 0, - 'role': 'Production Manager', - 'submit': 1, - 'write': 1 - }, - - # DocPerm - { - 'doctype': 'DocPerm', - 'idx': 9, - 'permlevel': 1, - 'role': 'Production Manager' - }, - - # DocPerm - { - 'doctype': 'DocPerm', - 'idx': 10, 'permlevel': 2, 'role': 'Production Manager', + 'submit': 0, 'write': 1 }, @@ -452,7 +443,7 @@ 'oldfieldname': 'process', 'oldfieldtype': 'Select', 'options': '\nMaterial Transfer\nBackflush', - 'permlevel': 2, + 'permlevel': 0, 'print_hide': 1, 'report_hide': 0, 'search_index': 0, @@ -474,7 +465,7 @@ 'oldfieldname': 'production_order', 'oldfieldtype': 'Link', 'options': 'Production Order', - 'permlevel': 2, + 'permlevel': 0, 'print_hide': 1, 'report_hide': 0, 'search_index': 1, @@ -493,7 +484,7 @@ 'no_copy': 0, 'oldfieldname': 'fg_completed_qty', 'oldfieldtype': 'Currency', - 'permlevel': 2, + 'permlevel': 0, 'print_hide': 1, 'report_hide': 0, 'search_index': 0, @@ -802,7 +793,7 @@ { 'doctype': 'DocField', 'fieldtype': 'Column Break', - 'idx': 36, + 'idx': 35, 'oldfieldtype': 'Column Break', 'permlevel': 0 }, @@ -814,13 +805,13 @@ 'doctype': 'DocField', 'fieldtype': 'Button', 'hidden': 0, - 'idx': 37, + 'idx': 36, 'in_filter': 0, 'label': 'Get Items', 'no_copy': 0, 'oldfieldtype': 'Button', 'options': 'get_items', - 'permlevel': 2, + 'permlevel': 0, 'print_hide': 1, 'report_hide': 0, 'search_index': 0 @@ -830,7 +821,7 @@ { 'doctype': 'DocField', 'fieldtype': 'Section Break', - 'idx': 38, + 'idx': 37, 'oldfieldtype': 'Section Break', 'options': 'Simple', 'permlevel': 0 @@ -843,7 +834,7 @@ 'doctype': 'DocField', 'fieldname': 'mtn_details', 'fieldtype': 'Table', - 'idx': 39, + 'idx': 38, 'in_filter': 0, 'label': 'MTN Details', 'no_copy': 0, @@ -862,7 +853,7 @@ 'doctype': 'DocField', 'fieldname': 'total_amount', 'fieldtype': 'Currency', - 'idx': 40, + 'idx': 39, 'in_filter': 0, 'label': 'Total Amount', 'no_copy': 0, @@ -878,7 +869,7 @@ { 'doctype': 'DocField', 'fieldtype': 'Section Break', - 'idx': 41, + 'idx': 40, 'label': 'Other Details', 'oldfieldtype': 'Section Break', 'permlevel': 0 @@ -890,7 +881,7 @@ 'doctype': 'DocField', 'fieldname': 'company', 'fieldtype': 'Link', - 'idx': 42, + 'idx': 41, 'in_filter': 1, 'label': 'Company', 'no_copy': 0, @@ -910,7 +901,7 @@ 'doctype': 'DocField', 'fieldname': 'fiscal_year', 'fieldtype': 'Select', - 'idx': 43, + 'idx': 42, 'in_filter': 0, 'label': 'Fiscal Year', 'no_copy': 0, @@ -930,7 +921,7 @@ 'doctype': 'DocField', 'fieldname': 'select_print_heading', 'fieldtype': 'Link', - 'idx': 44, + 'idx': 43, 'in_filter': 0, 'label': 'Select Print Heading', 'no_copy': 0, diff --git a/stock/doctype/stock_entry_detail/stock_entry_detail.txt b/stock/doctype/stock_entry_detail/stock_entry_detail.txt index 1d2408bf88b..50b7154a0ef 100644 --- a/stock/doctype/stock_entry_detail/stock_entry_detail.txt +++ b/stock/doctype/stock_entry_detail/stock_entry_detail.txt @@ -253,7 +253,8 @@ 'no_copy': 1, 'oldfieldname': 'serial_no', 'oldfieldtype': 'Text', - 'permlevel': 0 + 'permlevel': 0, + 'reqd': 0 }, # DocField @@ -280,4 +281,4 @@ 'oldfieldtype': 'Currency', 'permlevel': 1 } -] \ No newline at end of file +] diff --git a/stock/doctype/stock_ledger/stock_ledger.py b/stock/doctype/stock_ledger/stock_ledger.py index e67afa623b9..dca975402c9 100644 --- a/stock/doctype/stock_ledger/stock_ledger.py +++ b/stock/doctype/stock_ledger/stock_ledger.py @@ -13,7 +13,7 @@ sql = webnotes.conn.sql get_value = webnotes.conn.get_value in_transaction = webnotes.conn.in_transaction convert_to_lists = webnotes.conn.convert_to_lists - + # ----------------------------------------------------------------------------------------- def get_sr_no_list(sr_nos, qty = 0): @@ -55,15 +55,17 @@ class DocType: serial_nos = self.get_sr_no_list(d.serial_no) for s in serial_nos: s = s.strip() - sr_war = sql("select warehouse from `tabSerial No` where name = '%s'" % (s)) + sr_war = sql("select warehouse,name from `tabSerial No` where name = '%s'" % (s)) if not sr_war: - msgprint("Please set a warehouse in the Serial No %s" % s, raise_exception = 1) - if sr_war[0][0] != d.warehouse: - msgprint("Serial No : %s for Item : %s doesn't exists in Warehouse : %s" % (s, d.item_code, d.warehouse), raise_exception = 1) - + msgprint("Serial No %s does not exists"%s, raise_exception = 1) + elif not sr_war[0][0]: + msgprint("Warehouse not mentioned in the Serial No %s" % s, raise_exception = 1) + elif (d.warehouse and sr_war[0][0] != d.warehouse) or (d.s_warehouse and sr_war[0][0] != d.s_warehouse): + msgprint("Serial No : %s for Item : %s doesn't exists in Warehouse : %s" % (s, d.item_code, d.warehouse or d.s_warehouse), raise_exception = 1) + # ------------------------------------ - # check whether serial no is required + # check whether serial no is required # ------------------------------------ def validate_serial_no(self, obj, fname): for d in getlist(obj.doclist, fname): @@ -76,9 +78,9 @@ class DocType: msgprint("If serial no required, please select 'Yes' in 'Has Serial No' in Item :" + d.item_code + ', otherwise please remove serial no', raise_exception=1) elif ar_required == 'Yes' and not d.serial_no: msgprint("Serial no is mandatory for item: "+ d.item_code, raise_exception = 1) - - + + # ------------------- # get serial no list # ------------------- @@ -90,37 +92,37 @@ class DocType: # --------------------- def set_pur_serial_no_values(self, obj, serial_no, d, s, new_rec): item_details = 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) - s.purchase_document_type = obj.doc.doctype - s.purchase_document_no = obj.doc.name - s.purchase_date = obj.doc.posting_date - s.purchase_time = obj.doc.posting_time - s.purchase_rate = d.purchase_rate or d.incoming_rate - s.item_code = d.item_code - s.brand = d.brand - s.description = d.description - s.item_group = item_details and item_details[0]['item_group'] or '' - s.warranty_period = item_details and item_details[0]['warranty_period'] or 0 - s.supplier = obj.doc.supplier - s.supplier_name = obj.doc.supplier_name - s.supplier_address = obj.doc.supplier_address - s.warehouse = d.warehouse or d.t_warehouse - s.docstatus = 0 - s.status = 'In Store' - s.modified = nowdate() - s.modified_by = session['user'] - s.serial_no = serial_no - s.fiscal_year = obj.doc.fiscal_year - s.company = obj.doc.company + s.purchase_document_type= obj.doc.doctype + s.purchase_document_no = obj.doc.name + s.purchase_date = obj.doc.posting_date + s.purchase_time = obj.doc.posting_time + s.purchase_rate = d.purchase_rate or d.incoming_rate + s.item_code = d.item_code + s.brand = d.brand + s.description = d.description + s.item_group = item_details and item_details[0]['item_group'] or '' + s.warranty_period = item_details and item_details[0]['warranty_period'] or 0 + s.supplier = obj.doc.supplier + s.supplier_name = obj.doc.supplier_name + s.supplier_address = obj.doc.supplier_address + s.warehouse = d.warehouse or d.t_warehouse + s.docstatus = 0 + s.status = 'In Store' + s.modified = nowdate() + s.modified_by = session['user'] + s.serial_no = serial_no + s.fiscal_year = obj.doc.fiscal_year + s.company = obj.doc.company s.save(new_rec) # ---------------------------------- # update serial no purchase details # ---------------------------------- - def update_serial_purchase_details(self, obj, d, serial_no, is_submit, is_transfer = 0): + def update_serial_purchase_details(self, obj, d, serial_no, is_submit, purpose = ''): exists = sql("select name, status, docstatus from `tabSerial No` where name = '%s'" % (serial_no)) if is_submit: - if exists and exists[0][2] != 2 and not is_transfer: + if exists and exists[0][2] != 2 and purpose not in ['Material Transfer', 'Sales Return']: msgprint("Serial No: %s already %s" % (serial_no, exists and exists[0][1]), raise_exception = 1) elif exists: s = Document('Serial No', exists and exists[0][0]) @@ -131,8 +133,10 @@ class DocType: else: if exists and exists[0][1] == 'Delivered' and exists[0][2] != 2: msgprint("Serial No: %s is already delivered, you can not cancel the document." % serial_no, raise_exception=1) + elif purpose in ['Material Transfer', 'Sales Return']: + sql("update `tabSerial No` set status = '%s', purchase_document_type = '', purchase_document_no = '', warehouse = '%s' where name = '%s'" % (purpose == 'Material Transfer' and 'In Store' or 'Delivered', d.s_warehouse, serial_no)) else: - sql("update `tabSerial No` set docstatus = '%s', status = '%s', purchase_document_type = '', purchase_document_no = '', purchase_date = '', purchase_rate = '', supplier = null, supplier_name = '', supplier_address = '', warehouse = null where name = '%s'" % (not is_transfer and 2 or 0, is_transfer and 'In Store' or 'Not in Use', serial_no)) + sql("update `tabSerial No` set docstatus = 2, status = 'Not in Use', purchase_document_type = '', purchase_document_no = '', purchase_date = '', purchase_rate = '', supplier = null, supplier_name = '', supplier_address = '', warehouse = '' where name = '%s'" % serial_no) # ------------------------------- @@ -227,15 +231,16 @@ class DocType: sle = Document(doctype = 'Stock Ledger Entry') for k in args.keys(): # adds warehouse_type - if k == 'warehouse': + if k == 'warehouse': sle.fields['warehouse_type'] = get_value('Warehouse' , args[k], 'warehouse_type') sle.fields[k] = args[k] sle_obj = get_obj(doc=sle) + # validate sle_obj.validate() sle.save(new = 1) return sle.name - + def repost(self): """ Repost everything! diff --git a/stock/doctype/stock_uom_replace_utility/stock_uom_replace_utility.py b/stock/doctype/stock_uom_replace_utility/stock_uom_replace_utility.py index e603d1fc8f4..f8ac7372a52 100644 --- a/stock/doctype/stock_uom_replace_utility/stock_uom_replace_utility.py +++ b/stock/doctype/stock_uom_replace_utility/stock_uom_replace_utility.py @@ -22,7 +22,7 @@ class DocType: self.doc, self.doclist = d,dl def get_stock_uom(self, item_code): - return cstr({'current_stock_uom': cstr(get_value('Item', item_code, 'stock_uom'))}) + return {'current_stock_uom': cstr(get_value('Item', item_code, 'stock_uom'))} def validate_mandatory(self): if not cstr(self.doc.item_code): diff --git a/support/doctype/customer_issue/customer_issue.py b/support/doctype/customer_issue/customer_issue.py index db63cc206d5..12a8ebdc6d9 100644 --- a/support/doctype/customer_issue/customer_issue.py +++ b/support/doctype/customer_issue/customer_issue.py @@ -27,37 +27,6 @@ class DocType(TransactionBase): def autoname(self): #self.doc.name = make_autoname('CI/' + self.doc.fiscal_year + '/.######') self.doc.name = make_autoname(self.doc.naming_series + '.######') - - #def get_customer_details(self): - # details = sql("select address, territory, customer_group, customer_name from `tabCustomer` where name = '%s' and docstatus != 2" %(self.doc.customer), as_dict = 1) - # if details: - # ret = { - # 'customer_address' : details and details[0]['address'] or '', - # 'customer_name' : details and details[0]['customer_name'] or '', - # 'territory' : details and details[0]['territory'] or '', - # 'customer_group' : details and details[0]['customer_group'] or '' - # } - # # ********** get primary contact details (this is done separately coz. , in case there is no primary contact thn it would not be able to fetch customer details in case of join query) - # contact_det = sql("select contact_name, contact_no, email_id from `tabContact` where customer_name = '%s' and is_customer = 1 and is_primary_contact = 'Yes' and docstatus != 2" %(self.doc.customer), as_dict = 1) - # ret['contact_person'] = contact_det and contact_det[0]['contact_name'] or '' - # ret['contact_no'] = contact_det and contact_det[0]['contact_no'] or '' - # ret['email_id'] = contact_det and contact_det[0]['email_id'] or '' - # - # return cstr(ret) - # else: - # msgprint("Customer : %s does not exist in system." % (name)) - # raise Exception - - # Get customer's contact person details - # ============================================================== - #def get_contact_details(self): - # contact = sql("select contact_no, email_id from `tabContact` where contact_name = '%s' and customer_name = '%s' and docstatus != 2" %(self.doc.contact_person, self.doc.customer), as_dict = 1) - # ret = { - # 'contact_no' : contact and contact[0]['contact_no'] or '', - # 'email_id' : contact and contact[0]['email_id'] or '' - # } - # return str(ret) - #check if maintenance schedule already generated #============================================ @@ -66,7 +35,7 @@ class DocType(TransactionBase): nm = nm and nm[0][0] or '' if not nm: - return cstr('No') + return 'No' def on_submit(self): if session['user'] != 'Guest': diff --git a/support/doctype/maintenance_schedule/maintenance_schedule.py b/support/doctype/maintenance_schedule/maintenance_schedule.py index 0d6ef809fbb..d5c90b55fca 100644 --- a/support/doctype/maintenance_schedule/maintenance_schedule.py +++ b/support/doctype/maintenance_schedule/maintenance_schedule.py @@ -38,21 +38,8 @@ class DocType(TransactionBase): 'item_name': item and item[0]['item_name'] or '', 'description' : item and item[0]['description'] or '' } - return str(ret) - - #pull customer details - #------------------------- - #def get_customer_details(self): - # det = sql("select t1.customer_name,t1.address,t1.territory,t2.contact_name from `tabCustomer` t1, `tabContact` t2 where t1.name = %s and t1.name=t2.customer and t2.is_primary_contact = 'Yes'", self.doc.customer, as_dict=1) - # - # ret = { - # 'customer_name': det and det[0]['customer_name'] or '', - # 'address' : det and det[0]['address'] or '', - # 'territory': det and det[0]['territory'] or '', - # 'contact_person' : det and det[0]['contact_name'] or '' - # } - # return str(ret) - + return ret + # generate maintenance schedule #------------------------------------- def generate_schedule(self): @@ -132,7 +119,7 @@ class DocType(TransactionBase): count = period/365 ret = {'no_of_visits':count} - return str(ret) + return ret def validate_maintenance_detail(self): if not getlist(self.doclist, 'item_maintenance_detail'): diff --git a/support/doctype/maintenance_visit/maintenance_visit.py b/support/doctype/maintenance_visit/maintenance_visit.py index 203793c9295..e4efe1c53a5 100644 --- a/support/doctype/maintenance_visit/maintenance_visit.py +++ b/support/doctype/maintenance_visit/maintenance_visit.py @@ -31,20 +31,7 @@ class DocType(TransactionBase): 'item_name' : item and item[0]['item_name'] or '', 'description' : item and item[0]['description'] or '' } - return str(ret) - - #get customer details - #----------------------- - #def get_customer_details(self): - # det = sql("select t1.customer_name,t1.address,t1.territory,t2.contact_name from `tabCustomer` t1, `tabContact` t2 where t1.name = %s and t1.name=t2.customer and t2.is_primary_contact = 'Yes'", self.doc.customer, as_dict=1) - # - # ret = { - # 'customer_name' : det and det[0]['customer_name'] or '', - # 'address' : det and det[0]['address'] or '', - # 'territory': det and det[0]['territory'] or '', - # 'contact_person' : det and det[0]['contact_name'] or '' - # } - # return str(ret) + return ret # fetch details of resp Sales order or customer issue #----------------------------------------------------------- diff --git a/support/doctype/support_ticket/__init__.py b/support/doctype/support_ticket/__init__.py index 936233db7ca..23c405964f5 100644 --- a/support/doctype/support_ticket/__init__.py +++ b/support/doctype/support_ticket/__init__.py @@ -61,15 +61,15 @@ class SupportMailbox(POP3Mailbox): d.status = 'Open' try: d.save(1) + # update feed + update_feed(d) + + # send auto reply + self.send_auto_reply(d) + except: d.description = 'Unable to extract message' d.save(1) - - # update feed - update_feed(d) - - # send auto reply - self.send_auto_reply(d) def send_auto_reply(self, d): """ @@ -85,14 +85,14 @@ We will get back to you as soon as possible [This is an automatic response] - """ + signature) + """ + (signature or '')) from webnotes.utils.email_lib import sendmail sendmail(\ recipients = [d.raised_by], \ sender = self.email_settings.support_email, \ - subject = '['+d.name+'] ' + d.subject, \ + subject = '['+d.name+'] ' + str(d.subject or ''), \ msg = response) def auto_close_tickets(self): diff --git a/utilities/doctype/bulk_rename_tool/bulk_rename_tool.txt b/utilities/doctype/bulk_rename_tool/bulk_rename_tool.txt index 155d3da2caa..16058e7f703 100644 --- a/utilities/doctype/bulk_rename_tool/bulk_rename_tool.txt +++ b/utilities/doctype/bulk_rename_tool/bulk_rename_tool.txt @@ -3,9 +3,9 @@ # These values are common in all dictionaries { - 'creation': '2011-07-07 17:47:52', + 'creation': '2011-07-08 11:14:15', 'docstatus': 0, - 'modified': '2011-07-27 13:19:22', + 'modified': '2011-07-26 00:59:27', 'modified_by': 'Administrator', 'owner': 'Administrator' }, @@ -96,4 +96,4 @@ 'label': 'Rename', 'options': 'do_rename' } -] \ No newline at end of file +] diff --git a/utilities/doctype/file_browser_control/file_browser_control.py b/utilities/doctype/file_browser_control/file_browser_control.py index 8008ae9877e..d5ad0cccfac 100644 --- a/utilities/doctype/file_browser_control/file_browser_control.py +++ b/utilities/doctype/file_browser_control/file_browser_control.py @@ -69,7 +69,7 @@ class DocType: 'name' : f_obj.doc.name, 'label' : f_obj.doc.file_name } - return cstr(ret) + return ret # Update changes done to selected file group. def update_grp(self,arg): @@ -160,7 +160,7 @@ class DocType: 'file_name' : f.file_name } - return cstr(ret) + return ret else: return 'No file found.' else: @@ -195,4 +195,4 @@ class DocType: def get_privileges(self,arg): arg = eval(arg) privilege = convert_to_lists(sql("select ifnull(can_edit,''), ifnull(can_view,''),owner from `tab%s` where name='%s'" % (arg['dt'],arg['dn']))) - return privilege \ No newline at end of file + return privilege diff --git a/utilities/doctype/patch_util/patch_util.py b/utilities/doctype/patch_util/patch_util.py index f26d110aa67..828c8050970 100644 --- a/utilities/doctype/patch_util/patch_util.py +++ b/utilities/doctype/patch_util/patch_util.py @@ -85,7 +85,8 @@ class DocType: d.parent = doctype d.parenttype = 'DocType' d.parentfield = 'permissions' - + + d.permlevel = level d.role = role d.read = read d.write = write diff --git a/utilities/transaction_base.py b/utilities/transaction_base.py index 332e201986d..3678298f7b0 100644 --- a/utilities/transaction_base.py +++ b/utilities/transaction_base.py @@ -53,7 +53,7 @@ class TransactionBase: 'contact_email' : contact_email, 'contact_mobile' : contact_mobile } - return cstr(ret) + return ret # Get Address Text # ----------------------- @@ -125,7 +125,7 @@ class TransactionBase: 'shipping_address_name' : details and details[0]['name'] or '', 'shipping_address' : address_display } - return cstr(ret) + return ret # Get Lead Details # ----------------------- @@ -144,7 +144,7 @@ class TransactionBase: 'contact_mobile' : extract('mobile_no'), 'contact_email' : extract('email_id') } - return cstr(ret) + return ret # Get Supplier Default Primary Address - first load @@ -162,7 +162,7 @@ class TransactionBase: 'contact_mobile' : contact_mobile } ret.update(self.get_supplier_details(args['supplier'])) - return cstr(ret) + return ret # Get Supplier Address # ----------------------- @@ -178,7 +178,7 @@ class TransactionBase: 'contact_email' : contact_email, 'contact_mobile' : contact_mobile } - return cstr(ret) + return ret # Get Supplier Details # -----------------------