From 80ed6b25e84d15e7ad8d98fe997bd17479761a73 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 27 Sep 2011 11:53:23 +0530 Subject: [PATCH 01/10] deleted gl_control.js file --- .../accounts/doctype/gl_control/gl_control.js | 367 ------------------ 1 file changed, 367 deletions(-) delete mode 100644 erpnext/accounts/doctype/gl_control/gl_control.js diff --git a/erpnext/accounts/doctype/gl_control/gl_control.js b/erpnext/accounts/doctype/gl_control/gl_control.js deleted file mode 100644 index 8f8d786424..0000000000 --- a/erpnext/accounts/doctype/gl_control/gl_control.js +++ /dev/null @@ -1,367 +0,0 @@ -class DocType: - def __init__(self,d,dl): - self.doc, self.doclist = d, dl - self.entries = [] - - # Get Company List - # ---------------- - def get_companies(self,arg=''): - d = get_defaults() - ret = sql("select name, abbr from tabCompany where docstatus != 2") - pl = {} - for r in ret: - inc = get_value('Account','Income - '+r[1], 'balance') - exp = get_value('Account','Expenses - '+r[1], 'balance') - pl[r[0]] = flt(flt(inc) - flt(exp)) - return {'cl':[r[0] for r in ret], 'pl':pl} - - # Get current balance - # -------------------- - def get_bal(self,arg): - ac, fy = arg.split('~~~') - det = sql("select t1.balance, t2.debit_or_credit from `tabAccount Balance` t1, `tabAccount` t2 where t1.period = %s and t2.name=%s and t1.parent = t2.name", (fy, ac)) - bal = det and flt(det[0][0]) or 0 - dr_or_cr = det and flt(det[0][1]) or '' - return fmt_money(bal) + ' ' + dr_or_cr - - def get_period_balance(self,arg): - acc, f, t = arg.split('~~~') - c, fy = '', get_defaults()['fiscal_year'] - - det = sql("select debit_or_credit, lft, rgt, is_pl_account from tabAccount where name=%s", acc) - if f: c += (' and t1.posting_date >= "%s"' % f) - if t: c += (' and t1.posting_date <= "%s"' % t) - bal = sql("select sum(ifnull(t1.debit,0))-sum(ifnull(t1.credit,0)) from `tabGL Entry` t1 where t1.account='%s' and ifnull(is_opening, 'No') = 'No' %s" % (acc, c)) - bal = bal and flt(bal[0][0]) or 0 - - if det[0][0] != 'Debit': - bal = (-1) * bal - - # add opening for balance sheet accounts - if det[0][3] == 'No': - opening = flt(sql("select opening from `tabAccount Balance` where parent=%s and period=%s", (acc, fy))[0][0]) - bal = bal + opening - - return flt(bal) - - - def get_period_difference(self,arg, cost_center =''): - # used in General Ledger Page Report - # used for Budget where cost center passed as extra argument - acc, f, t = arg.split('~~~') - c, fy = '', get_defaults()['fiscal_year'] - - det = sql("select debit_or_credit, lft, rgt, is_pl_account from tabAccount where name=%s", acc) - if f: c += (' and t1.posting_date >= "%s"' % f) - if t: c += (' and t1.posting_date <= "%s"' % t) - if cost_center: c += (' and t1.cost_center = "%s"' % cost_center) - bal = sql("select sum(ifnull(t1.debit,0))-sum(ifnull(t1.credit,0)) from `tabGL Entry` t1 where t1.account='%s' %s" % (acc, c)) - bal = bal and flt(bal[0][0]) or 0 - - if det[0][0] != 'Debit': - bal = (-1) * bal - - return flt(bal) - - # Get Children (for tree) - # ----------------------- - def get_cl(self, arg): - fy = get_defaults()['fiscal_year'] - parent, parent_acc_name, company, type = arg.split(',') - - # get children account details - if type=='Account': - if parent=='Root': - cl = sql("select t1.name, t1.group_or_ledger, t1.debit_or_credit, t2.balance, t1.account_name from tabAccount t1, `tabAccount Balance` t2 where t1.parent_account is NULL or t1.parent_account='' and t1.docstatus != 2 and t1.company=%s and t1.name = t2.parent and t2.period = %s order by t1.name asc", (company, fy),as_dict=1) - else: - cl = sql("select t1.name, t1.group_or_ledger, t1.debit_or_credit, t2.balance, t1.account_name from tabAccount t1, `tabAccount Balance` t2 where t1.parent_account=%s and t1.docstatus != 2 and t1.company=%s and t1.name = t2.parent and t2.period = %s order by t1.name asc",(parent, company, fy) ,as_dict=1) - - # remove Decimals - for c in cl: c['balance'] = flt(c['balance']) - - # get children cost center details - elif type=='Cost Center': - if parent=='Root': - cl = sql("select name,group_or_ledger, cost_center_name from `tabCost Center` where parent_cost_center is NULL or parent_cost_center='' and docstatus != 2 and company_name=%s order by name asc",(company),as_dict=1) - else: - cl = sql("select name,group_or_ledger,cost_center_name from `tabCost Center` where parent_cost_center=%s and docstatus != 2 and company_name=%s order by name asc",(parent,company),as_dict=1) - - return {'parent':parent, 'parent_acc_name':parent_acc_name, 'cl':cl} - - # Add a new account - # ----------------- - def add_ac(self,arg): - arg = eval(arg) - ac = Document('Account') - for d in arg.keys(): - ac.fields[d] = arg[d] - ac.old_parent = '' - ac_obj = get_obj(doc=ac) - ac_obj.validate() - ac_obj.doc.save(1) - ac_obj.on_update() - - return ac_obj.doc.name - - # Add a new cost center - #---------------------- - def add_cc(self,arg): - arg = eval(arg) - cc = Document('Cost Center') - # map fields - for d in arg.keys(): - cc.fields[d] = arg[d] - # map company abbr - other_info = sql("select company_abbr from `tabCost Center` where name='%s'"%arg['parent_cost_center']) - cc.company_abbr = other_info and other_info[0][0] or arg['company_abbr'] - - cc_obj = get_obj(doc=cc) - cc_obj.validate() - cc_obj.doc.save(1) - cc_obj.on_update() - - return cc_obj.doc.name - - - - # Get field values from the voucher - #------------------------------------------ - def get_val(self, src, d, parent=None): - if not src: - return None - if src.startswith('parent:'): - return parent.fields[src.split(':')[1]] - elif src.startswith('value:'): - return eval(src.split(':')[1]) - elif src: - return d.fields.get(src) - - def check_if_in_list(self, le): - for e in self.entries: - if e.account == le.account and (cstr(e.against_voucher)==cstr(le.against_voucher)) and (cstr(e.against_voucher_type)==cstr(le.against_voucher_type)) and (cstr(e.cost_center)==cstr(le.cost_center)): - return [e] - return 0 - - # Make a dictionary(le) for every gl entry and append to a list(self.entries) - #---------------------------------------------------------------------------- - def make_single_entry(self,parent,d,le_map,cancel): - if self.get_val(le_map['account'], d, parent) and (self.get_val(le_map['debit'], d, parent) or self.get_val(le_map['credit'], d, parent)): - flist = ['account','cost_center','against','debit','credit','remarks','voucher_type','voucher_no','transaction_date','posting_date','fiscal_year','against_voucher','against_voucher_type','company','is_opening', 'aging_date'] - - # Check budget before gl entry - #check budget only if account is expense account - is_expense_acct = sql("select name from tabAccount where is_pl_account='Yes' and debit_or_credit='Debit' and name=%s",self.get_val(le_map['account'], d, parent)) - if is_expense_acct and self.get_val(le_map['cost_center'], d, parent): - get_obj('Budget Control').check_budget([self.get_val(le_map[k], d, parent) for k in flist if k in ['account','cost_center','debit','credit','posting_date','fiscal_year','company']],cancel) - - # Create new GL entry object and map values - le = Document('GL Entry') - for k in flist: - le.fields[k] = self.get_val(le_map[k], d, parent) - - # if there is already an entry in this account then just add it to that entry - same_head = self.check_if_in_list(le) - if same_head: - same_head = same_head[0] - same_head.debit = flt(same_head.debit) + flt(le.debit) - same_head.credit = flt(same_head.credit) + flt(le.credit) - else: - self.entries.append(le) - - # Save GL Entries - # ---------------- - def save_entries(self, cancel, adv_adj): - for le in self.entries: - # cancel - if cancel: - tmp=le.debit - le.debit, le.credit = le.credit, tmp - - le_obj = get_obj(doc=le) - # validate except on_cancel - if not cancel: - le_obj.validate() - - # save - le.save(1) - le_obj.on_update(adv_adj) - - # update total debit / credit - self.td += flt(le.debit) - self.tc += flt(le.credit) - - # Make Multiple Entries - # --------------------- - def make_gl_entries(self, doc, doclist, cancel=0, adv_adj = 0): - # get entries - le_map_list = sql("select * from `tabGL Mapper Detail` where parent = %s", doc.doctype, as_dict=1) - - self.td, self.tc = 0.0, 0.0 - - for le_map in le_map_list: - if le_map['table_field']: - for d in getlist(doclist,le_map['table_field']): - # purchase_tax_details is the table of other charges in purchase cycle - if le_map['table_field'] != 'purchase_tax_details' or (le_map['table_field'] == 'purchase_tax_details' and d.fields.get('category') != 'For Valuation'): - self.make_single_entry(doc,d,le_map,cancel) - else: - self.make_single_entry(None,doc,le_map,cancel) - - # save entries - self.save_entries(cancel,adv_adj) - - # check total debit / credit - # Due to old wrong entries (total debit != total credit) some voucher could be cancelled - if abs(self.td - self.tc) > 0.001 and not cancel: - msgprint("Debit and Credit not equal for this voucher: Diff (Debit) is %s" % (self.td-self.tc)) - raise Exception - - # set as cancelled - if cancel: - vt, vn = self.get_val(le_map['voucher_type'], doc, doc), self.get_val(le_map['voucher_no'], doc, doc) - sql("update `tabGL Entry` set is_cancelled='Yes' where voucher_type=%s and voucher_no=%s", (vt, vn)) - - # Get account balance on any date - # ------------------------------- - - def get_as_on_balance(self, account_name, fiscal_year, as_on, credit_or_debit, is_pl, lft, rgt, ysd): - # get total transaction value for the current year - bal = bal = sql("select SUM(t1.debit), SUM(t1.credit) from `tabGL Entry` t1, `tabAccount` t2 WHERE t1.posting_date >= %s AND t1.posting_date <= %s and t1.is_opening = 'No' AND t1.account = t2.name AND t2.lft >= %s AND t2.rgt <= %s and t1.is_cancelled = 'No'", (ysd,as_on,lft, rgt)) - bal = bal and (flt(bal[0][0]) - flt(bal[0][1])) or 0 - - if credit_or_debit == 'Credit' and bal: - bal = -bal - - # Add opening balance with the transaction value - if is_pl=='No': - op = sql("select opening from `tabAccount Balance` where parent=%s and period=%s", (account_name, fiscal_year)) - op = op and op[0][0] or 0 - bal += flt(op) - return flt(bal) - - # ADVANCE ALLOCATION - #------------------- - def get_advances(self, obj, account_head, table_name,table_field_name, dr_or_cr): - jv_detail = sql("select t1.name, t1.remark, t2.%s, t2.name, t1.ded_amount from `tabJournal Voucher` t1, `tabJournal Voucher Detail` t2 where t1.name = t2.parent and (t2.against_voucher is null or t2.against_voucher = '') and (t2.against_invoice is null or t2.against_invoice = '') and t2.account = '%s' and t2.is_advance = 'Yes' and t1.docstatus = 1 order by t1.voucher_date " % (dr_or_cr,account_head)) - # clear advance table - obj.doc.clear_table(obj.doclist,table_field_name) - # Create advance table - for d in jv_detail: - add = addchild(obj.doc, table_field_name, table_name, 1, obj.doclist) - add.journal_voucher = d[0] - add.jv_detail_no = d[3] - add.remarks = d[1] - add.advance_amount = flt(d[2]) - add.allocate_amount = 0 - if table_name == 'Advance Allocation Detail': - add.tds_amount = flt(d[4]) - - # Clear rows which is not adjusted - #------------------------------------- - def clear_advances(self, obj,table_name,table_field_name): - for d in getlist(obj.doclist,table_field_name): - if not flt(d.allocated_amount): - sql("update `tab%s` set parent = '' where name = '%s' and parent = '%s'" % (table_name, d.name, d.parent)) - d.parent = '' - - # Update aginst document in journal voucher - #------------------------------------------ - def update_against_document_in_jv(self, obj, table_field_name, against_document_no, against_document_doctype, account_head, dr_or_cr,doctype): - for d in getlist(obj.doclist, table_field_name): - self.validate_jv_entry(d, account_head, dr_or_cr) - if flt(d.advance_amount) == flt(d.allocated_amount): - # cancel JV - jv_obj = get_obj('Journal Voucher', d.journal_voucher, with_children=1) - get_obj(dt='GL Control').make_gl_entries(jv_obj.doc, jv_obj.doclist, cancel =1, adv_adj =1) - - # update ref in JV Detail - sql("update `tabJournal Voucher Detail` set %s = '%s' where name = '%s'" % (doctype=='Payable Voucher' and 'against_voucher' or 'against_invoice', cstr(against_document_no), d.jv_detail_no)) - - # re-submit JV - jv_obj = get_obj('Journal Voucher', d.journal_voucher, with_children =1) - get_obj(dt='GL Control').make_gl_entries(jv_obj.doc, jv_obj.doclist, cancel = 0, adv_adj =1) - - elif flt(d.advance_amount) > flt(d.allocated_amount): - # cancel JV - jv_obj = get_obj('Journal Voucher', d.journal_voucher, with_children=1) - get_obj(dt='GL Control').make_gl_entries(jv_obj.doc, jv_obj.doclist, cancel =1, adv_adj = 1) - - # add extra entries - self.add_extra_entry(jv_obj, d.journal_voucher, d.jv_detail_no, flt(d.allocated_amount), account_head, doctype, dr_or_cr, against_document_no) - - # re-submit JV - jv_obj = get_obj('Journal Voucher', d.journal_voucher, with_children =1) - get_obj(dt='GL Control').make_gl_entries(jv_obj.doc, jv_obj.doclist, cancel = 0, adv_adj = 1) - else: - msgprint("Allocation amount cannot be greater than advance amount") - raise Exception - - # Add extra row in jv detail for unadjusted amount - #-------------------------------------------------- - def add_extra_entry(self,jv_obj,jv,jv_detail_no, allocate, account_head, doctype, dr_or_cr, against_document_no): - # get old entry details - - jvd = sql("select %s, cost_center, balance, against_account from `tabJournal Voucher Detail` where name = '%s'" % (dr_or_cr,jv_detail_no)) - advance = jvd and flt(jvd[0][0]) or 0 - balance = flt(advance) - flt(allocate) - - # update old entry - sql("update `tabJournal Voucher Detail` set %s = '%s', %s = '%s' where name = '%s'" % (dr_or_cr, flt(allocate), doctype == "Payable Voucher" and 'against_voucher' or 'against_invoice',cstr(against_document_no), jv_detail_no)) - - # new entry with balance amount - add = addchild(jv_obj.doc, 'entries', 'Journal Voucher Detail', 1, jv_obj.doclist) - add.account = account_head - add.cost_center = cstr(jvd[0][1]) - add.balance = cstr(jvd[0][2]) - add.fields[dr_or_cr] = balance - add.against_account = cstr(jvd[0][3]) - add.is_advance = 'Yes' - add.save(1) - - # check if advance entries are still valid - # ---------------------------------------- - def validate_jv_entry(self, d, account_head, dr_or_cr): - # 1. check if there is already a voucher reference - # 2. check if amount is same - # 3. check if is_advance is 'Yes' - # 4. check if jv is submitted - ret = sql("select t2.%s from `tabJournal Voucher` t1, `tabJournal Voucher Detail` t2 where t1.name = t2.parent and (t2.against_voucher = '' || t2.against_voucher is null) and (t2.against_invoice = '' || t2.against_invoice is null) and t2.account = '%s' and t1.name = '%s' and t2.name = '%s' and t2.is_advance = 'Yes' and t1.docstatus=1 and t2.%s = %s" % ( dr_or_cr, account_head, d.journal_voucher, d.jv_detail_no, dr_or_cr, d.advance_amount)) - if (not ret): - msgprint("Please click on 'Get Advances Paid' button as the advance entries have been changed.") - raise Exception - return - -############################################################################## -# Repair Outstanding Amount -############################################################################## - def repair_voucher_outstanding(self, voucher_obj): - msg = [] - - # Get Balance from GL Entries - bal = sql("select sum(debit)-sum(credit) from `tabGL Entry` where against_voucher=%s and against_voucher_type=%s", (voucher_obj.doc.name , voucher_obj.doc.doctype)) - bal = bal and flt(bal[0][0]) or 0.0 - if cstr(voucher_obj.doc.doctype) == 'Payable Voucher': - bal = -bal - - # Check outstanding Amount - if flt(voucher_obj.doc.outstanding_amount) != flt(bal): - msgprint('
Difference found in Outstanding Amount of %s : %s (Before : %s; After : %s)
' % (voucher_obj.doc.doctype, voucher_obj.doc.name, voucher_obj.doc.outstanding_amount, bal)) - msg.append('
Difference found in Outstanding Amount of %s : %s (Before : %s; After : %s)
' % (voucher_obj.doc.doctype, voucher_obj.doc.name, voucher_obj.doc.outstanding_amount, bal)) - - # set voucher balance - #sql("update `tab%s` set outstanding_amount=%s where name='%s'" % (voucher_obj.doc.doctype, bal, voucher_obj.doc.name)) - set(voucher_obj.doc, 'outstanding_amount', flt(bal)) - - # Send Mail - if msg: - email_msg = """ Dear Administrator, - -In Account := %s User := %s has Repaired Outstanding Amount For %s : %s and following was found:- - -%s - -""" % (get_value('Control Panel', None,'account_id'), session['user'], voucher_obj.doc.doctype, voucher_obj.doc.name, '\n'.join(msg)) - - sendmail(['jai@webnotestech.com'], subject='Repair Outstanding Amount', parts = [('text/plain', email_msg)]) - # Acknowledge User - msgprint(cstr(voucher_obj.doc.doctype) + " : " + cstr(voucher_obj.doc.name) + " has been checked" + cstr(msg and " and repaired successfully." or ". No changes Found.")) From e76e2a1172a619fb50d0927d74df5f6718aaaade Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 27 Sep 2011 12:45:48 +0530 Subject: [PATCH 02/10] reload internal reconciliation --- erpnext/patches/patch.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/erpnext/patches/patch.py b/erpnext/patches/patch.py index 79d40c98b0..2f826d54e7 100644 --- a/erpnext/patches/patch.py +++ b/erpnext/patches/patch.py @@ -1,7 +1,7 @@ # REMEMBER to update this # ======================== -last_patch = 372 +last_patch = 374 #------------------------------------------- @@ -382,3 +382,7 @@ def execute(patch_no): sql("delete from `tabDocField` where label = 'View Ledger Entry' and parent = 'Journal Voucher' and fieldtype = 'Button' limit 1") if sql("select count(name) from `tabDocField` where label = 'Get Balance' and parent = 'Journal Voucher' and fieldtype = 'Button'")[0][0] > 1: sql("delete from `tabDocField` where label = 'Get Balance' and parent = 'Journal Voucher' and fieldtype = 'Button' limit 1") + elif patch_no == 374: + reload_doc('accounts', 'doctype', 'internal_reconciliation') + reload_doc('accounts', 'doctype', 'ir_payment_detail') + reload_doc('accounts', 'Module Def', 'Accounts') From e2df68bb5b4c1331f362028330ba9fc8745fd11a Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 27 Sep 2011 12:47:09 +0530 Subject: [PATCH 03/10] reload internal reconciliation --- erpnext/accounts/Module Def/Accounts/Accounts.txt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/Module Def/Accounts/Accounts.txt b/erpnext/accounts/Module Def/Accounts/Accounts.txt index 50a7ac9697..0a6921a13c 100644 --- a/erpnext/accounts/Module Def/Accounts/Accounts.txt +++ b/erpnext/accounts/Module Def/Accounts/Accounts.txt @@ -5,7 +5,7 @@ { 'creation': '2010-09-25 10:50:37', 'docstatus': 0, - 'modified': '2011-09-12 13:22:15', + 'modified': '2011-09-27 12:44:04', 'modified_by': 'Administrator', 'owner': 'Administrator' }, @@ -128,6 +128,15 @@ 'doctype': 'Module Def Item' }, + # Module Def Item + { + 'description': 'Link your invoices and payment vouchers to clear/update outstanding amount', + 'display_name': 'Internal Reconciliation', + 'doc_name': 'Internal Reconciliation', + 'doc_type': 'Single DocType', + 'doctype': 'Module Def Item' + }, + # Module Def Item { 'display_name': 'TDS Payment', From ec451da2f43bf1259be19ec150c71925667b87ec Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 27 Sep 2011 12:47:59 +0530 Subject: [PATCH 04/10] Re-written update_against_document_in_jv function in RV and PV --- .../payable_voucher/payable_voucher.py | 38 +++++++++-- .../receivable_voucher/receivable_voucher.py | 67 ++++++++++--------- 2 files changed, 70 insertions(+), 35 deletions(-) diff --git a/erpnext/accounts/doctype/payable_voucher/payable_voucher.py b/erpnext/accounts/doctype/payable_voucher/payable_voucher.py index b403d20c02..39544b0d2a 100644 --- a/erpnext/accounts/doctype/payable_voucher/payable_voucher.py +++ b/erpnext/accounts/doctype/payable_voucher/payable_voucher.py @@ -447,12 +447,38 @@ class DocType(TransactionBase): if not submitted: msgprint("Purchase Receipt : "+ cstr(d.purchase_receipt) +" is not submitted") raise Exception , "Validation Error." - - def update_against_document_in_jv(self, against_document_no, against_document_doctype): - get_obj('GL Control').update_against_document_in_jv( self,'advance_allocation_details', against_document_no, against_document_doctype, self.doc.credit_to, 'debit',self.doc.doctype) + + + #-------------------------------------------------------------------- + def update_against_document_in_jv(self): + """ + Links invoice and advance voucher: + 1. cancel advance voucher + 2. split into multiple rows if partially adjusted, assign against voucher + 3. submit advance voucher + """ + + lst = [] + for d in getlist(self.doclist, 'advance_allocation_details'): + if flt(d.allocated_amount) > 0: + args = { + 'voucher_no' : d.journal_voucher, + 'voucher_detail_no' : d.jv_detail_no, + 'against_voucher_type' : 'Payable Voucher', + 'against_voucher' : self.doc.name, + 'account' : self.doc.credit_to, + 'is_advance' : 'Yes', + 'dr_or_cr' : 'debit', + 'unadjusted_amt' : flt(d.advance_amount), + 'allocated_amt' : flt(d.allocated_amount) + } + lst.append(args) + + if lst: + get_obj('GL Control').reconcile_against_document(lst) # On Submit - # ---------- + #-------------------------------------------------------------------- def on_submit(self): self.check_prev_docstatus() @@ -462,7 +488,9 @@ class DocType(TransactionBase): # this sequence because outstanding may get -negative get_obj(dt='GL Control').make_gl_entries(self.doc, self.doclist) - self.update_against_document_in_jv(self.doc.name, self.doc.doctype) + + self.update_against_document_in_jv() + get_obj(dt = 'Purchase Common').update_prevdoc_detail(self, is_submit = 1) diff --git a/erpnext/accounts/doctype/receivable_voucher/receivable_voucher.py b/erpnext/accounts/doctype/receivable_voucher/receivable_voucher.py index dba08fe8b9..6d1f80adb9 100644 --- a/erpnext/accounts/doctype/receivable_voucher/receivable_voucher.py +++ b/erpnext/accounts/doctype/receivable_voucher/receivable_voucher.py @@ -225,40 +225,47 @@ class DocType(TransactionBase): #----------------------------------------------------------------- - # ADVANCE ALLOCATION - #----------------------------------------------------------------- - def update_against_document_in_jv(self,against_document_no, against_document_doctype): - get_obj('GL Control').update_against_document_in_jv( self, 'advance_adjustment_details', against_document_no, against_document_doctype, self.doc.debit_to, 'credit', self.doc.doctype) + def update_against_document_in_jv(self): + """ + Links invoice and advance voucher: + 1. cancel advance voucher + 2. split into multiple rows if partially adjusted, assign against voucher + 3. submit advance voucher + """ + + lst = [] + for d in getlist(self.doclist, 'advance_adjustment_details'): + if flt(d.allocated_amount) > 0: + args = { + 'voucher_no' : d.journal_voucher, + 'voucher_detail_no' : d.jv_detail_no, + 'against_voucher_type' : 'Receivable Voucher', + 'against_voucher' : self.doc.name, + 'account' : self.doc.debit_to, + 'is_advance' : 'Yes', + 'dr_or_cr' : 'credit', + 'unadjusted_amt' : flt(d.advance_amount), + 'allocated_amt' : flt(d.allocated_amount) + } + lst.append(args) + + if lst: + get_obj('GL Control').reconcile_against_document(lst) - - -# ************************************* VALIDATE ********************************************** - # Get Customer Name and address based on Debit To Account selected - # This case arises in case of direct RV where user doesn't enter customer name. - # Hence it should be fetched from Account Head. - # ----------------------------------------------------------------------------- - #def get_customer_details(self): - # get_obj('Sales Common').get_customer_details(self, inv_det_reqd = 1) - # self.get_cust_and_due_date() - - # Validate Customer Name with SO or DN if items are fetched from SO or DN # ------------------------------------------------------------------------ def validate_customer(self): + """ + Validate customer name with SO and DN + """ for d in getlist(self.doclist,'entries'): - customer = '' - if d.sales_order: - customer = sql("select customer from `tabSales Order` where name = '%s'" % d.sales_order)[0][0] - doctype = 'sales order' - doctype_no = cstr(d.sales_order) - if d.delivery_note: - customer = sql("select customer from `tabDelivery Note` where name = '%s'" % d.delivery_note)[0][0] - doctype = 'delivery note' - doctype_no = cstr(d.delivery_note) - if customer and not cstr(self.doc.customer) == cstr(customer): - msgprint("Customer %s do not match with customer of %s %s." %(self.doc.customer,doctype,doctype_no)) - raise Exception , " Validation Error " - + dt = d.delivery_note and 'Delivery Note' or d.sales_order and 'Sales Order' or '' + if dt: + dt_no = d.delivery_note or d.sales_order + cust = sql("select customer from `tab%s` where name = %s" % (dt, '%s'), dt_no) + if cust and cstr(cust[0][0]) != cstr(self.doc.customer): + msgprint("Customer %s does not match with customer of %s: %s." %(self.doc.customer, dt, dt_no), raise_exception=1) + # Validates Debit To Account and Customer Matches # ------------------------------------------------ @@ -545,7 +552,7 @@ class DocType(TransactionBase): self.make_gl_entries() if not cint(self.doc.is_pos) == 1: - self.update_against_document_in_jv(self.doc.name, self.doc.doctype) + self.update_against_document_in_jv() # on submit notification # get_obj('Notification Control').notify_contact('Sales Invoice', self.doc.doctype,self.doc.name, self.doc.email_id, self.doc.contact_person) From d9a16a282c9e6d4da71d9da41fc65bb627e16433 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 27 Sep 2011 15:10:07 +0530 Subject: [PATCH 05/10] deleted gl_entry.js file --- erpnext/accounts/doctype/gl_entry/gl_entry.js | 202 ------------------ 1 file changed, 202 deletions(-) delete mode 100644 erpnext/accounts/doctype/gl_entry/gl_entry.js diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.js b/erpnext/accounts/doctype/gl_entry/gl_entry.js deleted file mode 100644 index 9f34ad8795..0000000000 --- a/erpnext/accounts/doctype/gl_entry/gl_entry.js +++ /dev/null @@ -1,202 +0,0 @@ -class DocType: - def __init__(self,d,dl): - self.doc, self.doclist = d, dl - - # Validate mandatory - #------------------- - def check_mandatory(self): - # Following fields are mandatory in GL Entry - mandatory = ['account','remarks','voucher_type','voucher_no','fiscal_year','company'] - for k in mandatory: - if not self.doc.fields.get(k): - msgprint("%s is mandatory for GL Entry" % k) - raise Exception - - # Zero value transaction is not allowed - if not (flt(self.doc.debit) or flt(self.doc.credit)): - msgprint("GL Entry: Debit or Credit amount is mandatory for %s" % self.doc.account) - raise Exception - - # Debit and credit can not done at the same time - if flt(self.doc.credit) != 0 and flt(self.doc.debit) != 0: - msgprint("Sorry you cannot credit and debit under same account head.") - raise Exception, "Validation Error." - - # Cost center is required only if transaction made against pl account - #-------------------------------------------------------------------- - def pl_must_have_cost_center(self): - if sql("select name from tabAccount where name=%s and is_pl_account='Yes'", self.doc.account): - if not self.doc.cost_center and not self.doc.voucher_type != 'Period Closing Entry': - msgprint("Error: Cost Center must be specified for PL Account: %s" % self.doc.account_name) - raise Exception - else: # not pl - if self.doc.cost_center: - self.doc.cost_center = '' - - # Account must be ledger, active and not freezed - #----------------------------------------------- - def validate_account_details(self, adv_adj): - ret = sql("select group_or_ledger, docstatus, freeze_account, company from tabAccount where name=%s", self.doc.account) - - # 1. Checks whether Account type is group or ledger - if ret and ret[0][0]=='Group': - msgprint("Error: All accounts must be Ledgers. Account %s is a group" % self.doc.account) - raise Exception - - # 2. Checks whether Account is active - if ret and ret[0][1]==2: - msgprint("Error: All accounts must be Active. Account %s moved to Trash" % self.doc.account) - raise Exception - - # 3. Account has been freezed for other users except account manager - if ret and ret[0][2]== 'Yes' and not adv_adj and not 'Accounts Manager' in session['data']['roles']: - msgprint("Error: Account %s has been freezed. Only Accounts Manager can do transaction against this account." % self.doc.account) - raise Exception - - # 4. Check whether account is within the company - if ret and ret[0][3] != self.doc.company: - msgprint("Account: %s does not belong to the company: %s" % (self.doc.account, self.doc.company)) - raise Exception - - # Posting date must be in selected fiscal year and fiscal year is active - #------------------------------------------------------------------------- - def validate_posting_date(self): - fy = sql("select docstatus, year_start_date from `tabFiscal Year` where name=%s ", self.doc.fiscal_year) - ysd = fy[0][1] - yed = get_last_day(get_first_day(ysd,0,11)) - pd = getdate(self.doc.posting_date) - if fy[0][0] == 2: - msgprint("Fiscal Year is not active. You can restore it from Trash") - raise Exception - if pd < ysd or pd > yed: - msgprint("Posting date must be in the Selected Financial Year") - raise Exception - - - # Nobody can do GL Entries where posting date is before freezing date except 'Accounts Manager' - #---------------------------------------------------------------------------------------------- - def check_freezing_date(self, adv_adj): - if not adv_adj: - pd,fd = getdate(self.doc.posting_date),0 - acc_frozen_upto = get_obj(dt = 'Manage Account').doc.acc_frozen_upto or '' - if acc_frozen_upto: - fd = getdate(acc_frozen_upto) - - bde_auth_role = get_value( 'Manage Account', None,'bde_auth_role') - if fd and pd <= fd and (bde_auth_role and not bde_auth_role in session['data']['roles']): - msgprint("Message:You are not authorized to do back dated entries for account: %s before %s." % (self.doc.account, str(fd))) - raise Exception - - # create new bal if not exists - #----------------------------- - def create_new_balances(self, ac_obj, p, amt): - ac = addchild(ac_obj.doc, 'account_balances', 'Account Balance', 1) - ac.period = p[0] - ac.start_date = p[1].strftime('%Y-%m-%d') - ac.end_date = p[2].strftime('%Y-%m-%d') - ac.fiscal_year = p[3] - ac.opening = 0 - ac.balance = amt - ac.save() - - # Post Balance - # ------------ - def post_balance(self, acc): - # get details - lft = sql("select lft, rgt, debit_or_credit from `tabAccount` where name='%s'" % acc) - - # amount to debit - amt = flt(self.doc.debit) - flt(self.doc.credit) - if lft[0][2] == 'Credit': amt = -amt - - # get periods - periods = self.get_period_list(self.doc.posting_date, self.doc.fiscal_year) - - acc_obj = get_obj('Account', self.doc.account) - for p in periods: - if not sql("select name from `tabAccount Balance` where parent=%s and period=%s", (self.doc.account, p[0])): - self.create_new_balances(acc_obj, p, amt) - else: - # update current - pl = sql("update `tabAccount Balance` t1, `tabAccount` t2 set t1.balance = t1.balance + %s where t2.lft<=%s and t2.rgt>=%s and t1.parent = t2.name and t1.period = '%s'" % (amt, cint(lft[0][0]), cint(lft[0][1]), p[0])) - - # update opening - if self.doc.is_opening=='Yes': - pl = sql("update `tabAccount Balance` t1, `tabAccount` t2 set t1.opening = ifnull(t1.opening,0) + %s where t2.lft<=%s and t2.rgt>=%s and t1.parent = t2.name and t1.period = '%s'" % (amt, cint(lft[0][0]), cint(lft[0][1]), self.doc.fiscal_year)) - - # Get periods(month and year) - #----------------------------- - def get_period_list(self, dt, fy): - pl = sql("SELECT name, start_date, end_date, fiscal_year FROM tabPeriod WHERE end_date >='%s' and fiscal_year = '%s' and period_type in ('Month', 'Year')" % (dt,fy)) - return pl - - # Voucher Balance - # --------------- - def update_outstanding_amt(self): - # get final outstanding amt - bal = flt(sql("select sum(debit)-sum(credit) from `tabGL Entry` where against_voucher=%s and against_voucher_type=%s and ifnull(is_cancelled,'No') = 'No'", (self.doc.against_voucher, self.doc.against_voucher_type))[0][0] or 0.0) - tds = 0 - - if self.doc.against_voucher_type=='Payable Voucher': - # amount to debit - bal = -bal - - # Check if tds applicable - tds = sql("select total_tds_on_voucher from `tabPayable Voucher` where name = '%s'" % self.doc.against_voucher) - tds = tds and flt(tds[0][0]) or 0 - - # Validation : Outstanding can not be negative - if bal < 0 and not tds and self.doc.is_cancelled == 'No': - msgprint("Outstanding for Voucher %s will become %s. Outstanding cannot be less than zero. Please match exact outstanding." % (self.doc.against_voucher, fmt_money(bal))) - raise Exception - - # Update outstanding amt on against voucher - sql("update `tab%s` set outstanding_amount=%s where name='%s'"% (self.doc.against_voucher_type,bal,self.doc.against_voucher)) - - - # Total outstanding can not be greater than credit limit for any time for any customer - #--------------------------------------------------------------------------------------------- - def check_credit_limit(self): - #check for user role Freezed - master_type=sql("select master_type from `tabAccount` where name='%s' " %self.doc.account) - tot_outstanding = 0 #needed when there is no GL Entry in the system for that acc head - if (self.doc.voucher_type=='Journal Voucher' or self.doc.voucher_type=='Receivable Voucher') and (master_type and master_type[0][0]=='Customer'): - dbcr=sql("select sum(debit),sum(credit) from `tabGL Entry` where account = '%s' and is_cancelled='No'" % self.doc.account) - if dbcr: - tot_outstanding = flt(dbcr[0][0])-flt(dbcr[0][1])+flt(self.doc.debit)-flt(self.doc.credit) - get_obj('Account',self.doc.account).check_credit_limit(self.doc.account, self.doc.company, tot_outstanding) - - #for opening entry account can not be pl account - #----------------------------------------------- - def check_pl_account(self): - if self.doc.is_opening=='Yes': - is_pl_account=sql("select is_pl_account from `tabAccount` where name='%s'"%(self.doc.account)) - if is_pl_account and is_pl_account[0][0]=='Yes': - msgprint("For opening balance entry account can not be a PL account") - raise Exception - - # Validate - # -------- - def validate(self): # not called on cancel - self.check_mandatory() - self.pl_must_have_cost_center() - self.validate_posting_date() - self.doc.is_cancelled = 'No' # will be reset by GL Control if cancelled - self.check_credit_limit() - self.check_pl_account() - - # On Update - #---------- - def on_update(self,adv_adj): - # Account must be ledger, active and not freezed - self.validate_account_details(adv_adj) - - # Posting date must be after freezing date - self.check_freezing_date(adv_adj) - - # Update current account balance - self.post_balance(self.doc.account) - - # Update outstanding amt on against voucher - if self.doc.against_voucher: - self.update_outstanding_amt() \ No newline at end of file From c8d5625763ce99006bf0e15e13c76395cff18d48 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 27 Sep 2011 15:26:29 +0530 Subject: [PATCH 06/10] removed trashed profile from user search result --- .../doctype/pos_setting/pos_setting.js | 121 ++++++++++++++---- 1 file changed, 96 insertions(+), 25 deletions(-) diff --git a/erpnext/accounts/doctype/pos_setting/pos_setting.js b/erpnext/accounts/doctype/pos_setting/pos_setting.js index 2bbc08cf58..4eed7b6918 100755 --- a/erpnext/accounts/doctype/pos_setting/pos_setting.js +++ b/erpnext/accounts/doctype/pos_setting/pos_setting.js @@ -1,38 +1,109 @@ -cur_frm.cscript.onload = function(doc,cdt,cdn){ - $c_obj(make_doclist(cdt,cdn),'get_series','',function(r,rt){ - if(r.message) set_field_options('naming_series', r.message); - }); + +//--------- ONLOAD ------------- +cur_frm.cscript.onload = function(doc, cdt, cdn) { + +} + +// Settings Module + +cur_frm.cscript.refresh = function(doc,cdt,cdn){ + + + if(doc.based_on == 'Grand Total' || doc.based_on == 'Average Discount' || doc.based_on == 'Total Claimed Amount' || doc.based_on == 'Not Applicable') hide_field('master_name'); + else unhide_field('master_name'); + if(doc.based_on == 'Not Applicable') hide_field('value'); + else unhide_field('value'); + + if(doc.transaction == 'Expense Voucher' || doc.transaction == 'Appraisal'){ + hide_field(['master_name','system_role', 'system_user']); + unhide_field(['to_emp','to_designation']); + if(doc.transaction == 'Appraisal') hide_field('value'); + else unhide_field('value'); + } + else { + unhide_field(['master_name','system_role', 'system_user','value']); + hide_field(['to_emp','to_designation']); + } } -//cash bank account -//------------------------------------ -cur_frm.fields_dict['cash_bank_account'].get_query = function(doc,cdt,cdn) { - return 'SELECT tabAccount.name FROM tabAccount WHERE tabAccount.debit_or_credit="Debit" AND tabAccount.is_pl_account = "No" AND tabAccount.group_or_ledger="Ledger" AND tabAccount.docstatus!=2 AND tabAccount.company="'+doc.company+'" AND tabAccount.%(key)s LIKE "%s"' +cur_frm.cscript.based_on = function(doc){ + if(doc.based_on == 'Grand Total' || doc.based_on == 'Average Discount' || doc.based_on == 'Total Claimed Amount' || doc.based_on == 'Not Applicable'){ + doc.master_name = ''; + refresh_field('master_name'); + hide_field('master_name'); + } + else{ + unhide_field('master_name'); + } + + if(doc.based_on == 'Not Applicable') { + doc.value =0; + refresh_field('value'); + hide_field('value'); + } + else unhide_field('value'); } -// Income Account -// -------------------------------- -cur_frm.fields_dict['income_account'].get_query = function(doc,cdt,cdn) { - return 'SELECT tabAccount.name FROM tabAccount WHERE tabAccount.debit_or_credit="Credit" AND tabAccount.group_or_ledger="Ledger" AND tabAccount.docstatus!=2 AND tabAccount.company="'+doc.company+'" AND tabAccount.account_type ="Income Account" AND tabAccount.%(key)s LIKE "%s"' +cur_frm.cscript.transaction = function(doc,cdt,cdn){ + if(doc.transaction == 'Expense Voucher' || doc.transaction == 'Appraisal'){ + doc.master_name = doc.system_role = doc.system_user = ''; + refresh_many(['master_name','system_role', 'system_user']); + hide_field(['master_name','system_role', 'system_user']); + unhide_field(['to_emp','to_designation']); + if(doc.transaction == 'Appraisal') { + doc.value =0; + refresh_many('value'); + hide_field('value'); + } + else unhide_field('value'); + } + else { + unhide_field(['master_name','system_role', 'system_user','value']); + hide_field(['to_emp','to_designation']); + } + + if(doc.transaction == 'Expense Voucher') doc.based_on = 'Total Claimed Amount'; + if(doc.transaction == 'Appraisal') doc.based_on == 'Not Applicable'; } -// Cost Center -// ----------------------------- -cur_frm.fields_dict['cost_center'].get_query = function(doc,cdt,cdn) { - return 'SELECT `tabCost Center`.`name` FROM `tabCost Center` WHERE `tabCost Center`.`company_name` = "' +doc.company+'" AND `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'; -} - -//get query select Territory -//================================================================= -cur_frm.fields_dict['territory'].get_query = function(doc,cdt,cdn) { - return 'SELECT `tabTerritory`.`name`,`tabTerritory`.`parent_territory` FROM `tabTerritory` WHERE `tabTerritory`.`is_group` = "No" AND `tabTerritory`.`docstatus`!= 2 AND `tabTerritory`.%(key)s LIKE "%s" ORDER BY `tabTerritory`.`name` ASC LIMIT 50'; +// System User Trigger +// ------------------- +cur_frm.fields_dict['system_user'].get_query = function(doc) { + return 'SELECT tabProfile.name, tabProfile.first_name FROM tabProfile WHERE tabProfile.name not in ("Administrator","Guest") AND tabProfile.docstatus != 2 AND tabProfile.%(key)s LIKE "%s" LIMIT 50' } -// ------------------ Get Print Heading ------------------------------------ -cur_frm.fields_dict['select_print_heading'].get_query = function(doc, cdt, cdn) { - return 'SELECT `tabPrint Heading`.name FROM `tabPrint Heading` WHERE `tabPrint Heading`.docstatus !=2 AND `tabPrint Heading`.name LIKE "%s" ORDER BY `tabPrint Heading`.name ASC LIMIT 50'; +// System Role Trigger +// ----------------------- +cur_frm.fields_dict['system_role'].get_query = function(doc) { + return 'SELECT tabRole.name FROM tabRole WHERE tabRole.name not in ("Administrator","Guest","All") AND tabRole.docstatus != 2 AND tabRole.%(key)s LIKE "%s" LIMIT 50' +} + + +// Approving User Trigger +// ----------------------- +cur_frm.fields_dict['approving_user'].get_query = function(doc) { + return 'SELECT tabProfile.name, tabProfile.first_name FROM tabProfile WHERE tabProfile.name not in ("Administrator","Guest") AND tabProfile.docstatus != 2 AND tabProfile.%(key)s LIKE "%s" LIMIT 50' +} + + +// Approving Role Trigger +// ----------------------- +cur_frm.fields_dict['approving_role'].get_query = function(doc) { + return 'SELECT tabRole.name FROM tabRole WHERE tabRole.name not in ("Administrator","Guest","All") AND tabRole.docstatus != 2 AND tabRole.%(key)s LIKE "%s" LIMIT 50' +} + + +// Master Name Trigger +// -------------------- +cur_frm.fields_dict['master_name'].get_query = function(doc){ + if(doc.based_on == 'Customerwise Discount') + return 'SELECT `tabCustomer`.`name` FROM `tabCustomer` WHERE `tabCustomer`.docstatus !=2 and `tabCustomer`.`name` LIKE "%s" ORDER BY `tabCustomer`.`name` DESC LIMIT 50'; + else if(doc.based_on == 'Itemwise Discount') + return 'SELECT `tabItem`.`name` FROM `tabItem` WHERE (IFNULL(`tabItem`.`end_of_life`,"") = "" OR `tabItem`.`end_of_life` = "0000-00-00" OR `tabItem`.`end_of_life` > NOW()) and `tabItem`.is_sales_item = "Yes" and tabItem.%(key)s LIKE "%s" ORDER BY `tabItem`.`name` DESC LIMIT 50'; + else + return 'SELECT `tabItem`.`name` FROM `tabItem` WHERE `tabItem`.`name` = "cheating done to avoid null" ORDER BY `tabItem`.`name` DESC LIMIT 50'; } From 525887fd8ab7d2aad5ac829ad8365d5bc1a4ab24 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 27 Sep 2011 17:00:01 +0530 Subject: [PATCH 07/10] Error fixed in auth control --- .../authorization_control/authorization_control.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/erpnext/setup/doctype/authorization_control/authorization_control.py b/erpnext/setup/doctype/authorization_control/authorization_control.py index d0494301c8..3ddcab41db 100644 --- a/erpnext/setup/doctype/authorization_control/authorization_control.py +++ b/erpnext/setup/doctype/authorization_control/authorization_control.py @@ -38,7 +38,7 @@ class DocType(TransactionBase): for d in app_dtl: if(d[0]): appr_users.append(d[0]) if(d[1]): appr_roles.append(d[1]) - + if not has_common(appr_roles, webnotes.user.get_roles()) and not has_common(appr_users, session['user']): msg, add_msg = '','' if max_amount: @@ -117,7 +117,7 @@ class DocType(TransactionBase): # Check for authorization set for individual user based_on = [x[0] for x in sql("select distinct based_on from `tabAuthorization Rule` where transaction = %s and system_user = %s and (company = %s or ifnull(company,'')='') and docstatus != 2", (doctype_name, session['user'], company))] - + for d in based_on: self.bifurcate_based_on_type(doctype_name, total, av_dis, d, doc_obj, 1, company) @@ -128,7 +128,13 @@ class DocType(TransactionBase): # Specific Role # =============== # Check for authorization set on particular roles - based_on = [x[0] for x in sql("select based_on from `tabAuthorization Rule` where transaction = %s and system_role IN (%s) and based_on IN (%s) and (company = %s or ifnull(company,'')='') and docstatus != 2", (doctype_name, "'"+"','".join(webnotes.user.get_roles())+"'", "'"+"','".join(final_based_on)+"'",company))] + based_on = [x[0] for x in sql("""select based_on + from `tabAuthorization Rule` + where transaction = %s and system_role IN (%s) and based_on IN (%s) + and (company = %s or ifnull(company,'')='') + and docstatus != 2 + """ % ('%s', "'"+"','".join(webnotes.user.get_roles())+"'", "'"+"','".join(final_based_on)+"'", '%s'), (doctype_name, company))] + for d in based_on: self.bifurcate_based_on_type(doctype_name, total, av_dis, d, doc_obj, 2, company) From fff40599e808e47ea8a81de88d5eb278f7b82d84 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 29 Sep 2011 10:39:44 +0530 Subject: [PATCH 08/10] test field deleted from warehouse --- erpnext/stock/doctype/warehouse/warehouse.txt | 76 ++----------------- 1 file changed, 6 insertions(+), 70 deletions(-) diff --git a/erpnext/stock/doctype/warehouse/warehouse.txt b/erpnext/stock/doctype/warehouse/warehouse.txt index 1363eef701..da29dfab64 100644 --- a/erpnext/stock/doctype/warehouse/warehouse.txt +++ b/erpnext/stock/doctype/warehouse/warehouse.txt @@ -5,17 +5,18 @@ { 'creation': '2010-08-08 17:09:30', 'docstatus': 0, - 'modified': '2010-12-16 23:57:04', - 'modified_by': 'nabin@webnotestech.com', + 'modified': '2011-09-28 16:19:59', + 'modified_by': 'Administrator', 'owner': 'Administrator' }, # These values are common for all DocType { - '_last_update': '1300788639', + '_last_update': '1311621379', 'allow_trash': 1, 'autoname': 'field:warehouse_name', 'colour': 'White:FFF', + 'default_print_format': 'Standard', 'doctype': 'DocType', 'document_type': 'Master', 'module': 'Stock', @@ -24,7 +25,7 @@ 'section_style': 'Tabbed', 'server_code_error': ' ', 'show_in_menu': 0, - 'version': 55 + 'version': 56 }, # These values are common for all DocField @@ -58,7 +59,6 @@ 'cancel': 0, 'create': 0, 'doctype': 'DocPerm', - 'idx': 1, 'permlevel': 2, 'role': 'Material User', 'submit': 0, @@ -71,7 +71,6 @@ 'cancel': 0, 'create': 0, 'doctype': 'DocPerm', - 'idx': 2, 'permlevel': 0, 'role': 'Material User', 'submit': 0, @@ -84,7 +83,6 @@ 'cancel': 0, 'create': 0, 'doctype': 'DocPerm', - 'idx': 3, 'permlevel': 1, 'role': 'Material User', 'submit': 0, @@ -97,7 +95,6 @@ 'cancel': 0, 'create': 0, 'doctype': 'DocPerm', - 'idx': 4, 'permlevel': 2, 'role': 'Material Manager', 'submit': 0, @@ -110,7 +107,6 @@ 'cancel': 0, 'create': 0, 'doctype': 'DocPerm', - 'idx': 5, 'permlevel': 0, 'role': 'Material Manager', 'submit': 0, @@ -123,7 +119,6 @@ 'cancel': 0, 'create': 0, 'doctype': 'DocPerm', - 'idx': 6, 'permlevel': 1, 'role': 'Material Manager', 'submit': 0, @@ -133,7 +128,6 @@ # DocPerm { 'doctype': 'DocPerm', - 'idx': 7, 'permlevel': 1, 'role': 'All' }, @@ -144,7 +138,6 @@ 'cancel': 1, 'create': 1, 'doctype': 'DocPerm', - 'idx': 8, 'permlevel': 0, 'role': 'Material Master Manager', 'submit': 0, @@ -154,7 +147,6 @@ # DocPerm { 'doctype': 'DocPerm', - 'idx': 9, 'permlevel': 1, 'role': 'Material Master Manager' }, @@ -164,7 +156,6 @@ 'cancel': 1, 'create': 1, 'doctype': 'DocPerm', - 'idx': 10, 'permlevel': 0, 'role': 'System Manager', 'write': 1 @@ -174,7 +165,6 @@ { 'create': 0, 'doctype': 'DocPerm', - 'idx': 11, 'permlevel': 2, 'role': 'System Manager', 'write': 1 @@ -185,7 +175,6 @@ 'doctype': 'DocField', 'fieldname': 'trash_reason', 'fieldtype': 'Small Text', - 'idx': 1, 'label': 'Trash Reason', 'oldfieldname': 'trash_reason', 'oldfieldtype': 'Small Text', @@ -196,7 +185,6 @@ { 'doctype': 'DocField', 'fieldtype': 'Section Break', - 'idx': 2, 'label': 'Warehouse Detail', 'oldfieldtype': 'Section Break', 'permlevel': 0 @@ -207,7 +195,6 @@ 'doctype': 'DocField', 'fieldname': 'warehouse_name', 'fieldtype': 'Data', - 'idx': 3, 'label': 'Warehouse Name', 'oldfieldname': 'warehouse_name', 'oldfieldtype': 'Data', @@ -221,7 +208,6 @@ 'doctype': 'DocField', 'fieldname': 'warehouse_type', 'fieldtype': 'Link', - 'idx': 4, 'label': 'Warehouse Type', 'oldfieldname': 'warehouse_type', 'oldfieldtype': 'Link', @@ -237,14 +223,13 @@ 'doctype': 'DocField', 'fieldname': 'company', 'fieldtype': 'Link', - 'idx': 5, 'in_filter': 1, 'label': 'Company', 'oldfieldname': 'company', 'oldfieldtype': 'Link', 'options': 'Company', 'permlevel': 0, - 'search_index': 0 + 'search_index': 1 }, # DocField @@ -253,7 +238,6 @@ 'fieldname': 'email_id', 'fieldtype': 'Data', 'hidden': 1, - 'idx': 6, 'label': 'Email Id', 'oldfieldname': 'email_id', 'oldfieldtype': 'Data', @@ -267,7 +251,6 @@ 'fieldname': 'auto_indent_mail', 'fieldtype': 'Select', 'hidden': 1, - 'idx': 7, 'label': 'Send Reorder Alert Mail ', 'no_copy': 1, 'oldfieldname': 'auto_indent_mail', @@ -285,7 +268,6 @@ 'doctype': 'DocField', 'fieldname': 'phone_no', 'fieldtype': 'Int', - 'idx': 8, 'label': 'Phone No', 'oldfieldname': 'phone_no', 'oldfieldtype': 'Int', @@ -298,7 +280,6 @@ 'doctype': 'DocField', 'fieldname': 'mobile_no', 'fieldtype': 'Int', - 'idx': 9, 'label': 'Mobile No', 'oldfieldname': 'mobile_no', 'oldfieldtype': 'Int', @@ -310,7 +291,6 @@ { 'doctype': 'DocField', 'fieldtype': 'Column Break', - 'idx': 10, 'oldfieldtype': 'Column Break', 'permlevel': 0 }, @@ -320,7 +300,6 @@ 'doctype': 'DocField', 'fieldname': 'address_line_1', 'fieldtype': 'Data', - 'idx': 11, 'label': 'Address Line 1', 'oldfieldname': 'address_line_1', 'oldfieldtype': 'Data', @@ -332,7 +311,6 @@ 'doctype': 'DocField', 'fieldname': 'address_line_2', 'fieldtype': 'Data', - 'idx': 12, 'label': 'Address Line 2', 'oldfieldname': 'address_line_2', 'oldfieldtype': 'Data', @@ -346,7 +324,6 @@ 'fieldname': 'country', 'fieldtype': 'Link', 'hidden': 0, - 'idx': 13, 'in_filter': 0, 'label': 'Country', 'no_copy': 0, @@ -367,7 +344,6 @@ 'doctype': 'DocField', 'fieldname': 'state', 'fieldtype': 'Select', - 'idx': 14, 'label': 'State', 'oldfieldname': 'state', 'oldfieldtype': 'Select', @@ -380,7 +356,6 @@ 'doctype': 'DocField', 'fieldname': 'city', 'fieldtype': 'Data', - 'idx': 15, 'label': 'City', 'oldfieldname': 'city', 'oldfieldtype': 'Data', @@ -393,7 +368,6 @@ 'doctype': 'DocField', 'fieldname': 'pin', 'fieldtype': 'Int', - 'idx': 16, 'label': 'PIN', 'oldfieldname': 'pin', 'oldfieldtype': 'Int', @@ -404,7 +378,6 @@ { 'doctype': 'DocField', 'fieldtype': 'Section Break', - 'idx': 17, 'label': 'Repost Stock', 'oldfieldtype': 'Section Break', 'permlevel': 2 @@ -415,46 +388,9 @@ 'doctype': 'DocField', 'fieldtype': 'Button', 'hidden': 0, - 'idx': 18, 'label': 'Repost Stock Ledger', 'oldfieldtype': 'Button', 'options': 'repost_stock', 'permlevel': 2 - }, - - # DocField - { - 'doctype': 'DocField', - 'fieldname': 'test_field2', - 'fieldtype': 'Data', - 'idx': 19, - 'label': 'Test Field2', - 'oldfieldname': 'test_field2', - 'oldfieldtype': 'Data', - 'permlevel': 0 - }, - - # DocField - { - 'doctype': 'DocField', - 'fieldname': 'test_field1', - 'fieldtype': 'Data', - 'idx': 20, - 'label': 'Test Field1', - 'oldfieldname': 'test_field1', - 'oldfieldtype': 'Data', - 'permlevel': 0 - }, - - # DocField - { - 'doctype': 'DocField', - 'fieldname': 'test_field', - 'fieldtype': 'Data', - 'idx': 21, - 'label': 'Test Field', - 'oldfieldname': 'test_field', - 'oldfieldtype': 'Data', - 'permlevel': 0 } ] \ No newline at end of file From 79e8247d82ebcbc9a60aae09d2ee1e0fe0a505ec Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 29 Sep 2011 10:40:04 +0530 Subject: [PATCH 09/10] fix in stock ledger --- erpnext/stock/doctype/stock_ledger/stock_ledger.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/stock_ledger/stock_ledger.py b/erpnext/stock/doctype/stock_ledger/stock_ledger.py index ff6de7083d..c1bfa968d3 100644 --- a/erpnext/stock/doctype/stock_ledger/stock_ledger.py +++ b/erpnext/stock/doctype/stock_ledger/stock_ledger.py @@ -139,7 +139,7 @@ class DocType: elif purpose == 'Sales Return': sql("update `tabSerial No` set status = 'Delivered', purchase_document_type = '', purchase_document_no = '' where name = '%s'" % serial_no) else: - 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) + sql("update `tabSerial No` set docstatus = 2, status = 'Not in Use', purchase_document_type = '', purchase_document_no = '', purchase_date = null, purchase_rate = 0, supplier = null, supplier_name = '', supplier_address = '', warehouse = '' where name = '%s'" % serial_no) # ------------------------------- From 31665e538a8e58f4152679d9bd98b39fb4b71136 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 29 Sep 2011 10:41:02 +0530 Subject: [PATCH 10/10] Test Case: stock entry submit and cancel Sandbox created for maintaining testdata and testcases --- erpnext/sandbox/__init__.py | 0 erpnext/sandbox/test_stock_entry.py | 110 +++++++++ erpnext/sandbox/testdata/__init__.py | 0 erpnext/sandbox/testdata/masters.py | 282 ++++++++++++++++++++++++ erpnext/sandbox/testdata/stock_entry.py | 32 +++ 5 files changed, 424 insertions(+) create mode 100644 erpnext/sandbox/__init__.py create mode 100644 erpnext/sandbox/test_stock_entry.py create mode 100644 erpnext/sandbox/testdata/__init__.py create mode 100644 erpnext/sandbox/testdata/masters.py create mode 100644 erpnext/sandbox/testdata/stock_entry.py diff --git a/erpnext/sandbox/__init__.py b/erpnext/sandbox/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/sandbox/test_stock_entry.py b/erpnext/sandbox/test_stock_entry.py new file mode 100644 index 0000000000..273c4424a1 --- /dev/null +++ b/erpnext/sandbox/test_stock_entry.py @@ -0,0 +1,110 @@ +import unittest + +import webnotes +import webnotes.profile +webnotes.user = webnotes.profile.Profile() + + +from webnotes.model.doc import Document +from webnotes.model.code import get_obj +from webnotes.utils import cstr, flt +sql = webnotes.conn.sql + +from sandbox.testdata.masters import * +from sandbox.testdata import stock_entry +#---------------------------------------------------------- + +class TestStockEntry(unittest.TestCase): + def setUp(self): + print "=====================================" + webnotes.conn.begin() + + create_master_records() + print 'Master Data Created' + + for each in stock_entry.mr: + each.save(1) + + for t in stock_entry.mr[1:]: + sql("update `tabStock Entry Detail` set parent = '%s' where name = '%s'" % (stock_entry.mr[0].name, t.name)) + print "Stock Entry Created" + + + #=========================================================================== + def test_stock_entry_onsubmit(self): + print "Test Case: Stock Entry submission" + self.submit_stock_entry() + + expected_sle = (('Stock Entry', stock_entry.mr[0].name, 10, 10, 100, 'No'),) + self.check_sle(expected_sle) + + self.check_bin_qty(10) + self.check_serial_no('submit', 10) + + #=========================================================================== + def test_stock_entry_oncancel(self): + print "Test Case: Stock Entry Cancellation" + self.cancel_stock_entry() + + expected_sle = ( + ('Stock Entry', stock_entry.mr[0].name, 10, 10, 100, 'Yes'), + ('Stock Entry', stock_entry.mr[0].name, -10, None, None, 'Yes'), + ) + self.check_sle(expected_sle) + + self.check_bin_qty(0) + self.check_serial_no('cancel', 10) + + + #=========================================================================== + def submit_stock_entry(self): + ste1 = get_obj('Stock Entry', stock_entry.mr[0].name, with_children=1) + ste1.validate() + ste1.on_submit() + + ste1.doc.docstatus = 1 + ste1.doc.save() + + print "Stock Entry Submitted" + + + #=========================================================================== + def cancel_stock_entry(self): + self.submit_stock_entry() + + ste1 = get_obj('Stock Entry', stock_entry.mr[0].name, with_children=1) + ste1.on_cancel() + + ste1.doc.cancel_reason = "testing" + ste1.doc.docstatus = 2 + ste1.doc.save() + + print "Stock Entry Cancelled" + + #=========================================================================== + def check_sle(self, expected): + print "Checking stock ledger entry........." + sle = sql("select voucher_type, voucher_no, actual_qty, bin_aqat, valuation_rate, is_cancelled from `tabStock Ledger Entry` where item_code = 'it' and warehouse = 'wh1'") + self.assertTrue(sle == expected) + + #=========================================================================== + def check_bin_qty(self, expected_qty): + print "Checking Bin qty........." + bin_qty = sql("select actual_qty from tabBin where item_code = 'it' and warehouse = 'wh1'") + self.assertTrue(bin_qty[0][0] == expected_qty) + + #=========================================================================== + def check_serial_no(self, action, cnt): + print "Checking serial nos........" + if action == 'submit': + status, wh, docstatus = 'In Store', 'wh1', 0 + else: + status, wh, docstatus = 'Not in Use', '', 2 + + ser = sql("select count(name) from `tabSerial No` where item_code = 'it' and warehouse = '%s' and status = '%s' and docstatus = %s" % (wh, status, docstatus)) + + self.assertTrue(ser[0][0] == cnt) + + #=========================================================================== + def tearDown(self): + webnotes.conn.rollback() diff --git a/erpnext/sandbox/testdata/__init__.py b/erpnext/sandbox/testdata/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/sandbox/testdata/masters.py b/erpnext/sandbox/testdata/masters.py new file mode 100644 index 0000000000..7f2d67c4da --- /dev/null +++ b/erpnext/sandbox/testdata/masters.py @@ -0,0 +1,282 @@ +""" + All master data in one place, can be created by 1 function call + +""" + +import webnotes +from webnotes.model.doc import Document + + +master_groups = { + # Company + #---------------------------------- + 'company': Document( + fielddata={ + 'doctype':'Company', + 'abbr': 'co', + 'company_name' : 'comp', + 'name': 'comp' + } + ), + + # Customer Group + #---------------------------------- + 'customer_group': Document( + fielddata={ + 'doctype':'Customer Group', + 'customer_group_name' : 'cg', + 'name': 'cg', + 'is_group': 'No', + 'parent_customer_group':'', + 'lft' : 1, + 'rgt': 2 + } + ), + + # Item Group + #---------------------------------- + 'item_group': Document( + fielddata = { + 'doctype': 'Item Group', + 'item_group_name': 'ig', + 'lft': 1, + 'rgt': 2, + 'parent_item_group' : '', + 'is_group': 'No', + 'name': 'ig' + } + ), + + # Warehouse Type + #----------------------------- + 'warehouse_type' : Document( + fielddata = { + 'doctype' : 'Warehouse Type', + 'name': 'normal', + 'warehouse_type' : 'normal' + } + ), + + # Supplier Type + #----------------------------- + 'supplier_type' : Document( + fielddata = { + 'doctype': 'Supplier Type', + 'supplier_type': 'stype' + } + ) + +} + + +main_masters = { + # Customer + #---------------------------------- + 'customer': Document( + fielddata={ + 'doctype':'Customer', + 'docstatus':0, + 'customer_name' : 'cust', + 'company' : 'comp', + 'customer_group' : '', + 'name': 'cust' + } + ), + + + # Supplier + #---------------------------------- + 'supplier': Document( + fielddata = { + 'doctype': 'Supplier', + 'supplier_name': 'supp', + 'name': 'supp', + 'supplier_type' : 'stype' + } + ), + + # Customer Account + #---------------------------------- + 'customer_acc': Document( + fielddata={ + 'doctype':'Account', + 'docstatus':0, + 'account_name' : 'cust', + 'debit_or_credit': 'Debit', + 'company' : 'comp', + 'lft': 1, + 'rgt': 2, + 'group_or_ledger' : 'Ledger', + 'is_pl_account': 'No', + 'name' : 'cust - co' + } + ), + + # Customer Account + #---------------------------------- + 'supplier_acc': Document( + fielddata={ + 'doctype':'Account', + 'docstatus':0, + 'account_name' : 'supp', + 'debit_or_credit': 'Credit', + 'company' : 'comp', + 'lft': 5, + 'rgt': 6, + 'group_or_ledger' : 'Ledger', + 'is_pl_account': 'No', + 'name' : 'supp - co' + } + ), + + # Bank Account + #---------------------------------- + 'bank_acc': Document( + fielddata={ + 'doctype':'Account', + 'docstatus':0, + 'account_name' : 'icici', + 'parent_account': '', + 'debit_or_credit': 'Debit', + 'company' : 'comp', + 'lft': 3, + 'rgt': 4, + 'group_or_ledger' : 'Ledger', + 'is_pl_account': 'No', + 'name' : 'icici - co' + } + ), + + # Income Account + #---------------------------------- + 'income_acc': Document( + fielddata={ + 'doctype':'Account', + 'docstatus':0, + 'account_name' : 'income', + 'debit_or_credit': 'Credit', + 'company' : 'comp', + 'lft': 7, + 'rgt': 8, + 'group_or_ledger' : 'Ledger', + 'is_pl_account': 'Yes', + 'name' : 'income - co' + } + ), + + # Expense Account + #---------------------------------- + 'expense_acc': Document( + fielddata={ + 'doctype':'Account', + 'docstatus':0, + 'account_name' : 'expense', + 'debit_or_credit': 'Debit', + 'company' : 'comp', + 'lft': 9, + 'rgt': 10, + 'group_or_ledger' : 'Ledger', + 'is_pl_account': 'Yes', + 'name' : 'expense - co' + } + ), + + # Cost Center + #---------------------------------- + 'cost_center': Document( + fielddata={ + 'doctype':'Cost Center', + 'docstatus':0, + 'cost_center_name' : 'cc', + 'lft': 1, + 'rgt': 2, + 'group_or_ledger' : 'Ledger', + 'name' : 'cc' + } + ), + + # Item + #---------------------------------- + # Stock item / non-serialized + + 'item': [ + Document( + fielddata = { + 'doctype': 'Item', + 'docstatus': 0, + 'name': 'it', + 'item_name': 'it', + 'item_code': 'it', + 'item_group': 'ig', + 'is_stock_item': 'Yes', + 'has_serial_no': 'Yes', + 'stock_uom': 'Nos', + 'is_sales_item': 'Yes', + 'is_purchase_item': 'Yes', + 'is_service_item': 'No', + 'is_sub_contracted_item': 'No', + 'is_pro_applicable': 'Yes', + 'is_manufactured_item': 'Yes' + } + ), + Document( + fielddata = { + 'doctype': 'Ref Rate Detail', + 'parentfield': 'ref_rate_details', + 'parenttype': 'Item', + 'parent' : 'it', + 'price_list_name': 'pl', + 'ref_currency': 'INR', + 'ref_rate': 100 + } + ), + Document( + fielddata = { + 'doctype': 'Item Tax', + 'parentfield': 'item_tax', + 'parenttype': 'Item', + 'parent' : 'it', + 'tax_type' : 'Tax1', + 'tax_rate': 10 + } + ) + ], + + # Warehouse + #----------------------------- + 'warehouse': [ + Document( + fielddata = { + 'doctype': 'Warehouse', + 'name' : 'wh1', + 'warehouse_name' : 'wh1', + 'warehouse_type': 'normal', + 'company': 'comp' + } + ), + Document( + fielddata = { + 'doctype': 'Warehouse', + 'name' : 'wh2', + 'warehouse_name' : 'wh2', + 'warehouse_type': 'normal', + 'company': 'comp' + } + ) + ] +} + + + +# Save all master records +#---------------------------------- +def create_master_records(): + for m in master_groups.keys(): + master_groups[m].save(1) + + for m in main_masters.keys(): + if type(main_masters[m]) == list: + for each in main_masters[m]: + each.save(1) + else: + main_masters[m].save(1) diff --git a/erpnext/sandbox/testdata/stock_entry.py b/erpnext/sandbox/testdata/stock_entry.py new file mode 100644 index 0000000000..e2d1d71c02 --- /dev/null +++ b/erpnext/sandbox/testdata/stock_entry.py @@ -0,0 +1,32 @@ +from webnotes.model.doc import Document + +mr = [ + Document( + fielddata = { + 'doctype': 'Stock Entry', + 'posting_date': '2011-09-01', + 'transfer_date': '2011-09-01', + 'posting_time': '12:00', + 'company': 'comp', + 'fiscal_year' : '2011-2012', + 'purpose': 'Material Receipt', + 'name': 'ste' + } + ), + Document( + fielddata ={ + 'doctype': 'Stock Entry Detail', + 'parenttype': 'Stock Entry', + 'parentfield' : 'mtn_details', + 'parent' : 'ste', + 'item_code' : 'it', + 't_warehouse' : 'wh1', + 'qty' : 10, + 'transfer_qty' : 10, + 'incoming_rate': 100, + 'stock_uom': 'Nos', + 'conversion_factor': 1, + 'serial_no': 'srno1, srno2, srno3, srno4, srno5, srno6, srno7, srno8, srno9, srno10' + } + ) +]