diff --git a/accounts/doctype/account/account.js b/accounts/doctype/account/account.js index 77386823e4..db50ff6ac8 100644 --- a/accounts/doctype/account/account.js +++ b/accounts/doctype/account/account.js @@ -120,7 +120,7 @@ cur_frm.fields_dict['master_name'].get_query = function(doc) { if (doc.master_type) { return { query: "accounts.doctype.account.account.get_master_name", - args: { "master_type": doc.master_type } + filters: { "master_type": doc.master_type } } } } @@ -128,6 +128,6 @@ cur_frm.fields_dict['master_name'].get_query = function(doc) { cur_frm.fields_dict['parent_account'].get_query = function(doc) { return { query: "accounts.doctype.account.account.get_parent_account", - args: { "company": doc.company} + filters: { "company": doc.company} } } diff --git a/accounts/doctype/account/account.py b/accounts/doctype/account/account.py index 14af7cf4ef..b590ba7fc0 100644 --- a/accounts/doctype/account/account.py +++ b/accounts/doctype/account/account.py @@ -29,13 +29,12 @@ class DocType: self.nsm_parent_field = 'parent_account' def autoname(self): - company_abbr = sql("select abbr from tabCompany where name=%s", self.doc.company)[0][0] - self.doc.name = self.doc.account_name.strip() + ' - ' + company_abbr + self.doc.name = self.doc.account_name.strip() + ' - ' + \ + webnotes.conn.get_value("Company", self.doc.company, "abbr") - def get_address(self): - add=sql("Select address from `tab%s` where name='%s'" % - (self.doc.master_type, self.doc.master_name)) - return {'address': add[0][0]} + def get_address(self): + address = webnotes.conn.get_value(self.doc.master_type, self.doc.master_name, "address") + return {'address': address} def validate_master_name(self): if (self.doc.master_type == 'Customer' or self.doc.master_type == 'Supplier') \ @@ -46,7 +45,7 @@ class DocType: """Fetch Parent Details and validation for account not to be created under ledger""" if self.doc.parent_account: par = sql("""select name, group_or_ledger, is_pl_account, debit_or_credit - from tabAccount where name =%s""",self.doc.parent_account) + from tabAccount where name =%s""", self.doc.parent_account) if not par: msgprint("Parent account does not exists", raise_exception=1) elif par and par[0][0] == self.doc.name: @@ -106,8 +105,8 @@ class DocType: # Check if any previous balance exists def check_gle_exists(self): - exists = sql("""select name from `tabGL Entry` where account = '%s' - and ifnull(is_cancelled, 'No') = 'No'""" % (self.doc.name)) + exists = sql("""select name from `tabGL Entry` where account = %s + and ifnull(is_cancelled, 'No') = 'No'""", self.doc.name) return exists and exists[0][0] or '' def check_if_child_exists(self): @@ -150,7 +149,7 @@ class DocType: credit_limit_from = 'Customer' cr_limit = sql("""select t1.credit_limit from tabCustomer t1, `tabAccount` t2 - where t2.name='%s' and t1.name = t2.master_name""" % account) + where t2.name=%s and t1.name = t2.master_name""", account) credit_limit = cr_limit and flt(cr_limit[0][0]) or 0 if not credit_limit: credit_limit = webnotes.conn.get_value('Company', company, 'credit_limit') @@ -193,19 +192,22 @@ class DocType: # rename account name account_name = " - ".join(parts[:-1]) - sql("update `tabAccount` set account_name = '%s' where name = '%s'" % \ - (account_name, old)) + sql("update `tabAccount` set account_name = %s where name = %s", (account_name, old)) return " - ".join(parts) -def get_master_name(doctype, txt, searchfield, start, page_len, args): - return webnotes.conn.sql("""select name from `tab%s` where name like '%%%s%%'""" % - (args["master_type"], txt), as_list=1) +def get_master_name(doctype, txt, searchfield, start, page_len, filters): + return webnotes.conn.sql("""select name from `tab%s` where %s like %s + order by name limit %s, %s""" % + (filters["master_type"], searchfield, "%s", "%s", "%s"), + ("%%%s%%" % txt, start, page_len), as_list=1) -def get_parent_account(doctype, txt, searchfield, start, page_len, args): +def get_parent_account(doctype, txt, searchfield, start, page_len, filters): return webnotes.conn.sql("""select name from tabAccount - where group_or_ledger = 'Group' and docstatus != 2 and company = '%s' - and name like '%%%s%%'""" % (args["company"], txt)) + where group_or_ledger = 'Group' and docstatus != 2 and company = %s + and %s like %s order by name limit %s, %s""" % + ("%s", searchfield, "%s", "%s", "%s"), + (filters["company"], "%%%s%%" % txt, start, page_len), as_list=1) def make_test_records(verbose): from webnotes.test_runner import load_module_and_make_records, make_test_objects diff --git a/accounts/doctype/c_form/c_form.js b/accounts/doctype/c_form/c_form.js index adb989d8f7..29c05f7223 100644 --- a/accounts/doctype/c_form/c_form.js +++ b/accounts/doctype/c_form/c_form.js @@ -17,15 +17,16 @@ //c-form js file // ----------------------------- cur_frm.fields_dict.invoice_details.grid.get_field("invoice_no").get_query = function(doc) { - cond = "" - if (doc.customer) cond += ' AND `tabSales Invoice`.`customer` = "' + cstr(doc.customer) + '"'; - if (doc.company) cond += ' AND `tabSales Invoice`.`company` = "' + cstr(doc.company) + '"'; - return 'SELECT `tabSales Invoice`.`name` FROM `tabSales Invoice` WHERE `tabSales Invoice`.`docstatus` = 1 and `tabSales Invoice`.`c_form_applicable` = "Yes" and ifnull(`tabSales Invoice`.c_form_no, "") = ""'+cond+' AND `tabSales Invoice`.%(key)s LIKE "%s" ORDER BY `tabSales Invoice`.`name` ASC LIMIT 50'; + return { + query: "accounts.doctype.c_form.c_form.get_invoice_nos", + filters: { + customer: doc.customer, + company: doc.company + } + } } cur_frm.cscript.invoice_no = function(doc, cdt, cdn) { var d = locals[cdt][cdn]; get_server_fields('get_invoice_details', d.invoice_no, 'invoice_details', doc, cdt, cdn, 1); -} - -cur_frm.fields_dict.customer.get_query = erpnext.utils.customer_query; \ No newline at end of file +} \ No newline at end of file diff --git a/accounts/doctype/c_form/c_form.py b/accounts/doctype/c_form/c_form.py index 4575653699..5bca063dd7 100644 --- a/accounts/doctype/c_form/c_form.py +++ b/accounts/doctype/c_form/c_form.py @@ -32,22 +32,23 @@ class DocType: and no other c-form is received for that""" for d in getlist(self.doclist, 'invoice_details'): - inv = webnotes.conn.sql("""select c_form_applicable, c_form_no from - `tabSales Invoice` where name = %s""", d.invoice_no) + if d.invoice_no: + inv = webnotes.conn.sql("""select c_form_applicable, c_form_no from + `tabSales Invoice` where name = %s""", d.invoice_no) - if not inv: - webnotes.msgprint("Invoice: %s is not exists in the system, please check." % - d.invoice_no, raise_exception=1) + if not inv: + webnotes.msgprint("Invoice: %s is not exists in the system, please check." % + d.invoice_no, raise_exception=1) - elif inv[0][0] != 'Yes': - webnotes.msgprint("C-form is not applicable for Invoice: %s" % - d.invoice_no, raise_exception=1) + elif inv[0][0] != 'Yes': + webnotes.msgprint("C-form is not applicable for Invoice: %s" % + d.invoice_no, raise_exception=1) - elif inv[0][1] and inv[0][1] != self.doc.name: - webnotes.msgprint("""Invoice %s is tagged in another C-form: %s. - If you want to change C-form no for this invoice, - please remove invoice no from the previous c-form and then try again""" % - (d.invoice_no, inv[0][1]), raise_exception=1) + elif inv[0][1] and inv[0][1] != self.doc.name: + webnotes.msgprint("""Invoice %s is tagged in another C-form: %s. + If you want to change C-form no for this invoice, + please remove invoice no from the previous c-form and then try again""" % + (d.invoice_no, inv[0][1]), raise_exception=1) def on_update(self): """ Update C-Form No on invoices""" @@ -80,4 +81,14 @@ class DocType: 'territory' : inv and inv[0][1] or '', 'net_total' : inv and flt(inv[0][2]) or '', 'grand_total' : inv and flt(inv[0][3]) or '' - } \ No newline at end of file + } + +def get_invoice_nos(doctype, txt, searchfield, start, page_len, filters): + from utilities import build_filter_conditions + conditions, filter_values = build_filter_conditions(filters) + + return webnotes.conn.sql("""select name from `tabSales Invoice` where docstatus = 1 + and c_form_applicable = 'Yes' and ifnull(c_form_no, '') = '' %s + and %s like %s order by name limit %s, %s""" % + (conditions, searchfield, "%s", "%s", "%s"), + tuple(filter_values + ["%%%s%%" % txt, start, page_len])) \ No newline at end of file diff --git a/accounts/doctype/fiscal_year/fiscal_year.py b/accounts/doctype/fiscal_year/fiscal_year.py index 34134777db..95c1aa42e6 100644 --- a/accounts/doctype/fiscal_year/fiscal_year.py +++ b/accounts/doctype/fiscal_year/fiscal_year.py @@ -35,7 +35,12 @@ class DocType: test_records = [ [{ "doctype": "Fiscal Year", - "year": "_Test Fiscal Year", + "year": "_Test Fiscal Year 2013", "year_start_date": "2013-01-01" + }], + [{ + "doctype": "Fiscal Year", + "year": "_Test Fiscal Year 2014", + "year_start_date": "2014-01-01" }] ] \ No newline at end of file diff --git a/accounts/doctype/gl_entry/gl_entry.py b/accounts/doctype/gl_entry/gl_entry.py index 9d53994e25..2a0985b04d 100644 --- a/accounts/doctype/gl_entry/gl_entry.py +++ b/accounts/doctype/gl_entry/gl_entry.py @@ -66,11 +66,8 @@ class DocType: self.doc.cost_center = "" def validate_posting_date(self): - from accounts.utils import get_fiscal_year - fiscal_year = get_fiscal_year(self.doc.posting_date)[0] - - if fiscal_year != self.doc.fiscal_year: - msgprint(_("Posting date must be in the Selected Fiscal Year"), raise_exception=1) + from accounts.utils import validate_fiscal_year + validate_fiscal_year(self.doc.posting_date, self.doc.fiscal_year, "Posting Date") def check_credit_limit(self): master_type, master_name = webnotes.conn.get_value("Account", diff --git a/accounts/doctype/journal_voucher/journal_voucher.js b/accounts/doctype/journal_voucher/journal_voucher.js index 444763a7f3..9f82828e6d 100644 --- a/accounts/doctype/journal_voucher/journal_voucher.js +++ b/accounts/doctype/journal_voucher/journal_voucher.js @@ -49,44 +49,6 @@ cur_frm.cscript.is_opening = function(doc, cdt, cdn) { if (doc.is_opening == 'Yes') unhide_field('aging_date'); } -cur_frm.fields_dict['entries'].grid.get_field('account').get_query = function(doc) { - return "SELECT `tabAccount`.name, `tabAccount`.parent_account FROM `tabAccount` WHERE `tabAccount`.company='"+doc.company+"' AND tabAccount.group_or_ledger = 'Ledger' AND tabAccount.docstatus != 2 AND `tabAccount`.%(key)s LIKE '%s' ORDER BY `tabAccount`.name DESC LIMIT 50"; -} - -cur_frm.fields_dict["entries"].grid.get_field("cost_center").get_query = function(doc, cdt, cdn) { - return 'SELECT `tabCost Center`.`name`, `tabCost Center`.parent_cost_center 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'; -} - -// Restrict Voucher based on Account -// --------------------------------- -cur_frm.fields_dict['entries'].grid.get_field('against_voucher').get_query = function(doc) { - var d = locals[this.doctype][this.docname]; - return "SELECT `tabPurchase Invoice`.name, `tabPurchase Invoice`.credit_to, `tabPurchase Invoice`.outstanding_amount,`tabPurchase Invoice`.bill_no, `tabPurchase Invoice`.bill_date FROM `tabPurchase Invoice` WHERE `tabPurchase Invoice`.credit_to='"+d.account+"' AND `tabPurchase Invoice`.outstanding_amount > 0 AND `tabPurchase Invoice`.docstatus = 1 AND `tabPurchase Invoice`.%(key)s LIKE '%s' ORDER BY `tabPurchase Invoice`.name DESC LIMIT 200"; -} - -cur_frm.fields_dict['entries'].grid.get_field('against_invoice').get_query = function(doc) { - var d = locals[this.doctype][this.docname]; - return "SELECT `tabSales Invoice`.name, `tabSales Invoice`.debit_to, `tabSales Invoice`.outstanding_amount FROM `tabSales Invoice` WHERE `tabSales Invoice`.debit_to='"+d.account+"' AND `tabSales Invoice`.outstanding_amount > 0 AND `tabSales Invoice`.docstatus = 1 AND `tabSales Invoice`.%(key)s LIKE '%s' ORDER BY `tabSales Invoice`.name DESC LIMIT 200"; -} - -cur_frm.fields_dict['entries'].grid.get_field('against_jv').get_query = function(doc) { - var d = locals[this.doctype][this.docname]; - - if(!d.account) { - msgprint("Please select Account first!") - throw "account not selected" - } - - return "SELECT `tabJournal Voucher`.name, `tabJournal Voucher`.posting_date,\ - `tabJournal Voucher`.user_remark\ - from `tabJournal Voucher`, `tabJournal Voucher Detail`\ - where `tabJournal Voucher Detail`.account = '"+ esc_quotes(d.account) + "'\ - and `tabJournal Voucher`.name like '%s'\ - and `tabJournal Voucher`.docstatus=1\ - and `tabJournal Voucher`.voucher_type='Journal Entry'\ - and `tabJournal Voucher Detail`.parent = `tabJournal Voucher`.name"; -} - //Set debit and credit to zero on adding new row //---------------------------------------------- cur_frm.fields_dict['entries'].grid.onrowadd = function(doc, cdt, cdn){ @@ -116,9 +78,8 @@ cur_frm.cscript.against_invoice = function(doc,cdt,cdn) { } } - // Update Totals -// --------------- + cur_frm.cscript.update_totals = function(doc) { var td=0.0; var tc =0.0; var el = getchildren('Journal Voucher Detail', doc.name, 'entries'); @@ -161,12 +122,6 @@ cur_frm.cscript.validate = function(doc,cdt,cdn) { cur_frm.cscript.update_totals(doc); } -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'; -} - - - cur_frm.cscript.select_print_heading = function(doc,cdt,cdn){ if(doc.select_print_heading){ // print heading @@ -201,3 +156,49 @@ cur_frm.cscript.voucher_type = function(doc, cdt, cdn) { cur_frm.set_df_property("cheque_date", "reqd", false); } } + +// get_query + +cur_frm.fields_dict['entries'].grid.get_field('account').get_query = function(doc) { + return { + query: "accounts.utils.get_account_list", + filters: { company: doc.company } + } +} + +cur_frm.fields_dict["entries"].grid.get_field("cost_center").get_query = function(doc) { + return { + query: "accounts.utils.get_cost_center_list", + filters: { company_name: doc.company} + } +} + +cur_frm.fields_dict['entries'].grid.get_field('against_voucher').get_query = function(doc) { + var d = locals[this.doctype][this.docname]; + return { + query: "accounts.doctype.journal_voucher.journal_voucher.get_against_purchase_invoice", + filters: { account: d.account } + } +} + +cur_frm.fields_dict['entries'].grid.get_field('against_invoice').get_query = function(doc) { + var d = locals[this.doctype][this.docname]; + return { + query: "accounts.doctype.journal_voucher.journal_voucher.get_against_sales_invoice", + filters: { account: d.account } + } +} + +cur_frm.fields_dict['entries'].grid.get_field('against_jv').get_query = function(doc) { + var d = locals[this.doctype][this.docname]; + + if(!d.account) { + msgprint("Please select Account first!") + throw "account not selected" + } + + return { + query: "accounts.doctype.journal_voucher.journal_voucher.get_against_jv", + filters: { account: d.account } + } +} \ 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 eafd7ee25c..4408068b35 100644 --- a/accounts/doctype/journal_voucher/journal_voucher.py +++ b/accounts/doctype/journal_voucher/journal_voucher.py @@ -339,4 +339,27 @@ class DocType(AccountsController): elif self.doc.write_off_based_on == 'Accounts Payable': return webnotes.conn.sql("""select name, credit_to, outstanding_amount from `tabPurchase Invoice` where docstatus = 1 and company = %s - and outstanding_amount > 0 %s""" % ('%s', cond), self.doc.company) \ No newline at end of file + and outstanding_amount > 0 %s""" % ('%s', cond), self.doc.company) + + +def get_against_purchase_invoice(doctype, txt, searchfield, start, page_len, filters): + return webnotes.conn.sql("""select name, credit_to, outstanding_amount, bill_no, bill_date + from `tabPurchase Invoice` where credit_to = %s and docstatus = 1 + and outstanding_amount > 0 and %s like %s order by name desc limit %s, %s""" % + ("%s", searchfield, "%s", "%s", "%s"), + (filters["account"], "%%%s%%" % txt, start, page_len)) + +def get_against_sales_invoice(doctype, txt, searchfield, start, page_len, filters): + return webnotes.conn.sql("""select name, debit_to, outstanding_amount + from `tabSales Invoice` where debit_to = %s and docstatus = 1 + and outstanding_amount > 0 and `%s` like %s order by name desc limit %s, %s""" % + ("%s", searchfield, "%s", "%s", "%s"), + (filters["account"], "%%%s%%" % txt, start, page_len)) + +def get_against_jv(doctype, txt, searchfield, start, page_len, filters): + return webnotes.conn.sql("""select name, posting_date, user_remark + from `tabJournal Voucher` jv, `tabJournal Voucher Detail` jv_detail + where jv_detail.parent = jv.name and jv_detail.account = %s and docstatus = 1 + and jv.%s like %s order by jv.name desc limit %s, %s""" % + ("%s", searchfield, "%s", "%s", "%s"), + (filters["account"], "%%%s%%" % txt, start, page_len)) \ No newline at end of file diff --git a/accounts/doctype/purchase_invoice/purchase_invoice.py b/accounts/doctype/purchase_invoice/purchase_invoice.py index 8b65e0dbda..8512b01831 100644 --- a/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -32,7 +32,6 @@ class DocType(BuyingController): self.tname = 'Purchase Invoice Item' self.fname = 'entries' - # ************************** Trigger Functions **************************** # Credit To diff --git a/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/accounts/doctype/purchase_invoice/test_purchase_invoice.py index 87577880f2..0619475bd1 100644 --- a/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -19,154 +19,48 @@ from __future__ import unicode_literals import unittest import webnotes import webnotes.model -from webnotes.utils import nowdate - -from stock.doctype.purchase_receipt import test_purchase_receipt - -company = webnotes.conn.get_default("company") -abbr = webnotes.conn.get_value("Company", company, "abbr") - -def load_data(): - test_purchase_receipt.load_data() - - webnotes.insert({"doctype": "Account", "account_name": "Cost for Goods Sold", - "parent_account": "Expenses - %s" % abbr, "company": company, - "group_or_ledger": "Ledger"}) - - webnotes.insert({"doctype": "Account", "account_name": "Excise Duty", - "parent_account": "_Test Tax Assets - %s" % abbr, "company": company, - "group_or_ledger": "Ledger"}) - - webnotes.insert({"doctype": "Account", "account_name": "Education Cess", - "parent_account": "_Test Tax Assets - %s" % abbr, "company": company, - "group_or_ledger": "Ledger"}) - - webnotes.insert({"doctype": "Account", "account_name": "S&H Education Cess", - "parent_account": "_Test Tax Assets - %s" % abbr, "company": company, - "group_or_ledger": "Ledger"}) - - webnotes.insert({"doctype": "Account", "account_name": "CST", - "parent_account": "Direct Expenses - %s" % abbr, "company": company, - "group_or_ledger": "Ledger"}) - - webnotes.insert({"doctype": "Account", "account_name": "Discount", - "parent_account": "Direct Expenses - %s" % abbr, "company": company, - "group_or_ledger": "Ledger"}) - - from webnotes.model.doc import Document - item = Document("Item", "Home Desktop 100") - - # excise duty - item_tax = item.addchild("item_tax", "Item Tax") - item_tax.tax_type = "Excise Duty - %s" % abbr - item_tax.tax_rate = 10 - item_tax.save() - import json -purchase_invoice_doclist = [ - # parent - { - "doctype": "Purchase Invoice", - "credit_to": "East Wind Inc. - %s" % abbr, - "supplier_name": "East Wind Inc.", - "naming_series": "BILL", "posting_date": nowdate(), - "company": company, "fiscal_year": webnotes.conn.get_default("fiscal_year"), - "currency": webnotes.conn.get_default("currency"), "conversion_rate": 1, - 'net_total': 1250.00, 'grand_total': 1512.30, 'grand_total_import': 1512.30, - }, - # items - { - "doctype": "Purchase Invoice Item", - "item_code": "Home Desktop 100", "qty": 10, "import_rate": 50, "rate": 50, - "amount": 500, "import_amount": 500, "parentfield": "entries", - "uom": "Nos", "item_tax_rate": json.dumps({"Excise Duty - %s" % abbr: 10}), - "expense_head": "Cost for Goods Sold - %s" % abbr, - "cost_center": "Default Cost Center - %s" % abbr - }, - { - "doctype": "Purchase Invoice Item", - "item_code": "Home Desktop 200", "qty": 5, "import_rate": 150, "rate": 150, - "amount": 750, "import_amount": 750, "parentfield": "entries", "uom": "Nos", - "expense_head": "Cost for Goods Sold - %s" % abbr, - "cost_center": "Default Cost Center - %s" % abbr - }, - # taxes - { - "doctype": "Purchase Taxes and Charges", "charge_type": "Actual", - "account_head": "Shipping Charges - %s" % abbr, "rate": 100, "tax_amount": 100, - "category": "Valuation and Total", "parentfield": "purchase_tax_details", - "cost_center": "Default Cost Center - %s" % abbr, "add_deduct_tax": "Add" - }, - { - "doctype": "Purchase Taxes and Charges", "charge_type": "On Net Total", - "account_head": "Customs Duty - %s" % abbr, "rate": 10, "tax_amount": 125.00, - "category": "Valuation", "parentfield": "purchase_tax_details", - "cost_center": "Default Cost Center - %s" % abbr, "add_deduct_tax": "Add" - }, - { - "doctype": "Purchase Taxes and Charges", "charge_type": "On Net Total", - "account_head": "Excise Duty - %s" % abbr, "rate": 12, "tax_amount": 140.00, - "category": "Total", "parentfield": "purchase_tax_details", "add_deduct_tax": "Add" - }, - { - "doctype": "Purchase Taxes and Charges", "charge_type": "On Previous Row Amount", - "account_head": "Education Cess - %s" % abbr, "rate": 2, "row_id": 3, "tax_amount": 2.80, - "category": "Total", "parentfield": "purchase_tax_details", "add_deduct_tax": "Add" - }, - { - "doctype": "Purchase Taxes and Charges", "charge_type": "On Previous Row Amount", - "account_head": "S&H Education Cess - %s" % abbr, "rate": 1, "row_id": 3, - "tax_amount": 1.4, "category": "Total", "parentfield": "purchase_tax_details", - "add_deduct_tax": "Add" - }, - { - "doctype": "Purchase Taxes and Charges", "charge_type": "On Previous Row Total", - "account_head": "CST - %s" % abbr, "rate": 2, "row_id": 5, "tax_amount": 29.88, - "category": "Total", "parentfield": "purchase_tax_details", - "cost_center": "Default Cost Center - %s" % abbr, "add_deduct_tax": "Add" - }, - { - "doctype": "Purchase Taxes and Charges", "charge_type": "On Net Total", - "account_head": "VAT - Test - %s" % abbr, "rate": 12.5, "tax_amount": 156.25, - "category": "Total", "parentfield": "purchase_tax_details", "add_deduct_tax": "Add" - }, - { - "doctype": "Purchase Taxes and Charges", "charge_type": "On Previous Row Total", - "account_head": "Discount - %s" % abbr, "rate": 10, "row_id": 7, "tax_amount": 168.03, - "category": "Total", "parentfield": "purchase_tax_details", - "cost_center": "Default Cost Center - %s" % abbr, "add_deduct_tax": "Deduct" - }, -] class TestPurchaseInvoice(unittest.TestCase): def setUp(self): webnotes.conn.begin() - load_data() - # webnotes.conn.set_value("Global Defaults", None, "automatic_inventory_accounting", 1) self.load_test_data() + # webnotes.conn.set_value("Global Defaults", None, + # "automatic_inventory_accounting", 1) + + def tearDown(self): + webnotes.conn.rollback() def load_test_data(self): from webnotes.test_runner import make_test_records + webnotes.test_objects = {} make_test_records("Cost Center", verbose=0) make_test_records("Item", verbose=0) make_test_records("Purchase Invoice", verbose=0) - def atest_gl_entries(self): - wrapper = webnotes.model_wrapper(purchase_invoice_doclist).insert() + def test_gl_entries(self): + wrapper = webnotes.model_wrapper(self.get_test_doclist()) + + # circumvent the disabled calculation call + obj = webnotes.get_obj(doc=wrapper.doc, doclist=wrapper.doclist) + obj.calculate_taxes_and_totals() + wrapper.set_doclist(obj.doclist) + + wrapper.insert() wrapper.submit() wrapper.load_from_db() dl = wrapper.doclist expected_gl_entries = { - "East Wind Inc. - %s" % abbr : [0, 1512.30], - "Cost for Goods Sold - %s" % abbr : [1250, 0], - "Shipping Charges - %s" % abbr : [100, 0], - "Excise Duty - %s" % abbr : [140, 0], - "Education Cess - %s" % abbr : [2.8, 0], - "S&H Education Cess - %s" % abbr : [1.4, 0], - "CST - %s" % abbr : [29.88, 0], - "VAT - Test - %s" % abbr : [156.25, 0], - "Discount - %s" % abbr : [0, 168.03], + "_Test Supplier - _TC": [0, 1512.30], + "_Test Account Cost for Goods Sold - _TC": [1250, 0], + "_Test Account Shipping Charges - _TC": [100, 0], + "_Test Account Excise Duty - _TC": [140, 0], + "_Test Account Education Cess - _TC": [2.8, 0], + "_Test Account S&H Education Cess - _TC": [1.4, 0], + "_Test Account CST - _TC": [29.88, 0], + "_Test Account VAT - _TC": [156.25, 0], + "_Test Account Discount - _TC": [0, 168.03], } gl_entries = webnotes.conn.sql("""select account, debit, credit from `tabGL Entry` where voucher_type = 'Purchase Invoice' and voucher_no = %s""", dl[0].name, as_dict=1) @@ -174,7 +68,46 @@ class TestPurchaseInvoice(unittest.TestCase): self.assertEqual([d.debit, d.credit], expected_gl_entries.get(d.account)) def test_purchase_invoice_calculation(self): - test_doclist = [ + wrapper = webnotes.model_wrapper(self.get_test_doclist()) + + # circumvent the disabled calculation call + obj = webnotes.get_obj(doc=wrapper.doc, doclist=wrapper.doclist) + obj.calculate_taxes_and_totals() + wrapper.set_doclist(obj.doclist) + + wrapper.insert() + wrapper.load_from_db() + + self.assertEqual(wrapper.doclist[0].net_total, 1250) + + # tax amounts + expected_values = [ + ["_Test Account Shipping Charges - _TC", 100, 1350], + ["_Test Account Customs Duty - _TC", 125, 1350], + ["_Test Account Excise Duty - _TC", 140, 1490], + ["_Test Account Education Cess - _TC", 2.8, 1492.8], + ["_Test Account S&H Education Cess - _TC", 1.4, 1494.2], + ["_Test Account CST - _TC", 29.88, 1524.08], + ["_Test Account VAT - _TC", 156.25, 1680.33], + ["_Test Account Discount - _TC", 168.03, 1512.30], + ] + + for i, tax in enumerate(wrapper.doclist.get({"parentfield": "purchase_tax_details"})): + self.assertEqual(tax.account_head, expected_values[i][0]) + self.assertEqual(tax.tax_amount, expected_values[i][1]) + self.assertEqual(tax.total, expected_values[i][2]) + # print tax.account_head, tax.tax_amount, tax.item_wise_tax_detail + + expected_values = [ + ["_Test Item Home Desktop 100", 90], + ["_Test Item Home Desktop 200", 135] + ] + for i, item in enumerate(wrapper.doclist.get({"parentfield": "entries"})): + self.assertEqual(item.item_code, expected_values[i][0]) + self.assertEqual(item.item_tax_amount, expected_values[i][1]) + + def get_test_doclist(self): + return [ # parent { "doctype": "Purchase Invoice", @@ -183,7 +116,7 @@ class TestPurchaseInvoice(unittest.TestCase): "credit_to": "_Test Supplier - _TC", "bill_no": "NA", "posting_date": "2013-02-03", - "fiscal_year": "_Test Fiscal Year", + "fiscal_year": "_Test Fiscal Year 2013", "company": "_Test Company", "currency": "INR", "conversion_rate": 1, @@ -199,7 +132,7 @@ class TestPurchaseInvoice(unittest.TestCase): "import_rate": 50, "import_amount": 500, "rate": 50, - "amount": 50, + "amount": 500, "uom": "_Test UOM", "item_tax_rate": json.dumps({"_Test Account Excise Duty - _TC": 10}), "expense_head": "_Test Account Cost for Goods Sold - _TC", @@ -313,37 +246,4 @@ class TestPurchaseInvoice(unittest.TestCase): "rate": 10, "row_id": 7 }, - ] - - wrapper = webnotes.model_wrapper(test_doclist).insert() - wrapper.load_from_db() - - # tax amounts - expected_values = [ - ["_Test Account Shipping Charges - _TC", 100, 1350], - ["_Test Account Customs Duty - _TC", 125, 1350], - ["_Test Account Excise Duty - _TC", 140, 1490], - ["_Test Account Education Cess - _TC", 2.8, 1492.8], - ["_Test Account S&H Education Cess - _TC", 1.4, 1494.2], - ["_Test Account CST - _TC", 29.88, 1524.08], - ["_Test Account VAT - _TC", 156.25, 1680.33], - ["_Test Account Discount - _TC", 168.03, 1512.30], - ] - - for i, tax in enumerate(wrapper.doclist.get({"parentfield": "purchase_tax_details"})): - self.assertEqual(tax.account_head, expected_values[i][0]) - self.assertEqual(tax.tax_amount, expected_values[i][1]) - self.assertEqual(tax.total, expected_values[i][2]) - - expected_values = [ - ["_Test Item Home Desktop 100", 90], - ["_Test Item Home Desktop 200", 135] - ] - for i, item in enumerate(wrapper.doclist.get({"parentfield": "entries"})): - self.assertEqual(item.item_code, expected_values[i][0]) - self.assertEqual(item.item_tax_amount, expected_values[i][1]) - - # self.assertEqual(dl[0].net_total, 1250) - - def tearDown(self): - webnotes.conn.rollback() \ No newline at end of file + ] \ No newline at end of file diff --git a/accounts/doctype/purchase_invoice_item/purchase_invoice_item.txt b/accounts/doctype/purchase_invoice_item/purchase_invoice_item.txt index 2891a123bf..ecd981de69 100755 --- a/accounts/doctype/purchase_invoice_item/purchase_invoice_item.txt +++ b/accounts/doctype/purchase_invoice_item/purchase_invoice_item.txt @@ -1,8 +1,8 @@ [ { - "creation": "2013-01-28 10:05:58", + "creation": "2013-01-29 20:53:00", "docstatus": 0, - "modified": "2013-01-29 16:28:04", + "modified": "2013-02-08 14:06:17", "modified_by": "Administrator", "owner": "Administrator" }, @@ -268,6 +268,20 @@ "read_only": 1, "report_hide": 1 }, + { + "doctype": "DocField", + "fieldname": "item_tax_amount", + "fieldtype": "Currency", + "hidden": 1, + "label": "Item Tax Amount", + "no_copy": 1, + "options": "Company:company:default_currency", + "print_hide": 1, + "print_width": "150px", + "read_only": 1, + "search_index": 0, + "width": "150px" + }, { "allow_on_submit": 1, "doctype": "DocField", diff --git a/accounts/utils.py b/accounts/utils.py index 9596cd4ca9..6eb2ddb7eb 100644 --- a/accounts/utils.py +++ b/accounts/utils.py @@ -21,6 +21,8 @@ from webnotes.utils import nowdate, cstr, flt from webnotes.model.doc import addchild from webnotes import msgprint, _ from webnotes.utils import formatdate +from utilities import build_filter_conditions + class FiscalYearError(webnotes.ValidationError): pass @@ -209,4 +211,26 @@ def update_against_doc(d, jv_obj): ch.against_account = cstr(jvd[0][2]) ch.is_advance = cstr(jvd[0][3]) ch.docstatus = 1 - ch.save(1) \ No newline at end of file + ch.save(1) + +def get_account_list(doctype, txt, searchfield, start, page_len, filters): + if not filters.get("group_or_ledger"): + filters["group_or_ledger"] = "Ledger" + + conditions, filter_values = build_filter_conditions(filters) + + return webnotes.conn.sql("""select name, parent_account from `tabAccount` + where docstatus < 2 %s and %s like %s order by name limit %s, %s""" % + (conditions, searchfield, "%s", "%s", "%s"), + tuple(filter_values + ["%%%s%%" % txt, start, page_len])) + +def get_cost_center_list(doctype, txt, searchfield, start, page_len, filters): + if not filters.get("group_or_ledger"): + filters["group_or_ledger"] = "Ledger" + + conditions, filter_values = build_filter_conditions(filters) + + return webnotes.conn.sql("""select name, parent_cost_center from `tabCost Center` + where docstatus < 2 %s and %s like %s order by name limit %s, %s""" % + (conditions, searchfield, "%s", "%s", "%s"), + tuple(filter_values + ["%%%s%%" % txt, start, page_len])) \ No newline at end of file diff --git a/controllers/buying_controller.py b/controllers/buying_controller.py index 511ca17fd0..df2f429a14 100644 --- a/controllers/buying_controller.py +++ b/controllers/buying_controller.py @@ -17,10 +17,12 @@ from __future__ import unicode_literals import webnotes from webnotes import _, msgprint -from webnotes.utils import flt +from webnotes.utils import flt, cint +import json from buying.utils import get_item_details from setup.utils import get_company_currency +from webnotes.model.utils import round_floats_in_doc from controllers.accounts_controller import AccountsController @@ -32,7 +34,10 @@ class BuyingController(AccountsController): if self.doc.price_list_name and self.doc.price_list_currency: self.validate_conversion_rate("price_list_currency", "plc_conversion_rate") - + + # IMPORTANT: enable this only when client side code is similar to this one + # self.calculate_taxes_and_totals() + # set total in words self.set_total_in_words() @@ -87,11 +92,246 @@ class BuyingController(AccountsController): def calculate_taxes_and_totals(self): self.doc.conversion_rate = flt(self.doc.conversion_rate) + self.item_doclist = self.doclist.get({"parentfield": self.fname}) + self.tax_doclist = self.doclist.get({"parentfield": "purchase_tax_details"}) - # self.calculate_item_values() - # self.initialize_taxes() - # self.calculate_net_total() - # self.calculate_taxes() - # self.calculate_totals() - # self.set_total_in_words() - \ No newline at end of file + self.calculate_item_values() + self.initialize_taxes() + self.calculate_net_total() + self.calculate_taxes() + self.calculate_totals() + self.calculate_outstanding_amount() + + self._cleanup() + + def calculate_item_values(self): + def _set_base(item, print_field, base_field): + """set values in base currency""" + item.fields[base_field] = flt((flt(item.fields[print_field], + self.precision.item[print_field]) * self.doc.conversion_rate), + self.precision.item[base_field]) + + for item in self.item_doclist: + round_floats_in_doc(item, self.precision.item) + + if item.discount == 100: + if not item.import_ref_rate: + item.import_ref_rate = item.import_rate + item.import_rate = 0 + else: + if item.import_ref_rate: + item.import_rate = flt(item.import_ref_rate * + (1.0 - (item.discount_rate / 100.0)), + self.precision.item.import_rate) + else: + # assume that print rate and discount are specified + item.import_ref_rate = flt(item.import_rate / + (1.0 - (item.discount_rate / 100.0)), + self.precision.item.import_ref_rate) + + item.import_amount = flt(item.import_rate * item.qty, + self.precision.item.import_amount) + + _set_base(item, "import_ref_rate", "purchase_ref_rate") + _set_base(item, "import_rate", "rate") + _set_base(item, "import_amount", "amount") + + def initialize_taxes(self): + for tax in self.tax_doclist: + # initialize totals to 0 + tax.tax_amount = tax.total = 0.0 + + # temporary fields + tax.tax_amount_for_current_item = tax.grand_total_for_current_item = 0.0 + + tax.item_wise_tax_detail = {} + + self.validate_on_previous_row(tax) + + round_floats_in_doc(tax, self.precision.tax) + + def calculate_net_total(self): + self.doc.net_total = 0 + self.doc.net_total_import = 0 + + for item in self.item_doclist: + self.doc.net_total += item.amount + self.doc.net_total_import += item.import_amount + + self.doc.net_total = flt(self.doc.net_total, self.precision.main.net_total) + self.doc.net_total_import = flt(self.doc.net_total_import, + self.precision.main.net_total_import) + + def calculate_taxes(self): + for item in self.item_doclist: + item_tax_map = self._load_item_tax_rate(item.item_tax_rate) + item.item_tax_amount = 0 + + for i, tax in enumerate(self.tax_doclist): + # tax_amount represents the amount of tax for the current step + current_tax_amount = self.get_current_tax_amount(item, tax, item_tax_map) + + self.set_item_tax_amount(item, tax, current_tax_amount) + + # case when net total is 0 but there is an actual type charge + # in this case add the actual amount to tax.tax_amount + # and tax.grand_total_for_current_item for the first such iteration + if not (current_tax_amount or self.doc.net_total or tax.tax_amount) and \ + tax.charge_type=="Actual": + zero_net_total_adjustment = flt(tax.rate, self.precision.tax.tax_amount) + current_tax_amount += zero_net_total_adjustment + + # store tax_amount for current item as it will be used for + # charge type = 'On Previous Row Amount' + tax.tax_amount_for_current_item = current_tax_amount + + # accumulate tax amount into tax.tax_amount + tax.tax_amount += tax.tax_amount_for_current_item + + if tax.category == "Valuation": + # if just for valuation, do not add the tax amount in total + # hence, setting it as 0 for further steps + current_tax_amount = 0 + else: + current_tax_amount *= tax.add_deduct_tax == "Deduct" and -1.0 or 1.0 + + # Calculate tax.total viz. grand total till that step + # note: grand_total_for_current_item contains the contribution of + # item's amount, previously applied tax and the current tax on that item + if i==0: + tax.grand_total_for_current_item = flt(item.amount + + current_tax_amount, self.precision.tax.total) + + else: + tax.grand_total_for_current_item = \ + flt(self.tax_doclist[i-1].grand_total_for_current_item + + current_tax_amount, self.precision.tax.total) + + # in tax.total, accumulate grand total of each item + tax.total += tax.grand_total_for_current_item + + # store tax_breakup for each item + # DOUBT: should valuation type amount also be stored? + tax.item_wise_tax_detail[item.item_code] = current_tax_amount + + def calculate_totals(self): + if self.tax_doclist: + self.doc.grand_total = flt(self.tax_doclist[-1].total, + self.precision.main.grand_total) + self.doc.grand_total_import = flt( + self.doc.grand_total / self.doc.conversion_rate, + self.precision.main.grand_total_import) + else: + self.doc.grand_total = flt(self.doc.net_total, + self.precision.main.grand_total) + self.doc.grand_total_print = flt( + self.doc.grand_total / self.doc.conversion_rate, + self.precision.main.grand_total_import) + + self.doc.total_tax = \ + flt(self.doc.grand_total - self.doc.net_total, + self.precision.main.total_tax) + + if self.meta.get_field("rounded_total"): + self.doc.rounded_total = round(self.doc.grand_total) + + if self.meta.get_field("rounded_total_import"): + self.doc.rounded_total_import = round(self.doc.grand_total_import) + + def calculate_outstanding_amount(self): + if self.doc.doctype == "Purchase Invoice" and self.doc.docstatus == 0: + self.doc.total_advance = flt(self.doc.total_advance, + self.precision.main.total_advance) + self.doc.outstanding_amount = flt(self.doc.grand_total - self.doc.total_advance, + self.precision.main.outstanding_amount) + + def _cleanup(self): + for tax in self.tax_doclist: + del tax.fields["grand_total_for_current_item"] + del tax.fields["tax_amount_for_current_item"] + tax.item_wise_tax_detail = json.dumps(tax.item_wise_tax_detail) + + # except in purchase invoice, rate field is purchase_rate + if self.doc.doctype != "Purchase Invoice": + for item in self.item_doclist: + item.purchase_rate = item.rate + del item.fields["rate"] + + def validate_on_previous_row(self, tax): + """ + validate if a valid row id is mentioned in case of + On Previous Row Amount and On Previous Row Total + """ + if tax.charge_type in ["On Previous Row Amount", "On Previous Row Total"] and \ + (not tax.row_id or cint(tax.row_id) >= tax.idx): + msgprint((_("Row") + " # %(idx)s [%(taxes_doctype)s]: " + \ + _("Please specify a valid") + " %(row_id_label)s") % { + "idx": tax.idx, + "taxes_doctype": tax.parenttype, + "row_id_label": self.meta.get_label("row_id", + parentfield="purchase_tax_details") + }, raise_exception=True) + + def _load_item_tax_rate(self, item_tax_rate): + if not item_tax_rate: + return {} + return json.loads(item_tax_rate) + + def get_current_tax_amount(self, item, tax, item_tax_map): + tax_rate = self._get_tax_rate(tax, item_tax_map) + + if tax.charge_type == "Actual": + # distribute the tax amount proportionally to each item row + actual = flt(tax.rate, self.precision.tax.tax_amount) + current_tax_amount = (self.doc.net_total + and ((item.amount / self.doc.net_total) * actual) + or 0) + elif tax.charge_type == "On Net Total": + current_tax_amount = (tax_rate / 100.0) * item.amount + elif tax.charge_type == "On Previous Row Amount": + current_tax_amount = (tax_rate / 100.0) * \ + self.tax_doclist[cint(tax.row_id) - 1].tax_amount_for_current_item + elif tax.charge_type == "On Previous Row Total": + current_tax_amount = (tax_rate / 100.0) * \ + self.tax_doclist[cint(tax.row_id) - 1].grand_total_for_current_item + + return flt(current_tax_amount, self.precision.tax.tax_amount) + + def _get_tax_rate(self, tax, item_tax_map): + if item_tax_map.has_key(tax.account_head): + return flt(item_tax_map.get(tax.account_head), self.precision.tax.rate) + else: + return tax.rate + + def set_item_tax_amount(self, item, tax, current_tax_amount): + """ + item_tax_amount is the total tax amount applied on that item + stored for valuation + + TODO: rename item_tax_amount to valuation_tax_amount + """ + if tax.category in ["Valuation", "Valuation and Total"] and \ + item.item_code in self.stock_items: + item.item_tax_amount += flt(current_tax_amount, + self.precision.item.item_tax_amount) + + @property + def stock_items(self): + if not hasattr(self, "_stock_items"): + item_codes = list(set(item.item_code for item in self.item_doclist)) + self._stock_items = [r[0] for r in webnotes.conn.sql("""select name + from `tabItem` where name in (%s) and is_stock_item='Yes'""" % \ + (", ".join((["%s"]*len(item_codes))),), item_codes)] + + return self._stock_items + + @property + def precision(self): + if not hasattr(self, "_precision"): + self._precision = webnotes._dict() + self._precision.main = self.meta.get_precision_map() + self._precision.item = self.meta.get_precision_map(parentfield = self.fname) + if self.meta.get_field("purchase_tax_details"): + self._precision.tax = self.meta.get_precision_map(parentfield = \ + "purchase_tax_details") + return self._precision diff --git a/hr/doctype/holiday_block_list/holiday_block_list.py b/hr/doctype/holiday_block_list/holiday_block_list.py index 87ab7052f1..a016ab8f6b 100644 --- a/hr/doctype/holiday_block_list/holiday_block_list.py +++ b/hr/doctype/holiday_block_list/holiday_block_list.py @@ -23,7 +23,7 @@ class DocType: test_records = [[{ "doctype":"Holiday Block List", "holiday_block_list_name": "_Test Holiday Block List", - "year": "_Test Fiscal Year", + "year": "_Test Fiscal Year 2013", "company": "_Test Company" }, { "doctype": "Holiday Block List Date", diff --git a/hr/doctype/holiday_block_list/holiday_block_list.txt b/hr/doctype/holiday_block_list/holiday_block_list.txt index 23b70e2ecf..d034d8fdbf 100644 --- a/hr/doctype/holiday_block_list/holiday_block_list.txt +++ b/hr/doctype/holiday_block_list/holiday_block_list.txt @@ -2,7 +2,7 @@ { "creation": "2013-02-04 15:31:29", "docstatus": 0, - "modified": "2013-02-07 08:47:25", + "modified": "2013-02-08 11:36:20", "modified_by": "Administrator", "owner": "Administrator" }, @@ -66,7 +66,7 @@ "doctype": "DocField", "fieldname": "applies_to_all_departments", "fieldtype": "Check", - "label": "Applies to all Departments" + "label": "Applies to Company" }, { "description": "Stop users from making Leave Applications on following days.", diff --git a/hr/doctype/holiday_list/holiday_list.py b/hr/doctype/holiday_list/holiday_list.py index 00ea0bad89..4c929cd8e4 100644 --- a/hr/doctype/holiday_list/holiday_list.py +++ b/hr/doctype/holiday_list/holiday_list.py @@ -93,7 +93,7 @@ class DocType: test_records = [[{ "doctype": "Holiday List", "holiday_list_name": "_Test Holiday List", - "fiscal_year": "_Test Fiscal Year" + "fiscal_year": "_Test Fiscal Year 2013" }, { "doctype": "Holiday", "parent": "_Test Holiday List", diff --git a/hr/doctype/leave_application/leave_application.py b/hr/doctype/leave_application/leave_application.py index 9c6278d902..204514789e 100755 --- a/hr/doctype/leave_application/leave_application.py +++ b/hr/doctype/leave_application/leave_application.py @@ -117,21 +117,28 @@ class DocType: self.doc.leave_balance = get_leave_balance(self.doc.employee, self.doc.leave_type, self.doc.fiscal_year)["leave_balance"] self.doc.total_leave_days = self.get_total_leave_days()["total_leave_days"] - + + if self.doc.total_leave_days == 0: + msgprint(_("Hurray! The day(s) on which you are applying for leave \ + coincide with holiday(s). You need not apply for leave."), + raise_exception=1) + if self.doc.leave_balance - self.doc.total_leave_days < 0: msgprint("There is not enough leave balance for Leave Type: %s" % \ (self.doc.leave_type,), raise_exception=1) def validate_leave_overlap(self): - for d in webnotes.conn.sql("""select name, leave_type, posting_date, from_date, to_date + for d in webnotes.conn.sql("""select name, leave_type, posting_date, + from_date, to_date from `tabLeave Application` where (from_date <= %(to_date)s and to_date >= %(from_date)s) and employee = %(employee)s - and docstatus = 1 + and docstatus < 2 + and status in ("Open", "Approved") and name != %(name)s""", self.doc.fields, as_dict = 1): - msgprint("Employee : %s has already applied for %s between %s and %s on %s. Please refer Leave Application : %s" % (self.doc.employee, cstr(d['leave_type']), formatdate(d['from_date']), formatdate(d['to_date']), formatdate(d['posting_date']), d['name']), raise_exception = 1) + msgprint("Employee : %s has already applied for %s between %s and %s on %s. Please refer Leave Application : %s" % (self.doc.employee, cstr(d['leave_type']), formatdate(d['from_date']), formatdate(d['to_date']), formatdate(d['posting_date']), d['name'], d['name']), raise_exception = 1) def validate_max_days(self): max_days = webnotes.conn.sql("select max_days_allowed from `tabLeave Type` where name = '%s'" %(self.doc.leave_type)) diff --git a/hr/doctype/leave_application/test_leave_application.py b/hr/doctype/leave_application/test_leave_application.py index 22164a7f79..74f73c2825 100644 --- a/hr/doctype/leave_application/test_leave_application.py +++ b/hr/doctype/leave_application/test_leave_application.py @@ -39,7 +39,7 @@ test_records = [ [{ "doctype": "Leave Allocation", "leave_type": "_Test Leave Type", - "fiscal_year": "_Test Fiscal Year", + "fiscal_year": "_Test Fiscal Year 2013", "employee":"_T-Employee-0001", "new_leaves_allocated": 15, "docstatus": 1 @@ -50,7 +50,7 @@ test_records = [ "from_date": "2013-05-01", "to_date": "2013-05-05", "posting_date": "2013-01-02", - "fiscal_year": "_Test Fiscal Year", + "fiscal_year": "_Test Fiscal Year 2013", "employee": "_T-Employee-0001", "company": "_Test Company" }]] diff --git a/manufacturing/doctype/bom/bom.js b/manufacturing/doctype/bom/bom.js index cdb863d0b2..4e8fbc95d1 100644 --- a/manufacturing/doctype/bom/bom.js +++ b/manufacturing/doctype/bom/bom.js @@ -175,7 +175,7 @@ var calculate_total = function(doc) { cur_frm.fields_dict['item'].get_query = function(doc) { return erpnext.queries.item({ - 'ifnull(tabItem.is_manufactured_item, "No")': 'Yes' + 'ifnull(tabItem.is_manufactured_item, "No")': 'Yes', }) } diff --git a/manufacturing/doctype/bom/bom.py b/manufacturing/doctype/bom/bom.py index b4a51cd6e7..809f36a5f2 100644 --- a/manufacturing/doctype/bom/bom.py +++ b/manufacturing/doctype/bom/bom.py @@ -87,9 +87,6 @@ class DocType: msgprint("Item_code: %s in materials tab cannot be same as FG Item", item[0]['name'], raise_exception=1) - if item and item[0]['is_asset_item'] == 'Yes': - msgprint("Item: %s is an asset item, please check", item[0]['name'], raise_exception=1) - if not item or item[0]['docstatus'] == 2: msgprint("Item %s does not exist in system" % item[0]['item_code'], raise_exception = 1) @@ -147,11 +144,11 @@ class DocType: rate = [] for wh in warehouse: r = get_incoming_rate({ - item_code: args.get("item_code"), - warehouse: wh[0], - posting_date: dt, - posting_time: time, - qty: args.get("qty") or 0 + "item_code": args.get("item_code"), + "warehouse": wh[0], + "posting_date": dt, + "posting_time": time, + "qty": args.get("qty") or 0 }) if r: rate.append(r) diff --git a/selling/utils.py b/selling/utils.py new file mode 100644 index 0000000000..21e94f7234 --- /dev/null +++ b/selling/utils.py @@ -0,0 +1,32 @@ +# ERPNext - web based ERP (http://erpnext.com) +# Copyright (C) 2012 Web Notes Technologies Pvt Ltd +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from __future__ import unicode_literals +import webnotes + +def get_customer_list(doctype, txt, searchfield, start, page_len, filters): + if webnotes.conn.get_default("cust_master_name") == "Customer Name": + fields = ["name", "customer_group", "territory"] + else: + fields = ["name", "customer_name", "customer_group", "territory"] + + return webnotes.conn.sql("""select %s from `tabCustomer` where docstatus < 2 + and (%s like %s or customer_name like %s) order by + case when name like %s then 0 else 1 end, + case when customer_name like %s then 0 else 1 end, + name, customer_name limit %s, %s""" % + (", ".join(fields), searchfield, "%s", "%s", "%s", "%s", "%s", "%s"), + ("%%%s%%" % txt, "%%%s%%" % txt, "%%%s%%" % txt, "%%%s%%" % txt, start, page_len)) \ No newline at end of file diff --git a/startup/query_handlers.py b/startup/query_handlers.py index 5e2860865f..52a2e9ebf0 100644 --- a/startup/query_handlers.py +++ b/startup/query_handlers.py @@ -1,5 +1,7 @@ from __future__ import unicode_literals standard_queries = { - "Warehouse": "stock.utils.get_warehouse_list" + "Warehouse": "stock.utils.get_warehouse_list", + "Customer": "selling.utils.get_customer_list", + } \ No newline at end of file diff --git a/startup/report_data_map.py b/startup/report_data_map.py index ff9f3e44cf..83e4b30dca 100644 --- a/startup/report_data_map.py +++ b/startup/report_data_map.py @@ -113,7 +113,7 @@ data_map = { }, }, "Purchase Request Item": { - "columns": ["name", "item_code", "warehouse", + "columns": ["item.name as name", "item_code", "warehouse", "(ifnull(qty, 0) - ifnull(ordered_qty, 0)) as qty"], "from": "`tabPurchase Request Item` item, `tabPurchase Request` main", "conditions": ["item.parent = main.name", "main.docstatus=1", "main.status != 'Stopped'", @@ -124,7 +124,7 @@ data_map = { }, }, "Purchase Order Item": { - "columns": ["name", "item_code", "warehouse", + "columns": ["item.name as name", "item_code", "warehouse", "(ifnull(qty, 0) - ifnull(received_qty, 0)) as qty"], "from": "`tabPurchase Order Item` item, `tabPurchase Order` main", "conditions": ["item.parent = main.name", "main.docstatus=1", "main.status != 'Stopped'", @@ -136,7 +136,7 @@ data_map = { }, "Sales Order Item": { - "columns": ["name", "item_code", "(ifnull(qty, 0) - ifnull(delivered_qty, 0)) as qty", + "columns": ["item.name as name", "item_code", "(ifnull(qty, 0) - ifnull(delivered_qty, 0)) as qty", "reserved_warehouse as warehouse"], "from": "`tabSales Order Item` item, `tabSales Order` main", "conditions": ["item.parent = main.name", "main.docstatus=1", "main.status != 'Stopped'", diff --git a/stock/doctype/purchase_receipt_item/purchase_receipt_item.txt b/stock/doctype/purchase_receipt_item/purchase_receipt_item.txt index 2e5b219baa..fd73c879ff 100755 --- a/stock/doctype/purchase_receipt_item/purchase_receipt_item.txt +++ b/stock/doctype/purchase_receipt_item/purchase_receipt_item.txt @@ -1,8 +1,8 @@ [ { - "creation": "2013-01-30 12:49:56", + "creation": "2013-02-07 08:28:23", "docstatus": 0, - "modified": "2013-02-07 10:50:00", + "modified": "2013-02-08 14:06:15", "modified_by": "Administrator", "owner": "Administrator" }, @@ -407,7 +407,7 @@ "print_width": "150px", "read_only": 1, "reqd": 0, - "search_index": 1, + "search_index": 0, "width": "150px" }, { diff --git a/stock/page/stock_ledger/stock_ledger.js b/stock/page/stock_ledger/stock_ledger.js index 82230e4cef..6d945bb5f2 100644 --- a/stock/page/stock_ledger/stock_ledger.js +++ b/stock/page/stock_ledger/stock_ledger.js @@ -114,8 +114,7 @@ erpnext.StockLedger = erpnext.StockGridReport.extend({ }, toggle_enable_brand: function() { - if(this.filter_inputs.item_code.val() == - this.filter_inputs.item_code.get(0).opts.default_value) { + if(!this.filter_inputs.item_code.val()) { this.filter_inputs.brand.removeAttr("disabled"); } else { this.filter_inputs.brand diff --git a/stock/page/stock_level/stock_level.js b/stock/page/stock_level/stock_level.js index df63d9b081..3455e2b48a 100644 --- a/stock/page/stock_level/stock_level.js +++ b/stock/page/stock_level/stock_level.js @@ -127,8 +127,7 @@ erpnext.StockLevel = erpnext.StockGridReport.extend({ }, toggle_enable_brand: function() { - if(this.filter_inputs.item_code.val() == - this.filter_inputs.item_code.get(0).opts.default_value) { + if(!this.filter_inputs.item_code.val()) { this.filter_inputs.brand.removeAttr("disabled"); } else { this.filter_inputs.brand diff --git a/stock/utils.py b/stock/utils.py index 3b98cf0683..62c2a1794f 100644 --- a/stock/utils.py +++ b/stock/utils.py @@ -148,7 +148,7 @@ def get_valid_serial_nos(sr_nos, qty=0, item_code=''): return valid_serial_nos -def get_warehouse_list(doctype, txt, searchfield, start, page_len, args): +def get_warehouse_list(doctype, txt, searchfield, start, page_len, filters): """used in search queries""" wlist = [] for w in webnotes.conn.sql_list("""select name from tabWarehouse diff --git a/utilities/__init__.py b/utilities/__init__.py index 7c44ec31dd..079b03aee0 100644 --- a/utilities/__init__.py +++ b/utilities/__init__.py @@ -58,3 +58,12 @@ def get_report_list(): def validate_status(status, options): if status not in options: msgprint(_("Status must be one of ") + comma_or(options), raise_exception=True) + +def build_filter_conditions(filters): + conditions, filter_values = [], [] + for key in filters: + conditions.append('`' + key + '` = %s') + filter_values.append(filters[key]) + + conditions = conditions and " and " + " and ".join(conditions) or "" + return conditions, filter_values \ No newline at end of file