diff --git a/accounts/Print Format/Sales Invoice Classic/Sales Invoice Classic.txt b/accounts/Print Format/Sales Invoice Classic/Sales Invoice Classic.txt index d72c847850..5aefa812f8 100644 --- a/accounts/Print Format/Sales Invoice Classic/Sales Invoice Classic.txt +++ b/accounts/Print Format/Sales Invoice Classic/Sales Invoice Classic.txt @@ -1,17 +1,18 @@ [ { - "creation": "2013-02-01 14:16:04", + "creation": "2013-04-19 13:30:27", "docstatus": 0, - "modified": "2013-02-26 11:11:20", + "modified": "2013-05-28 17:19:38", "modified_by": "Administrator", "owner": "Administrator" }, { "doc_type": "Sales Invoice", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n\n", "module": "Accounts", "name": "__common__", + "print_format_type": "Client", "standard": "Yes" }, { diff --git a/accounts/Print Format/Sales Invoice Modern/Sales Invoice Modern.txt b/accounts/Print Format/Sales Invoice Modern/Sales Invoice Modern.txt index 97c50fd6df..2f6251c07b 100644 --- a/accounts/Print Format/Sales Invoice Modern/Sales Invoice Modern.txt +++ b/accounts/Print Format/Sales Invoice Modern/Sales Invoice Modern.txt @@ -1,17 +1,18 @@ [ { - "creation": "2012-05-15 18:39:02", + "creation": "2013-04-19 13:30:27", "docstatus": 0, - "modified": "2013-02-26 11:10:58", + "modified": "2013-05-28 17:19:52", "modified_by": "Administrator", "owner": "Administrator" }, { "doc_type": "Sales Invoice", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n\n", "module": "Accounts", "name": "__common__", + "print_format_type": "Client", "standard": "Yes" }, { diff --git a/accounts/Print Format/Sales Invoice Spartan/Sales Invoice Spartan.txt b/accounts/Print Format/Sales Invoice Spartan/Sales Invoice Spartan.txt index 6be83d45d1..b00b3d85f5 100644 --- a/accounts/Print Format/Sales Invoice Spartan/Sales Invoice Spartan.txt +++ b/accounts/Print Format/Sales Invoice Spartan/Sales Invoice Spartan.txt @@ -1,17 +1,18 @@ [ { - "creation": "2012-05-15 18:39:02", + "creation": "2013-04-19 13:30:27", "docstatus": 0, - "modified": "2013-02-26 11:11:40", + "modified": "2013-05-28 17:19:22", "modified_by": "Administrator", "owner": "Administrator" }, { "doc_type": "Sales Invoice", "doctype": "Print Format", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n\n", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n
\n\t\n\t\n
\n\n", "module": "Accounts", "name": "__common__", + "print_format_type": "Client", "standard": "Yes" }, { diff --git a/accounts/README.md b/accounts/README.md new file mode 100644 index 0000000000..10a99e5a62 --- /dev/null +++ b/accounts/README.md @@ -0,0 +1,13 @@ +Accounts module contains masters and transactions to manage a traditional +double entry accounting system. + +Accounting heads are called "Accounts" and they can be groups in a tree like +"Chart of Accounts" + +Entries are: + +- Journal Vouchers +- Sales Invoice (Itemised) +- Purchase Invoice (Itemised) + +All accounting entries are stored in the `General Ledger` \ No newline at end of file diff --git a/accounts/doctype/account/README.md b/accounts/doctype/account/README.md new file mode 100644 index 0000000000..44cdf50d7c --- /dev/null +++ b/accounts/doctype/account/README.md @@ -0,0 +1,11 @@ +Account DocType represents an Accounting Ledger or Group. + +Follows a composite model. `parent_account` represents the parent of an Account except +a root account. +There can be only 4 root accounts: Income, Expense, Assets and Liabilities in a company. + +Other features: + +- It can be of type Debit or Credit. +- A Group is a collection of groups or ledgers + diff --git a/accounts/doctype/account/account.py b/accounts/doctype/account/account.py index bdc26e46ce..45b02a8d15 100644 --- a/accounts/doctype/account/account.py +++ b/accounts/doctype/account/account.py @@ -29,6 +29,7 @@ class DocType: self.nsm_parent_field = 'parent_account' def autoname(self): + """Append abbreviation to company on naming""" self.doc.name = self.doc.account_name.strip() + ' - ' + \ webnotes.conn.get_value("Company", self.doc.company, "abbr") @@ -37,6 +38,7 @@ class DocType: return {'address': address} def validate_master_name(self): + """Remind to add master name""" if (self.doc.master_type == 'Customer' or self.doc.master_type == 'Supplier') \ and not self.doc.master_name: msgprint("Message: Please enter Master Name once the account is created.") @@ -62,6 +64,7 @@ class DocType: self.doc.debit_or_credit = par[0][3] def validate_max_root_accounts(self): + """Raise exception if there are more than 4 root accounts""" if webnotes.conn.sql("""select count(*) from tabAccount where company=%s and ifnull(parent_account,'')='' and docstatus != 2""", self.doc.company)[0][0] > 4: @@ -69,7 +72,6 @@ class DocType: raise_exception=1) def validate_duplicate_account(self): - if self.doc.fields.get('__islocal') or not self.doc.name: company_abbr = webnotes.conn.get_value("Company", self.doc.company, "abbr") if sql("""select name from tabAccount where name=%s""", @@ -134,6 +136,7 @@ class DocType: self.doc.parent_account = '' def update_nsm_model(self): + """update lft, rgt indices for nested set model""" import webnotes import webnotes.utils.nestedset webnotes.utils.nestedset.update_nsm(self) diff --git a/accounts/doctype/pos_setting/pos_setting.txt b/accounts/doctype/pos_setting/pos_setting.txt index 788af9ee06..accb29e351 100755 --- a/accounts/doctype/pos_setting/pos_setting.txt +++ b/accounts/doctype/pos_setting/pos_setting.txt @@ -1,8 +1,8 @@ [ { - "creation": "2013-05-09 13:16:11", + "creation": "2013-05-24 12:15:51", "docstatus": 0, - "modified": "2013-05-23 12:52:09", + "modified": "2013-05-30 12:09:39", "modified_by": "Administrator", "owner": "Administrator" }, @@ -18,8 +18,7 @@ "parent": "POS Setting", "parentfield": "fields", "parenttype": "DocType", - "permlevel": 0, - "read_only": 0 + "permlevel": 0 }, { "doctype": "DocPerm", @@ -44,7 +43,8 @@ "label": "User", "oldfieldname": "user", "oldfieldtype": "Link", - "options": "Profile" + "options": "Profile", + "read_only": 0 }, { "doctype": "DocField", @@ -54,6 +54,7 @@ "oldfieldname": "territory", "oldfieldtype": "Link", "options": "Territory", + "read_only": 0, "reqd": 1 }, { @@ -64,6 +65,7 @@ "no_copy": 1, "oldfieldname": "naming_series", "oldfieldtype": "Select", + "read_only": 0, "reqd": 1 }, { @@ -74,6 +76,7 @@ "oldfieldname": "currency", "oldfieldtype": "Select", "options": "Currency", + "read_only": 0, "reqd": 1 }, { @@ -84,6 +87,7 @@ "label": "Conversion Rate", "oldfieldname": "conversion_rate", "oldfieldtype": "Currency", + "read_only": 0, "reqd": 1 }, { @@ -94,6 +98,7 @@ "oldfieldname": "price_list_name", "oldfieldtype": "Select", "options": "link:Price List", + "read_only": 0, "reqd": 1 }, { @@ -105,13 +110,24 @@ "oldfieldname": "company", "oldfieldtype": "Link", "options": "Company", + "read_only": 0, "reqd": 1 }, { "doctype": "DocField", "fieldname": "column_break0", "fieldtype": "Column Break", - "oldfieldtype": "Column Break" + "oldfieldtype": "Column Break", + "read_only": 0 + }, + { + "default": "1", + "description": "Create Stock Ledger Entries when you submit a Sales Invoice", + "doctype": "DocField", + "fieldname": "update_stock", + "fieldtype": "Check", + "label": "Update Stock", + "reqd": 0 }, { "doctype": "DocField", @@ -121,6 +137,7 @@ "oldfieldname": "customer_account", "oldfieldtype": "Link", "options": "Account", + "read_only": 0, "reqd": 0 }, { @@ -131,6 +148,7 @@ "oldfieldname": "cash_bank_account", "oldfieldtype": "Link", "options": "Account", + "read_only": 0, "reqd": 1 }, { @@ -141,6 +159,7 @@ "oldfieldname": "income_account", "oldfieldtype": "Link", "options": "Account", + "read_only": 0, "reqd": 1 }, { @@ -152,6 +171,7 @@ "label": "Expense Account", "options": "Account", "print_hide": 1, + "read_only": 0, "reqd": 0 }, { @@ -162,6 +182,7 @@ "oldfieldname": "warehouse", "oldfieldtype": "Link", "options": "Warehouse", + "read_only": 0, "reqd": 1 }, { @@ -172,6 +193,7 @@ "oldfieldname": "cost_center", "oldfieldtype": "Link", "options": "Cost Center", + "read_only": 0, "reqd": 1 }, { @@ -181,7 +203,8 @@ "label": "Charge", "oldfieldname": "charge", "oldfieldtype": "Link", - "options": "Sales Taxes and Charges Master" + "options": "Sales Taxes and Charges Master", + "read_only": 0 }, { "doctype": "DocField", @@ -191,7 +214,8 @@ "oldfieldname": "letter_head", "oldfieldtype": "Select", "options": "link:Letter Head", - "print_hide": 1 + "print_hide": 1, + "read_only": 0 }, { "doctype": "DocField", @@ -200,7 +224,8 @@ "label": "Terms and Conditions", "oldfieldname": "tc_name", "oldfieldtype": "Link", - "options": "Terms and Conditions" + "options": "Terms and Conditions", + "read_only": 0 }, { "doctype": "DocField", @@ -210,17 +235,10 @@ "label": "Select Print Heading", "oldfieldname": "select_print_heading", "oldfieldtype": "Select", - "options": "link:Print Heading" + "options": "link:Print Heading", + "read_only": 0 }, { - "cancel": 1, - "create": 1, - "doctype": "DocPerm", - "role": "System Manager", - "write": 1 - }, - { - "cancel": 1, "create": 1, "doctype": "DocPerm", "role": "Accounts Manager", diff --git a/accounts/doctype/purchase_invoice/purchase_invoice.js b/accounts/doctype/purchase_invoice/purchase_invoice.js index 92f17487bc..c6a787e50a 100644 --- a/accounts/doctype/purchase_invoice/purchase_invoice.js +++ b/accounts/doctype/purchase_invoice/purchase_invoice.js @@ -17,86 +17,56 @@ cur_frm.cscript.tname = "Purchase Invoice Item"; cur_frm.cscript.fname = "entries"; cur_frm.cscript.other_fname = "purchase_tax_details"; + +wn.provide("erpnext.accounts"); wn.require('app/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js'); wn.require('app/buying/doctype/purchase_common/purchase_common.js'); -erpnext.buying.PurchaseInvoiceController = erpnext.buying.BuyingController.extend({ +erpnext.accounts.PurchaseInvoiceController = erpnext.buying.BuyingController.extend({ + onload: function() { + this._super(); + + if(!this.frm.doc.__islocal) { + // show credit_to in print format + if(!this.frm.doc.supplier && this.frm.doc.credit_to) { + this.frm.set_df_property("credit_to", "print_hide", 0); + } + } + }, + refresh: function(doc) { this._super(); // Show / Hide button if(doc.docstatus==1 && doc.outstanding_amount > 0) - cur_frm.add_custom_button('Make Payment Entry', cur_frm.cscript.make_bank_voucher); + this.frm.add_custom_button('Make Payment Entry', this.make_bank_voucher); if(doc.docstatus==1) { - cur_frm.add_custom_button('View Ledger', cur_frm.cscript.view_ledger_entry); + this.frm.add_custom_button('View Ledger', this.view_ledger_entry); } - cur_frm.cscript.is_opening(doc); + this.is_opening(doc); }, - onload_post_render: function(doc, dt, dn) { - var me = this; - var callback1 = function(doc, dt, dn) { - var callback2 = function(doc, dt, dn) { - if(doc.__islocal && doc.supplier) cur_frm.cscript.supplier(doc, dt, dn); - } - me.update_item_details(doc, dt, dn, callback2); - } - - // TODO: improve this - if(this.frm.doc.__islocal) { - if (this.frm.fields_dict.price_list_name && this.frm.doc.price_list_name) { - this.price_list_name(callback1); - } else { - callback1(doc, dt, dn); - } - } + + credit_to: function() { + this.supplier(); + }, + + write_off_amount: function() { + this.calculate_outstanding_amount(); + this.frm.refresh_fields(); + }, + + allocated_amount: function() { + this.calculate_total_advance("Purchase Invoice", "advance_allocation_details"); + this.frm.refresh_fields(); } }); -var new_cscript = new erpnext.buying.PurchaseInvoiceController({frm: cur_frm}); - // for backward compatibility: combine new and previous states -$.extend(cur_frm.cscript, new_cscript); +$.extend(cur_frm.cscript, new erpnext.accounts.PurchaseInvoiceController({frm: cur_frm})); -cur_frm.cscript.onload = function(doc,dt,dn) { - if(!doc.posting_date) set_multiple(dt,dn,{posting_date:get_today()}); -} - -cur_frm.cscript.supplier = function(doc,dt,dn) { - var callback = function(r,rt) { - var doc = locals[cur_frm.doctype][cur_frm.docname]; - get_server_fields('get_credit_to','','',doc, dt, dn, 0, callback2); - } - - var callback2 = function(r,rt){ - var doc = locals[cur_frm.doctype][cur_frm.docname]; - var el = getchildren('Purchase Invoice Item',doc.name,'entries'); - for(var i in el){ - if(el[i].item_code && (!el[i].expense_head || !el[i].cost_center)){ - args = { - item_code: el[i].item_code, - expense_head: el[i].expense_head, - cost_center: el[i].cost_center - }; - get_server_fields('get_default_values', JSON.stringify(args), 'entries', doc, el[i].doctype, el[i].name, 1); - } - } - cur_frm.cscript.calc_amount(doc, 1); - } - - if (doc.supplier) { - get_server_fields('get_default_supplier_address', - JSON.stringify({ supplier: doc.supplier }),'', doc, dt, dn, 1, function(doc, dt, dn) { - cur_frm.refresh(); - callback(doc, dt, dn); - }); - unhide_field(['supplier_address','contact_person']); - } - -} - cur_frm.cscript.supplier_address = cur_frm.cscript.contact_person = function(doc,dt,dn) { if(doc.supplier) get_server_fields('get_supplier_address', JSON.stringify({supplier: doc.supplier, address: doc.supplier_address, contact: doc.contact_person}),'', doc, dt, dn, 1); } @@ -112,23 +82,6 @@ cur_frm.fields_dict.contact_person.on_new = function(dn) { } -cur_frm.cscript.credit_to = function(doc,dt,dn) { - - var callback = function(doc, dt, dn) { - var doc = locals[doc.doctype][doc.name]; - if(doc.supplier) { - get_server_fields('get_default_supplier_address', - JSON.stringify({ supplier: doc.supplier }), '', doc, dt, dn, 1, function() { - cur_frm.refresh(); - }); - unhide_field(['supplier_address','contact_person']); - } - cur_frm.refresh(); - } - - get_server_fields('get_cust', '', '', doc, dt, dn, 1, callback); -} - cur_frm.fields_dict['entries'].grid.onrowadd = function(doc, cdt, cdn){ cl = getchildren('Purchase Invoice Item', doc.name, cur_frm.cscript.fname, doc.doctype); @@ -152,17 +105,6 @@ cur_frm.cscript.is_opening = function(doc, dt, dn) { if (doc.is_opening == 'Yes') unhide_field('aging_date'); } -cur_frm.cscript.write_off_amount = function(doc) { - doc.total_amount_to_pay = flt(doc.grand_total) - flt(doc.write_off_amount); - doc.outstanding_amount = flt(doc.total_amount_to_pay) - flt(doc.total_advance); - refresh_many(['outstanding_amount', 'total_amount_to_pay']); -} - -cur_frm.cscript.recalculate = function(doc, cdt, cdn) { - cur_frm.cscript.calculate_tax(doc,cdt,cdn); - calc_total_advance(doc,cdt,cdn); -} - cur_frm.cscript.get_items = function(doc, dt, dn) { var callback = function(r,rt) { unhide_field(['supplier_address', 'contact_person']); @@ -171,11 +113,6 @@ cur_frm.cscript.get_items = function(doc, dt, dn) { $c_obj(make_doclist(dt,dn),'pull_details','',callback); } -cur_frm.cscript.allocated_amount = function(doc,cdt,cdn) { - calc_total_advance(doc, cdt, cdn); -} - - cur_frm.cscript.make_bank_voucher = function() { wn.call({ method: "accounts.doctype.journal_voucher.journal_voucher.get_default_bank_cash_account", @@ -261,21 +198,6 @@ cur_frm.cscript.cost_center = function(doc, cdt, cdn){ refresh_field('entries'); } -calc_total_advance = function(doc,cdt,cdn) { - var doc = locals[doc.doctype][doc.name]; - var el = getchildren('Purchase Invoice Advance',doc.name,'advance_allocation_details') - var total_advance = 0; - for(var i in el) { - if (! el[i].allocated_amount == 0) { - total_advance += flt(el[i].allocated_amount); - } - } - doc.total_amount_to_pay = flt(doc.grand_total) - flt(doc.write_off_amount); - doc.total_advance = flt(total_advance); - doc.outstanding_amount = flt(doc.total_amount_to_pay) - flt(total_advance); - refresh_many(['total_advance','outstanding_amount', 'total_amount_to_pay']); -} - cur_frm.cscript.make_jv = function(doc, dt, dn, bank_account) { var jv = wn.model.make_new_doc_and_get_name('Journal Voucher'); jv = locals['Journal Voucher'][jv]; diff --git a/accounts/doctype/purchase_invoice/purchase_invoice.py b/accounts/doctype/purchase_invoice/purchase_invoice.py index 95b56dc4ff..59e66b57db 100644 --- a/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -91,6 +91,11 @@ class DocType(BuyingController): msgprint("%s does not have an Account Head in %s. You must first create it from the Supplier Master" % (self.doc.supplier, self.doc.company)) return ret + def set_supplier_defaults(self): + self.doc.fields.update(self.get_cust()) + self.doc.fields.update(self.get_credit_to()) + super(DocType, self).set_supplier_defaults() + def get_cust(self): ret = {} if self.doc.credit_to: @@ -100,31 +105,6 @@ class DocType(BuyingController): return ret - def get_default_values(self, args): - if isinstance(args, basestring): - import json - args = json.loads(args) - - out = webnotes._dict() - - item = webnotes.conn.sql("""select name, purchase_account, cost_center, - is_stock_item from `tabItem` where name=%s""", args.get("item_code"), as_dict=1) - - if item and item[0]: - item = item[0] - - if cint(webnotes.defaults.get_global_default("auto_inventory_accounting")) and \ - item.is_stock_item == "Yes": - # unset expense head for stock item and auto inventory accounting - out.expense_head = out.cost_center = None - else: - if not args.get("expense_head"): - out.expense_head = item.purchase_account - if not args.get("cost_center"): - out.cost_center = item.cost_center - - return out - def pull_details(self): if self.doc.purchase_receipt_main: self.validate_duplicate_docname('purchase_receipt') @@ -466,9 +446,9 @@ class DocType(BuyingController): # expense will be booked in sales invoice stock_item_and_auto_inventory_accounting = True - valuation_amt = (flt(item.amount, self.precision.item.amount) + - flt(item.item_tax_amount, self.precision.item.item_tax_amount) + - flt(item.rm_supp_cost, self.precision.item.rm_supp_cost)) + valuation_amt = (flt(item.amount, self.precision("amount", item)) + + flt(item.item_tax_amount, self.precision("item_tax_amount", item)) + + flt(item.rm_supp_cost, self.precision("rm_supp_cost", item))) gl_entries.append( self.get_gl_dict({ diff --git a/accounts/doctype/purchase_invoice/purchase_invoice.txt b/accounts/doctype/purchase_invoice/purchase_invoice.txt index 283c612371..4647fd235d 100755 --- a/accounts/doctype/purchase_invoice/purchase_invoice.txt +++ b/accounts/doctype/purchase_invoice/purchase_invoice.txt @@ -1,8 +1,8 @@ [ { - "creation": "2013-05-07 13:50:30", + "creation": "2013-05-21 16:16:39", "docstatus": 0, - "modified": "2013-05-13 11:12:56", + "modified": "2013-05-28 12:18:35", "modified_by": "Administrator", "owner": "Administrator" }, @@ -89,10 +89,11 @@ "read_only": 0 }, { + "depends_on": "supplier", "doctype": "DocField", "fieldname": "supplier_name", "fieldtype": "Text", - "hidden": 1, + "hidden": 0, "in_list_view": 1, "label": "Name", "oldfieldname": "supplier_name", @@ -100,34 +101,38 @@ "read_only": 1 }, { + "depends_on": "supplier", "doctype": "DocField", "fieldname": "address_display", "fieldtype": "Small Text", - "hidden": 1, + "hidden": 0, "label": "Address", "read_only": 1 }, { + "depends_on": "supplier", "doctype": "DocField", "fieldname": "contact_display", "fieldtype": "Small Text", - "hidden": 1, + "hidden": 0, "label": "Contact", "read_only": 1 }, { + "depends_on": "supplier", "doctype": "DocField", "fieldname": "contact_mobile", "fieldtype": "Text", - "hidden": 1, + "hidden": 0, "label": "Mobile No", "read_only": 1 }, { + "depends_on": "supplier", "doctype": "DocField", "fieldname": "contact_email", "fieldtype": "Text", - "hidden": 1, + "hidden": 0, "label": "Contact Email", "print_hide": 1, "read_only": 1 @@ -392,6 +397,7 @@ "read_only": 1 }, { + "depends_on": "supplier", "doctype": "DocField", "fieldname": "contact_section", "fieldtype": "Section Break", @@ -399,7 +405,6 @@ "read_only": 0 }, { - "depends_on": "eval:doc.supplier", "doctype": "DocField", "fieldname": "supplier_address", "fieldtype": "Link", @@ -415,7 +420,6 @@ "width": "50%" }, { - "depends_on": "eval:doc.supplier", "doctype": "DocField", "fieldname": "contact_person", "fieldtype": "Link", diff --git a/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/accounts/doctype/purchase_invoice/test_purchase_invoice.py index a70c932d9b..2ae569b7eb 100644 --- a/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -24,6 +24,7 @@ from webnotes.utils import cint import webnotes.defaults test_dependencies = ["Item", "Cost Center"] +test_ignore = ["Serial No"] class TestPurchaseInvoice(unittest.TestCase): def test_gl_entries_without_auto_inventory_accounting(self): @@ -119,25 +120,6 @@ class TestPurchaseInvoice(unittest.TestCase): 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]) - expected_values = [ ["_Test Item Home Desktop 100", 90, 59], ["_Test Item Home Desktop 200", 135, 177] @@ -147,13 +129,41 @@ class TestPurchaseInvoice(unittest.TestCase): self.assertEqual(item.item_tax_amount, expected_values[i][1]) self.assertEqual(item.valuation_rate, expected_values[i][2]) + 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]) + def test_purchase_invoice_with_subcontracted_item(self): wrapper = webnotes.bean(copy=test_records[0]) wrapper.doclist[1].item_code = "_Test FG Item" wrapper.run_method("calculate_taxes_and_totals") wrapper.insert() wrapper.load_from_db() - + + expected_values = [ + ["_Test FG Item", 90, 7059], + ["_Test Item Home Desktop 200", 135, 177] + ] + 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(item.valuation_rate, expected_values[i][2]) + self.assertEqual(wrapper.doclist[0].net_total, 1250) # tax amounts @@ -172,15 +182,6 @@ class TestPurchaseInvoice(unittest.TestCase): 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 FG Item", 90, 7059], - ["_Test Item Home Desktop 200", 135, 177] - ] - 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(item.valuation_rate, expected_values[i][2]) def test_purchase_invoice_with_advance(self): from accounts.doctype.journal_voucher.test_journal_voucher \ diff --git a/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.txt b/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.txt index 619aed1954..d6d2a92b7a 100644 --- a/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.txt +++ b/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.txt @@ -1,8 +1,8 @@ [ { - "creation": "2013-04-19 11:00:06", + "creation": "2013-05-21 16:16:04", "docstatus": 0, - "modified": "2013-05-07 11:23:56", + "modified": "2013-05-28 12:02:02", "modified_by": "Administrator", "owner": "Administrator" }, @@ -101,7 +101,7 @@ "oldfieldname": "tax_amount", "oldfieldtype": "Currency", "options": "Company:company:default_currency", - "read_only": 0, + "read_only": 1, "reqd": 0 }, { @@ -159,35 +159,5 @@ "print_hide": 1, "read_only": 0, "search_index": 0 - }, - { - "description": "Cheating Field\nPlease do not delete ", - "doctype": "DocField", - "fieldname": "total_tax_amount", - "fieldtype": "Currency", - "hidden": 1, - "label": "Total +Tax", - "no_copy": 1, - "oldfieldname": "total_tax_amount", - "oldfieldtype": "Currency", - "options": "Company:company:default_currency", - "print_hide": 1, - "read_only": 0, - "report_hide": 1 - }, - { - "description": "Cheating Field\nPlease do not delete ", - "doctype": "DocField", - "fieldname": "total_amount", - "fieldtype": "Currency", - "hidden": 1, - "label": "Tax Amount", - "no_copy": 1, - "oldfieldname": "total_amount", - "oldfieldtype": "Currency", - "options": "Company:company:default_currency", - "print_hide": 1, - "read_only": 0, - "report_hide": 1 } ] \ No newline at end of file diff --git a/accounts/doctype/sales_invoice/sales_invoice.js b/accounts/doctype/sales_invoice/sales_invoice.js index be6ec3d001..f776db57c2 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.js +++ b/accounts/doctype/sales_invoice/sales_invoice.js @@ -22,52 +22,90 @@ cur_frm.cscript.sales_team_fname = "sales_team"; // print heading cur_frm.pformat.print_heading = 'Invoice'; -wn.require('app/selling/doctype/sales_common/sales_common.js'); wn.require('app/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js'); wn.require('app/utilities/doctype/sms_control/sms_control.js'); +wn.require('app/selling/doctype/sales_common/sales_common.js'); -// On Load -// ------- -cur_frm.cscript.onload = function(doc,dt,dn) { - cur_frm.cscript.manage_rounded_total(); - if(!doc.customer && doc.debit_to) wn.meta.get_docfield(dt, 'debit_to', dn).print_hide = 0; - if (doc.__islocal) { - if(!doc.due_date) set_multiple(dt,dn,{due_date:get_today()}); - if(!doc.posting_date) set_multiple(dt,dn,{posting_date:get_today()}); - if(!doc.currency && sys_defaults.currency) set_multiple(dt,dn,{currency:sys_defaults.currency}); - if(!doc.price_list_currency) set_multiple(dt, dn, {price_list_currency: doc.currency, plc_conversion_rate: 1}); - - } -} - -cur_frm.cscript.onload_post_render = function(doc, dt, dn) { - var callback = function(doc, dt, dn) { - // called from mapper, update the account names for items and customer - var callback2 = function(doc, dt, dn) { - if(doc.customer && doc.__islocal) { - $c_obj(make_doclist(doc.doctype,doc.name), - 'load_default_accounts','', - function(r,rt) { - refresh_field('entries'); - cur_frm.cscript.customer(doc,dt,dn,onload=true); - } - ); +wn.provide("erpnext.accounts"); +erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.extend({ + onload: function() { + this._super(); + + if(!this.frm.doc.__islocal) { + // show debit_to in print format + if(!this.frm.doc.customer && this.frm.doc.debit_to) { + this.frm.set_df_property("debit_to", "print_hide", 0); } } - // defined in sales_common.js - var callback1 = function(doc, dt, dn) { - //for previously created sales invoice, set required field related to pos - cur_frm.cscript.update_item_details(doc, dt, dn, callback2); + }, + + refresh: function(doc, dt, dn) { + this._super(); + + cur_frm.cscript.is_opening(doc, dt, dn); + + if(doc.docstatus==1) { + cur_frm.add_custom_button('View Ledger', cur_frm.cscript.view_ledger_entry); + cur_frm.add_custom_button('Send SMS', cur_frm.cscript.send_sms); + + if(doc.is_pos==1 && doc.update_stock!=1) + cur_frm.add_custom_button('Make Delivery', cur_frm.cscript['Make Delivery Note']); + + if(doc.outstanding_amount!=0) + cur_frm.add_custom_button('Make Payment Entry', cur_frm.cscript.make_bank_voucher); + } + cur_frm.cscript.hide_fields(doc, dt, dn); + }, + + is_pos: function() { + if(cint(this.frm.doc.is_pos)) { + if(!this.frm.doc.company) { + this.frm.set_value("is_pos", 0); + msgprint(wn._("Please specify Company to proceed")); + } else { + var me = this; + this.frm.call({ + doc: me.frm.doc, + method: "set_missing_values", + }); + } } - if(doc.is_pos ==1) cur_frm.cscript.is_pos(doc, dt, dn,callback1); - else cur_frm.cscript.update_item_details(doc, dt, dn, callback2); - } - - cur_frm.cscript.hide_price_list_currency(doc, dt, dn, callback); - -} + // TODO toggle display of fields + }, + + debit_to: function() { + this.customer(); + }, + + allocated_amount: function() { + this.calculate_total_advance("Sales Invoice", "advance_adjustment_details"); + this.frm.refresh_fields(); + }, + + write_off_outstanding_amount_automatically: function() { + if(cint(this.frm.doc.write_off_outstanding_amount_automatically)) { + wn.model.round_floats_in(this.frm.doc, ["grand_total", "paid_amount"]); + // this will make outstanding amount 0 + this.frm.set_value("write_off_amount", + flt(this.frm.doc.grand_total - this.frm.doc.paid_amount), precision("write_off_amount")); + } + + this.frm.runclientscript("write_off_amount"); + }, + + write_off_amount: function() { + this.calculate_outstanding_amount(); + this.frm.refresh_fields(); + }, + + paid_amount: function() { + this.write_off_outstanding_amount_automatically(); + }, +}); +// for backward compatibility: combine new and previous states +$.extend(cur_frm.cscript, new erpnext.accounts.SalesInvoiceController({frm: cur_frm})); // Hide Fields // ------------ @@ -87,15 +125,12 @@ cur_frm.cscript.hide_fields = function(doc, cdt, cdn) { hide_field(par_flds); unhide_field('payments_section'); for(f in item_flds_normal) cur_frm.fields_dict['entries'].grid.set_column_disp(item_flds_normal[f], false); - for(f in item_flds_pos) cur_frm.fields_dict['entries'].grid.set_column_disp(item_flds_pos[f], (doc.update_stock==1?true:false)); } else { hide_field('payments_section'); unhide_field(par_flds); for(f in item_flds_normal) cur_frm.fields_dict['entries'].grid.set_column_disp(item_flds_normal[f], true); - for(f in item_flds_pos) cur_frm.fields_dict['entries'].grid.set_column_disp(item_flds_pos[f], false); } - - cur_frm.toggle_display("contact_section", doc.customer); + for(f in item_flds_pos) cur_frm.fields_dict['entries'].grid.set_column_disp(item_flds_pos[f], (cint(doc.update_stock)==1?true:false)); // India related fields var cp = wn.control_panel; @@ -104,50 +139,6 @@ cur_frm.cscript.hide_fields = function(doc, cdt, cdn) { } -// Refresh -// ------- -cur_frm.cscript.refresh = function(doc, dt, dn) { - cur_frm.cscript.is_opening(doc, dt, dn); - erpnext.hide_naming_series(); - - // Show / Hide button - cur_frm.clear_custom_buttons(); - if (!cur_frm.cscript.is_onload) cur_frm.cscript.hide_price_list_currency(doc, dt, dn); - - if(doc.docstatus==1) { - cur_frm.add_custom_button('View Ledger', cur_frm.cscript.view_ledger_entry); - cur_frm.add_custom_button('Send SMS', cur_frm.cscript.send_sms); - - if(doc.is_pos==1 && doc.update_stock!=1) - cur_frm.add_custom_button('Make Delivery', cur_frm.cscript['Make Delivery Note']); - - if(doc.outstanding_amount!=0) - cur_frm.add_custom_button('Make Payment Entry', cur_frm.cscript.make_bank_voucher); - } - cur_frm.cscript.hide_fields(doc, dt, dn); - -} - -//fetch retail transaction related fields -//-------------------------------------------- -cur_frm.cscript.is_pos = function(doc,dt,dn,callback){ - cur_frm.cscript.hide_fields(doc, dt, dn); - if(doc.is_pos == 1){ - if (!doc.company) { - msgprint("Please select company to proceed"); - doc.is_pos = 0; - refresh_field('is_pos'); - } - else { - var callback1 = function(r,rt){ - if(callback) callback(doc, dt, dn); - cur_frm.refresh(); - } - $c_obj(make_doclist(dt,dn),'set_pos_fields','',callback1); - } - } -} - cur_frm.cscript.mode_of_payment = function(doc) { cur_frm.call({ method: "get_bank_cash_account", @@ -159,94 +150,10 @@ cur_frm.cscript.update_stock = function(doc, dt, dn) { cur_frm.cscript.hide_fields(doc, dt, dn); } -cur_frm.cscript.warehouse = function(doc, cdt , cdn) { - var d = locals[cdt][cdn]; - if (!d.item_code) { msgprint("please enter item code first"); return }; - if (d.warehouse) { - arg = "{'item_code':'" + d.item_code + "','warehouse':'" + d.warehouse +"'}"; - get_server_fields('get_actual_qty',arg,'entries',doc,cdt,cdn,1); - } -} - - - -//Customer -cur_frm.cscript.customer = function(doc,dt,dn,onload) { - cur_frm.toggle_display("contact_section", doc.customer); - - var pl = doc.price_list_name; - var callback = function(r,rt) { - var callback2 = function(doc, dt, dn) { - doc = locals[dt][dn]; - if(doc.debit_to && doc.posting_date){ - get_server_fields('get_cust_and_due_date','','',doc,dt,dn,1, - function(doc, dt, dn) { - cur_frm.refresh(); - if (!onload && (pl != doc.price_list_name)) cur_frm.cscript.price_list_name(doc, dt, dn); - }); - - } - } - var doc = locals[cur_frm.doctype][cur_frm.docname]; - get_server_fields('get_debit_to','','',doc, dt, dn, 0, callback2); - } - var args = onload ? 'onload':'' - if(doc.customer) $c_obj(make_doclist(doc.doctype, doc.name), 'get_default_customer_address', args, callback); - -} - - - cur_frm.cscript.customer_address = cur_frm.cscript.contact_person = function(doc,dt,dn) { if(doc.customer) get_server_fields('get_customer_address', JSON.stringify({customer: doc.customer, address: doc.customer_address, contact: doc.contact_person}),'', doc, dt, dn, 1); } -// Set Due Date = posting date + credit days -cur_frm.cscript.debit_to = function(doc,dt,dn) { - - var callback2 = function(r,rt) { - var doc = locals[cur_frm.doctype][cur_frm.docname]; - cur_frm.refresh(); - } - - var callback = function(r,rt) { - var doc = locals[cur_frm.doctype][cur_frm.docname]; - if(doc.customer) $c_obj(make_doclist(dt,dn), 'get_default_customer_address', '', callback2); - cur_frm.toggle_display("contact_section", doc.customer); - - cur_frm.refresh(); - } - - if(doc.debit_to && doc.posting_date){ - get_server_fields('get_cust_and_due_date','','',doc,dt,dn,1,callback); - } -} - - - -//refresh advance amount -//------------------------------------------------- - - -cur_frm.cscript.write_off_outstanding_amount_automatically = function(doc) { - if (doc.write_off_outstanding_amount_automatically == 1) - doc.write_off_amount = flt(doc.grand_total) - flt(doc.paid_amount); - - doc.outstanding_amount = flt(doc.grand_total) - flt(doc.paid_amount) - flt(doc.write_off_amount); - refresh_field(['write_off_amount', 'outstanding_amount']); -} - -cur_frm.cscript.paid_amount = function(doc) { - cur_frm.cscript.write_off_outstanding_amount_automatically(doc); -} - -cur_frm.cscript.write_off_amount = function(doc) { - cur_frm.cscript.write_off_outstanding_amount_automatically(doc); -} - - -//Set debit and credit to zero on adding new row -//---------------------------------------------- cur_frm.fields_dict['entries'].grid.onrowadd = function(doc, cdt, cdn){ cl = getchildren('Sales Invoice Item', doc.name, cur_frm.cscript.fname, doc.doctype); @@ -282,12 +189,6 @@ cur_frm.cscript.get_items = function(doc, dt, dn) { -// Allocated Amount in advances table -// ----------------------------------- -cur_frm.cscript.allocated_amount = function(doc,cdt,cdn){ - cur_frm.cscript.calc_adjustment_amount(doc,cdt,cdn); -} - //Make Delivery Note Button //----------------------------- @@ -452,19 +353,6 @@ cur_frm.cscript.cost_center = function(doc, cdt, cdn){ refresh_field(cur_frm.cscript.fname); } -cur_frm.cscript.calc_adjustment_amount = function(doc,cdt,cdn) { - var doc = locals[doc.doctype][doc.name]; - var el = getchildren('Sales Invoice Advance',doc.name,'advance_adjustment_details'); - var total_adjustment_amt = 0 - for(var i in el) { - total_adjustment_amt += flt(el[i].allocated_amount) - } - doc.total_advance = flt(total_adjustment_amt); - doc.outstanding_amount = flt(doc.grand_total) - flt(total_adjustment_amt) - flt(doc.paid_amount) - flt(doc.write_off_amount); - refresh_many(['total_advance','outstanding_amount']); -} - - // Make Journal Voucher // -------------------- cur_frm.cscript.make_jv = function(doc, dt, dn, bank_account) { diff --git a/accounts/doctype/sales_invoice/sales_invoice.py b/accounts/doctype/sales_invoice/sales_invoice.py index c17654a601..17db651bd9 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.py +++ b/accounts/doctype/sales_invoice/sales_invoice.py @@ -41,7 +41,6 @@ class DocType(SellingController): def validate(self): super(DocType, self).validate() - self.fetch_missing_values() self.validate_posting_time() self.so_dn_required() self.validate_proj_cust() @@ -50,7 +49,6 @@ class DocType(SellingController): sales_com_obj.check_active_sales_items(self) sales_com_obj.check_conversion_rate(self) sales_com_obj.validate_max_discount(self, 'entries') - sales_com_obj.get_allocated_sum(self) sales_com_obj.validate_fiscal_year(self.doc.fiscal_year, self.doc.posting_date,'Posting Date') self.validate_customer() @@ -59,18 +57,22 @@ class DocType(SellingController): self.validate_fixed_asset_account() self.clear_unallocated_advances("Sales Invoice Advance", "advance_adjustment_details") self.add_remarks() + if cint(self.doc.is_pos): self.validate_pos() self.validate_write_off_account() - if cint(self.doc.update_stock): - sl = get_obj('Stock Ledger') - sl.validate_serial_no(self, 'entries') - sl.validate_serial_no(self, 'packing_details') - self.validate_item_code() - self.update_current_stock() - self.validate_delivery_note() + + if cint(self.doc.update_stock): + sl = get_obj('Stock Ledger') + sl.validate_serial_no(self, 'entries') + sl.validate_serial_no(self, 'packing_details') + self.validate_item_code() + self.update_current_stock() + self.validate_delivery_note() + if not self.doc.is_opening: self.doc.is_opening = 'No' + self.set_aging_date() self.set_against_income_account() self.validate_c_form() @@ -80,16 +82,15 @@ class DocType(SellingController): def on_submit(self): - if cint(self.doc.is_pos) == 1: - if cint(self.doc.update_stock) == 1: - sl_obj = get_obj("Stock Ledger") - sl_obj.validate_serial_no_warehouse(self, 'entries') - sl_obj.validate_serial_no_warehouse(self, 'packing_details') - - sl_obj.update_serial_record(self, 'entries', is_submit = 1, is_incoming = 0) - sl_obj.update_serial_record(self, 'packing_details', is_submit = 1, is_incoming = 0) - - self.update_stock_ledger(update_stock=1) + if cint(self.doc.update_stock) == 1: + sl_obj = get_obj("Stock Ledger") + sl_obj.validate_serial_no_warehouse(self, 'entries') + sl_obj.validate_serial_no_warehouse(self, 'packing_details') + + sl_obj.update_serial_record(self, 'entries', is_submit = 1, is_incoming = 0) + sl_obj.update_serial_record(self, 'packing_details', is_submit = 1, is_incoming = 0) + + self.update_stock_ledger(update_stock=1) else: # Check for Approving Authority if not self.doc.recurring_id: @@ -114,13 +115,12 @@ class DocType(SellingController): self.update_time_log_batch(None) def on_cancel(self): - if cint(self.doc.is_pos) == 1: - if cint(self.doc.update_stock) == 1: - sl = get_obj('Stock Ledger') - sl.update_serial_record(self, 'entries', is_submit = 0, is_incoming = 0) - sl.update_serial_record(self, 'packing_details', is_submit = 0, is_incoming = 0) - - self.update_stock_ledger(update_stock = -1) + if cint(self.doc.update_stock) == 1: + sl = get_obj('Stock Ledger') + sl.update_serial_record(self, 'entries', is_submit = 0, is_incoming = 0) + sl.update_serial_record(self, 'packing_details', is_submit = 0, is_incoming = 0) + + self.update_stock_ledger(update_stock = -1) sales_com_obj = get_obj(dt = 'Sales Common') sales_com_obj.check_stop_sales_order(self) @@ -136,25 +136,16 @@ class DocType(SellingController): self.validate_recurring_invoice() self.convert_to_recurring() - def fetch_missing_values(self): - # fetch contact and address details for customer, if they are not mentioned - if not (self.doc.contact_person and self.doc.customer_address): - for fieldname, val in self.get_default_address_and_contact("customer").items(): - if not self.doc.fields.get(fieldname) and self.meta.get_field(fieldname): - self.doc.fields[fieldname] = val - - # fetch missing item values - for item in self.doclist.get({"parentfield": "entries"}): - if item.fields.get("item_code"): - ret = get_obj('Sales Common').get_item_details(item.fields, self) - for fieldname, value in ret.items(): - if self.meta.get_field(fieldname, parentfield="entries") and \ - not item.fields.get(fieldname): - item.fields[fieldname] = value + def set_missing_values(self, for_validate=False): + super(DocType, self).set_missing_values(for_validate) + self.set_pos_fields(for_validate) - # fetch pos details, if they are not fetched - if cint(self.doc.is_pos): - self.set_pos_fields(for_validate=True) + def set_customer_defaults(self): + # TODO cleanup these methods + self.doc.fields.update(self.get_debit_to()) + self.get_cust_and_due_date() + + super(DocType, self).set_customer_defaults() def update_time_log_batch(self, sales_invoice): for d in self.doclist.get({"doctype":"Sales Invoice Item"}): @@ -175,10 +166,11 @@ class DocType(SellingController): """Set retail related fields from pos settings""" if cint(self.doc.is_pos) != 1: return + + from selling.utils import get_pos_settings, apply_pos_settings + pos = get_pos_settings(self.doc.company) - if self.pos_settings: - pos = self.pos_settings[0] - + if pos: self.doc.conversion_rate = flt(pos.conversion_rate) if not self.doc.debit_to: @@ -191,11 +183,14 @@ class DocType(SellingController): 'price_list_name', 'company', 'select_print_heading', 'cash_bank_account'): if (not for_validate) or (for_validate and not self.doc.fields.get(fieldname)): self.doc.fields[fieldname] = pos.get(fieldname) + + if not for_validate: + self.doc.update_stock = cint(pos.get("update_stock")) # set pos values in items for item in self.doclist.get({"parentfield": "entries"}): if item.fields.get('item_code'): - for fieldname, val in self.apply_pos_settings(item.fields).items(): + for fieldname, val in apply_pos_settings(pos, item.fields).items(): if (not for_validate) or (for_validate and not item.fields.get(fieldname)): item.fields[fieldname] = val @@ -205,7 +200,7 @@ class DocType(SellingController): # fetch charges if self.doc.charge and not len(self.doclist.get({"parentfield": "other_charges"})): - self.get_other_charges() + self.set_taxes() def get_customer_account(self): """Get Account Head to which amount needs to be Debited based on Customer""" @@ -275,86 +270,6 @@ class DocType(SellingController): ret = self.get_debit_to() self.doc.debit_to = ret.get('debit_to') - - def load_default_accounts(self): - """ - Loads default accounts from items, customer when called from mapper - """ - self.get_income_expense_account('entries') - - - def get_income_expense_account(self,doctype): - for d in getlist(self.doclist, doctype): - if d.item_code: - item = webnotes.conn.get_value("Item", d.item_code, ["default_income_account", - "default_sales_cost_center", "purchase_account"], as_dict=True) - d.income_account = item['default_income_account'] or "" - d.cost_center = item['default_sales_cost_center'] or "" - - if cint(webnotes.defaults.get_global_default("auto_inventory_accounting")) \ - and cint(self.doc.is_pos) and cint(self.doc.update_stock): - d.expense_account = item['purchase_account'] or "" - - def get_item_details(self, args=None): - import json - args = args and json.loads(args) or {} - if args.get('item_code'): - ret = get_obj('Sales Common').get_item_details(args, self) - - if cint(self.doc.is_pos) == 1 and self.pos_settings: - ret = self.apply_pos_settings(args, ret) - - return ret - - elif cint(self.doc.is_pos) == 1 and self.pos_settings: - for doc in self.doclist.get({"parentfield": "entries"}): - if doc.fields.get('item_code'): - ret = self.apply_pos_settings(doc.fields) - for r in ret: - if not doc.fields.get(r): - doc.fields[r] = ret[r] - - @property - def pos_settings(self): - if not hasattr(self, "_pos_settings"): - dtl = webnotes.conn.sql("""select * from `tabPOS Setting` where user = %s - and company = %s""", (webnotes.session['user'], self.doc.company), as_dict=1) - if not dtl: - dtl = webnotes.conn.sql("""select * from `tabPOS Setting` - where ifnull(user,'') = '' and company = %s""", self.doc.company, as_dict=1) - self._pos_settings = dtl - - return self._pos_settings - - def apply_pos_settings(self, args, ret=None): - if not ret: ret = {} - - pos = self.pos_settings[0] - - item = webnotes.conn.sql("""select default_income_account, default_sales_cost_center, - default_warehouse, purchase_account from tabItem where name = %s""", - args.get('item_code'), as_dict=1) - - if item: - item = item[0] - - ret.update({ - "income_account": item.get("default_income_account") \ - or pos.get("income_account") or args.get("income_account"), - "cost_center": item.get("default_sales_cost_center") \ - or pos.get("cost_center") or args.get("cost_center"), - "warehouse": item.get("default_warehouse") \ - or pos.get("warehouse") or args.get("warehouse"), - "expense_account": item.get("purchase_account") \ - or pos.get("expense_account") or args.get("expense_account") - }) - - if ret.get("warehouse"): - ret["actual_qty"] = flt(webnotes.conn.get_value("Bin", - {"item_code": args.get("item_code"), "warehouse": ret.get("warehouse")}, - "actual_qty")) - return ret - def get_barcode_details(self, barcode): return get_obj('Sales Common').get_barcode_details(barcode) @@ -378,14 +293,6 @@ class DocType(SellingController): return get_obj('Sales Common').get_tc_details(self) - def load_default_taxes(self): - self.doclist = get_obj('Sales Common').load_default_taxes(self) - - - def get_other_charges(self): - self.doclist = get_obj('Sales Common').get_other_charges(self) - - def get_advances(self): super(DocType, self).get_advances(self.doc.debit_to, "Sales Invoice Advance", "advance_adjustment_details", "credit") @@ -534,13 +441,13 @@ class DocType(SellingController): def validate_item_code(self): for d in getlist(self.doclist, 'entries'): if not d.item_code: - msgprint("Please enter Item Code at line no : %s to update stock for POS or remove check from Update Stock in Basic Info Tab." % (d.idx)) - raise Exception + msgprint("Please enter Item Code at line no : %s to update stock or remove check from Update Stock in Basic Info Tab." % (d.idx), + raise_exception=True) def validate_delivery_note(self): for d in self.doclist.get({"parentfield": "entries"}): if d.delivery_note: - msgprint("""POS can not be made against Delivery Note""", raise_exception=1) + msgprint("""Stock update can not be made against Delivery Note""", raise_exception=1) def validate_write_off_account(self): @@ -606,36 +513,28 @@ class DocType(SellingController): def on_update(self): - # Set default warehouse from pos setting - if cint(self.doc.is_pos) == 1: - if cint(self.doc.update_stock) == 1: + if cint(self.doc.update_stock) == 1: + # Set default warehouse from pos setting + if cint(self.doc.is_pos) == 1: w = self.get_warehouse() if w: for d in getlist(self.doclist, 'entries'): if not d.warehouse: d.warehouse = cstr(w) - - self.make_packing_list() - else: - self.doclist = self.doc.clear_table(self.doclist, 'packing_details') - if flt(self.doc.paid_amount) == 0: - if self.doc.cash_bank_account: - webnotes.conn.set(self.doc, 'paid_amount', - (flt(self.doc.grand_total) - flt(self.doc.write_off_amount))) - else: - # show message that the amount is not paid - webnotes.conn.set(self.doc,'paid_amount',0) - webnotes.msgprint("Note: Payment Entry will not be created since 'Cash/Bank Account' was not specified.") + if flt(self.doc.paid_amount) == 0: + if self.doc.cash_bank_account: + webnotes.conn.set(self.doc, 'paid_amount', + (flt(self.doc.grand_total) - flt(self.doc.write_off_amount))) + else: + # show message that the amount is not paid + webnotes.conn.set(self.doc,'paid_amount',0) + webnotes.msgprint("Note: Payment Entry will not be created since 'Cash/Bank Account' was not specified.") + self.make_packing_list() else: self.doclist = self.doc.clear_table(self.doclist, 'packing_details') webnotes.conn.set(self.doc,'paid_amount',0) - - webnotes.conn.set(self.doc, 'outstanding_amount', - flt(self.doc.grand_total) - flt(self.doc.total_advance) - - flt(self.doc.paid_amount) - flt(self.doc.write_off_amount)) - def check_prev_docstatus(self): for d in getlist(self.doclist,'entries'): @@ -689,15 +588,6 @@ class DocType(SellingController): get_obj('Stock Ledger', 'Stock Ledger').update_stock(self.values) - def get_actual_qty(self,args): - args = eval(args) - actual_qty = webnotes.conn.sql("select actual_qty from `tabBin` where item_code = '%s' and warehouse = '%s'" % (args['item_code'], args['warehouse']), as_dict=1) - ret = { - 'actual_qty' : actual_qty and flt(actual_qty[0]['actual_qty']) or 0 - } - return ret - - def make_gl_entries(self): from accounts.general_ledger import make_gl_entries, merge_similar_entries @@ -742,7 +632,7 @@ class DocType(SellingController): "against": self.doc.debit_to, "credit": flt(tax.tax_amount), "remarks": self.doc.remarks, - "cost_center": tax.cost_center_other_charges + "cost_center": tax.cost_center }) ) @@ -762,7 +652,7 @@ class DocType(SellingController): # expense account gl entries if cint(webnotes.defaults.get_global_default("auto_inventory_accounting")) \ - and cint(self.doc.is_pos) and cint(self.doc.update_stock): + and cint(self.doc.update_stock): for item in self.doclist.get({"parentfield": "entries"}): self.check_expense_account(item) diff --git a/accounts/doctype/sales_invoice/sales_invoice.txt b/accounts/doctype/sales_invoice/sales_invoice.txt index a2c422f38a..9dcac589a0 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.txt +++ b/accounts/doctype/sales_invoice/sales_invoice.txt @@ -1,8 +1,8 @@ [ { - "creation": "2013-04-19 11:00:14", + "creation": "2013-05-24 19:29:05", "docstatus": 0, - "modified": "2013-04-22 11:59:28", + "modified": "2013-05-29 18:53:26", "modified_by": "Administrator", "owner": "Administrator" }, @@ -10,6 +10,7 @@ "allow_attach": 1, "autoname": "naming_series:", "doctype": "DocType", + "document_type": "Transaction", "is_submittable": 1, "module": "Accounts", "name": "__common__", @@ -79,7 +80,6 @@ "read_only": 0 }, { - "depends_on": "eval:doc.is_pos==1", "doctype": "DocField", "fieldname": "update_stock", "fieldtype": "Check", @@ -118,10 +118,11 @@ "read_only": 0 }, { + "depends_on": "customer", "doctype": "DocField", "fieldname": "customer_name", "fieldtype": "Data", - "hidden": 1, + "hidden": 0, "in_list_view": 1, "label": "Name", "oldfieldname": "customer_name", @@ -129,34 +130,38 @@ "read_only": 1 }, { + "depends_on": "customer", "doctype": "DocField", "fieldname": "address_display", "fieldtype": "Small Text", - "hidden": 1, + "hidden": 0, "label": "Address", "read_only": 1 }, { + "depends_on": "customer", "doctype": "DocField", "fieldname": "contact_display", "fieldtype": "Small Text", - "hidden": 1, + "hidden": 0, "label": "Contact", "read_only": 1 }, { + "depends_on": "customer", "doctype": "DocField", "fieldname": "contact_mobile", "fieldtype": "Text", - "hidden": 1, + "hidden": 0, "label": "Mobile No", "read_only": 1 }, { + "depends_on": "customer", "doctype": "DocField", "fieldname": "contact_email", "fieldtype": "Text", - "hidden": 1, + "hidden": 0, "label": "Contact Email", "print_hide": 1, "read_only": 1 @@ -222,11 +227,12 @@ "doctype": "DocField", "fieldname": "entries", "fieldtype": "Table", - "label": "Entries", + "label": "Sales Invoice Items", "oldfieldname": "entries", "oldfieldtype": "Table", "options": "Sales Invoice Item", - "read_only": 0 + "read_only": 0, + "reqd": 1 }, { "doctype": "DocField", @@ -250,35 +256,6 @@ "read_only": 0, "width": "50%" }, - { - "description": "Will be calculated automatically when you enter the details", - "doctype": "DocField", - "fieldname": "net_total", - "fieldtype": "Currency", - "label": "Net Total*", - "oldfieldname": "net_total", - "oldfieldtype": "Currency", - "options": "Company:company:default_currency", - "print_hide": 0, - "read_only": 1, - "reqd": 1 - }, - { - "doctype": "DocField", - "fieldname": "recalculate_values", - "fieldtype": "Button", - "label": "Re-Calculate Values", - "oldfieldtype": "Button", - "print_hide": 1, - "read_only": 0 - }, - { - "doctype": "DocField", - "fieldname": "col_break25", - "fieldtype": "Column Break", - "read_only": 0, - "width": "50%" - }, { "description": "Select Items from Sales Order", "doctype": "DocField", @@ -312,6 +289,43 @@ "print_hide": 1, "read_only": 0 }, + { + "doctype": "DocField", + "fieldname": "col_break25", + "fieldtype": "Column Break", + "read_only": 0, + "width": "50%" + }, + { + "doctype": "DocField", + "fieldname": "recalculate_values", + "fieldtype": "Button", + "label": "Re-Calculate Values", + "oldfieldtype": "Button", + "print_hide": 1, + "read_only": 0 + }, + { + "doctype": "DocField", + "fieldname": "net_total", + "fieldtype": "Currency", + "label": "Net Total*", + "oldfieldname": "net_total", + "oldfieldtype": "Currency", + "options": "Company:company:default_currency", + "print_hide": 1, + "read_only": 1, + "reqd": 1 + }, + { + "doctype": "DocField", + "fieldname": "net_total_export", + "fieldtype": "Currency", + "label": "Net Total (Export)", + "options": "currency", + "print_hide": 0, + "read_only": 1 + }, { "doctype": "DocField", "fieldname": "currency_section", @@ -450,6 +464,15 @@ "print_hide": 1, "read_only": 1 }, + { + "doctype": "DocField", + "fieldname": "other_charges_total_export", + "fieldtype": "Currency", + "label": "Total Taxes and Charges (Export)", + "options": "currency", + "print_hide": 1, + "read_only": 1 + }, { "doctype": "DocField", "fieldname": "other_charges_calculation", @@ -728,6 +751,7 @@ "read_only": 0 }, { + "depends_on": "customer", "doctype": "DocField", "fieldname": "contact_section", "fieldtype": "Section Break", @@ -1283,6 +1307,17 @@ "read_only": 0, "report_hide": 1 }, + { + "amend": 0, + "cancel": 0, + "create": 0, + "doctype": "DocPerm", + "permlevel": 1, + "report": 0, + "role": "Accounts Manager", + "submit": 0, + "write": 0 + }, { "amend": 1, "cancel": 1, @@ -1290,10 +1325,32 @@ "doctype": "DocPerm", "permlevel": 0, "report": 1, + "role": "Accounts Manager", + "submit": 1, + "write": 1 + }, + { + "amend": 1, + "cancel": 0, + "create": 1, + "doctype": "DocPerm", + "permlevel": 0, + "report": 1, "role": "Accounts User", "submit": 1, "write": 1 }, + { + "amend": 0, + "cancel": 0, + "create": 0, + "doctype": "DocPerm", + "permlevel": 1, + "report": 0, + "role": "Accounts User", + "submit": 0, + "write": 0 + }, { "doctype": "DocPerm", "match": "customer", @@ -1301,4 +1358,9 @@ "report": 1, "role": "Customer" }, + { + "doctype": "DocPerm", + "permlevel": 0, + "role": "Retail User" + } ] \ No newline at end of file diff --git a/accounts/doctype/sales_invoice/test_sales_invoice.py b/accounts/doctype/sales_invoice/test_sales_invoice.py index b46cdd1777..dfc61eb172 100644 --- a/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -1,12 +1,226 @@ import webnotes -import unittest +import unittest, json +from webnotes.utils import flt, cint class TestSalesInvoice(unittest.TestCase): def make(self): - w = webnotes.bean(webnotes.copy_doclist(test_records[0])) + w = webnotes.bean(copy=test_records[0]) w.insert() w.submit() return w + + def test_sales_invoice_calculation_base_currency(self): + si = webnotes.bean(copy=test_records[2]) + si.run_method("calculate_taxes_and_totals") + si.insert() + + expected_values = { + "keys": ["ref_rate", "adj_rate", "export_rate", "export_amount", + "base_ref_rate", "basic_rate", "amount"], + "_Test Item Home Desktop 100": [50, 0, 50, 500, 50, 50, 500], + "_Test Item Home Desktop 200": [150, 0, 150, 750, 150, 150, 750], + } + + # check if children are saved + self.assertEquals(len(si.doclist.get({"parentfield": "entries"})), + len(expected_values)-1) + + # check if item values are calculated + for d in si.doclist.get({"parentfield": "entries"}): + for i, k in enumerate(expected_values["keys"]): + self.assertEquals(d.fields.get(k), expected_values[d.item_code][i]) + + # check net total + self.assertEquals(si.doc.net_total, 1250) + self.assertEquals(si.doc.net_total_export, 1250) + + # check tax calculation + expected_values = { + "keys": ["tax_amount", "total"], + "_Test Account Shipping Charges - _TC": [100, 1350], + "_Test Account Customs Duty - _TC": [125, 1475], + "_Test Account Excise Duty - _TC": [140, 1615], + "_Test Account Education Cess - _TC": [2.8, 1617.8], + "_Test Account S&H Education Cess - _TC": [1.4, 1619.2], + "_Test Account CST - _TC": [32.38, 1651.58], + "_Test Account VAT - _TC": [156.25, 1807.83], + "_Test Account Discount - _TC": [-180.78, 1627.05] + } + + for d in si.doclist.get({"parentfield": "other_charges"}): + for i, k in enumerate(expected_values["keys"]): + self.assertEquals(d.fields.get(k), expected_values[d.account_head][i]) + + self.assertEquals(si.doc.grand_total, 1627.05) + self.assertEquals(si.doc.grand_total_export, 1627.05) + + def test_sales_invoice_calculation_export_currency(self): + si = webnotes.bean(copy=test_records[2]) + si.doc.currency = "USD" + si.doc.conversion_rate = 50 + si.doclist[1].export_rate = 1 + si.doclist[1].ref_rate = 1 + si.doclist[2].export_rate = 3 + si.doclist[2].ref_rate = 3 + si.run_method("calculate_taxes_and_totals") + si.insert() + + expected_values = { + "keys": ["ref_rate", "adj_rate", "export_rate", "export_amount", + "base_ref_rate", "basic_rate", "amount"], + "_Test Item Home Desktop 100": [1, 0, 1, 10, 50, 50, 500], + "_Test Item Home Desktop 200": [3, 0, 3, 15, 150, 150, 750], + } + + # check if children are saved + self.assertEquals(len(si.doclist.get({"parentfield": "entries"})), + len(expected_values)-1) + + # check if item values are calculated + for d in si.doclist.get({"parentfield": "entries"}): + for i, k in enumerate(expected_values["keys"]): + self.assertEquals(d.fields.get(k), expected_values[d.item_code][i]) + + # check net total + self.assertEquals(si.doc.net_total, 1250) + self.assertEquals(si.doc.net_total_export, 25) + + # check tax calculation + expected_values = { + "keys": ["tax_amount", "total"], + "_Test Account Shipping Charges - _TC": [100, 1350], + "_Test Account Customs Duty - _TC": [125, 1475], + "_Test Account Excise Duty - _TC": [140, 1615], + "_Test Account Education Cess - _TC": [2.8, 1617.8], + "_Test Account S&H Education Cess - _TC": [1.4, 1619.2], + "_Test Account CST - _TC": [32.38, 1651.58], + "_Test Account VAT - _TC": [156.25, 1807.83], + "_Test Account Discount - _TC": [-180.78, 1627.05] + } + + for d in si.doclist.get({"parentfield": "other_charges"}): + for i, k in enumerate(expected_values["keys"]): + self.assertEquals(d.fields.get(k), expected_values[d.account_head][i]) + + self.assertEquals(si.doc.grand_total, 1627.05) + self.assertEquals(si.doc.grand_total_export, 32.54) + + def test_inclusive_rate_validations(self): + si = webnotes.bean(copy=test_records[2]) + for i, tax in enumerate(si.doclist.get({"parentfield": "other_charges"})): + tax.idx = i+1 + + si.doclist[1].ref_rate = 62.5 + si.doclist[1].ref_rate = 191 + for i in [3, 5, 6, 7, 8, 9]: + si.doclist[i].included_in_print_rate = 1 + + # tax type "Actual" cannot be inclusive + self.assertRaises(webnotes.ValidationError, si.run_method, "calculate_taxes_and_totals") + + # taxes above included type 'On Previous Row Total' should also be included + si.doclist[3].included_in_print_rate = 0 + self.assertRaises(webnotes.ValidationError, si.run_method, "calculate_taxes_and_totals") + + def test_sales_invoice_calculation_base_currency_with_tax_inclusive_price(self): + # prepare + si = webnotes.bean(copy=test_records[3]) + si.run_method("calculate_taxes_and_totals") + si.insert() + + expected_values = { + "keys": ["ref_rate", "adj_rate", "export_rate", "export_amount", + "base_ref_rate", "basic_rate", "amount"], + "_Test Item Home Desktop 100": [62.5, 0, 62.5, 625.0, 50, 50, 500], + "_Test Item Home Desktop 200": [190.66, 0, 190.66, 953.3, 150, 150, 750], + } + + # check if children are saved + self.assertEquals(len(si.doclist.get({"parentfield": "entries"})), + len(expected_values)-1) + + # check if item values are calculated + for d in si.doclist.get({"parentfield": "entries"}): + for i, k in enumerate(expected_values["keys"]): + self.assertEquals(d.fields.get(k), expected_values[d.item_code][i]) + + # check net total + self.assertEquals(si.doc.net_total, 1250) + self.assertEquals(si.doc.net_total_export, 1578.3) + + # check tax calculation + expected_values = { + "keys": ["tax_amount", "total"], + "_Test Account Excise Duty - _TC": [140, 1390], + "_Test Account Education Cess - _TC": [2.8, 1392.8], + "_Test Account S&H Education Cess - _TC": [1.4, 1394.2], + "_Test Account CST - _TC": [27.88, 1422.08], + "_Test Account VAT - _TC": [156.25, 1578.33], + "_Test Account Customs Duty - _TC": [125, 1703.33], + "_Test Account Shipping Charges - _TC": [100, 1803.33], + "_Test Account Discount - _TC": [-180.33, 1623] + } + + for d in si.doclist.get({"parentfield": "other_charges"}): + for i, k in enumerate(expected_values["keys"]): + self.assertEquals(flt(d.fields.get(k), 6), expected_values[d.account_head][i]) + + self.assertEquals(si.doc.grand_total, 1623) + self.assertEquals(si.doc.grand_total_export, 1623) + + def test_sales_invoice_calculation_export_currency_with_tax_inclusive_price(self): + # prepare + si = webnotes.bean(copy=test_records[3]) + si.doc.currency = "USD" + si.doc.conversion_rate = 50 + si.doclist[1].ref_rate = 55.56 + si.doclist[1].adj_rate = 10 + si.doclist[2].ref_rate = 187.5 + si.doclist[2].adj_rate = 20 + si.doclist[9].rate = 5000 + + si.run_method("calculate_taxes_and_totals") + si.insert() + + expected_values = { + "keys": ["ref_rate", "adj_rate", "export_rate", "export_amount", + "base_ref_rate", "basic_rate", "amount"], + "_Test Item Home Desktop 100": [55.56, 10, 50, 500, 2222.11, 1999.9, 19999.0], + "_Test Item Home Desktop 200": [187.5, 20, 150, 750, 7375.66, 5900.53, 29502.65], + } + + # check if children are saved + self.assertEquals(len(si.doclist.get({"parentfield": "entries"})), + len(expected_values)-1) + + # check if item values are calculated + for d in si.doclist.get({"parentfield": "entries"}): + for i, k in enumerate(expected_values["keys"]): + self.assertEquals(d.fields.get(k), expected_values[d.item_code][i]) + + # check net total + self.assertEquals(si.doc.net_total, 49501.65) + self.assertEquals(si.doc.net_total_export, 1250) + + # check tax calculation + expected_values = { + "keys": ["tax_amount", "total"], + "_Test Account Excise Duty - _TC": [5540.22, 55041.87], + "_Test Account Education Cess - _TC": [110.81, 55152.68], + "_Test Account S&H Education Cess - _TC": [55.4, 55208.08], + "_Test Account CST - _TC": [1104.16, 56312.24], + "_Test Account VAT - _TC": [6187.71, 62499.95], + "_Test Account Customs Duty - _TC": [4950.17, 67450.12], + "_Test Account Shipping Charges - _TC": [5000, 72450.12], + "_Test Account Discount - _TC": [-7245.01, 65205.11] + } + + for d in si.doclist.get({"parentfield": "other_charges"}): + for i, k in enumerate(expected_values["keys"]): + self.assertEquals(flt(d.fields.get(k), 6), expected_values[d.account_head][i]) + + self.assertEquals(si.doc.grand_total, 65205.11) + self.assertEquals(si.doc.grand_total_export, 1304.1) def test_outstanding(self): w = self.make() @@ -103,7 +317,7 @@ class TestSalesInvoice(unittest.TestCase): pos[0]["cash_bank_account"] = "_Test Account Bank Account - _TC" pos[0]["paid_amount"] = 600.0 - si = webnotes.bean(pos) + si = webnotes.bean(copy=pos) si.insert() si.submit() @@ -113,7 +327,7 @@ class TestSalesInvoice(unittest.TestCase): si.doc.name, as_dict=1)[0] self.assertTrue(sle) self.assertEquals([sle.item_code, sle.warehouse, sle.actual_qty], - ["_Test Item", "_Test Warehouse", -5.0]) + ["_Test Item", "_Test Warehouse", -1.0]) # check gl entries stock_in_hand_account = webnotes.conn.get_value("Company", "_Test Company", @@ -126,11 +340,11 @@ class TestSalesInvoice(unittest.TestCase): expected_gl_entries = sorted([ [si.doc.debit_to, 630.0, 0.0], - [test_records[1][1]["income_account"], 0.0, 500.0], - [test_records[1][2]["account_head"], 0.0, 80.0], - [test_records[1][3]["account_head"], 0.0, 50.0], - [stock_in_hand_account, 0.0, 375.0], - [test_records[1][1]["expense_account"], 375.0, 0.0], + [pos[1]["income_account"], 0.0, 500.0], + [pos[2]["account_head"], 0.0, 80.0], + [pos[3]["account_head"], 0.0, 50.0], + [stock_in_hand_account, 0.0, 75.0], + [pos[1]["expense_account"], 75.0, 0.0], [si.doc.debit_to, 0.0, 600.0], ["_Test Account Bank Account - _TC", 600.0, 0.0] ]) @@ -444,7 +658,7 @@ test_records = [ "description": "VAT", "doctype": "Sales Taxes and Charges", "parentfield": "other_charges", - "tax_amount": 30.0, + "rate": 6, }, { "account_head": "_Test Account Service Tax - _TC", @@ -452,7 +666,7 @@ test_records = [ "description": "Service Tax", "doctype": "Sales Taxes and Charges", "parentfield": "other_charges", - "tax_amount": 31.8, + "rate": 6.36, }, { "parentfield": "sales_team", @@ -494,7 +708,7 @@ test_records = [ "description": "_Test Item", "doctype": "Sales Invoice Item", "parentfield": "entries", - "qty": 5.0, + "qty": 1.0, "basic_rate": 500.0, "amount": 500.0, "export_rate": 500.0, @@ -509,7 +723,7 @@ test_records = [ "description": "VAT", "doctype": "Sales Taxes and Charges", "parentfield": "other_charges", - "tax_amount": 80.0, + "rate": 16, }, { "account_head": "_Test Account Service Tax - _TC", @@ -517,7 +731,270 @@ test_records = [ "description": "Service Tax", "doctype": "Sales Taxes and Charges", "parentfield": "other_charges", - "tax_amount": 50.0, + "rate": 10 } ], + [ + { + "naming_series": "_T-Sales Invoice-", + "company": "_Test Company", + "conversion_rate": 1.0, + "currency": "INR", + "debit_to": "_Test Customer - _TC", + "customer": "_Test Customer", + "customer_name": "_Test Customer", + "doctype": "Sales Invoice", + "due_date": "2013-01-23", + "fiscal_year": "_Test Fiscal Year 2013", + "grand_total_export": 0, + "plc_conversion_rate": 1.0, + "posting_date": "2013-01-23", + "price_list_currency": "INR", + "price_list_name": "_Test Price List", + "territory": "_Test Territory", + }, + # items + { + "doctype": "Sales Invoice Item", + "parentfield": "entries", + "item_code": "_Test Item Home Desktop 100", + "item_name": "_Test Item Home Desktop 100", + "qty": 10, + "ref_rate": 50, + "export_rate": 50, + "stock_uom": "_Test UOM", + "item_tax_rate": json.dumps({"_Test Account Excise Duty - _TC": 10}), + "income_account": "Sales - _TC", + "cost_center": "_Test Cost Center - _TC", + + }, + { + "doctype": "Sales Invoice Item", + "parentfield": "entries", + "item_code": "_Test Item Home Desktop 200", + "item_name": "_Test Item Home Desktop 200", + "qty": 5, + "ref_rate": 150, + "export_rate": 150, + "stock_uom": "_Test UOM", + "income_account": "Sales - _TC", + "cost_center": "_Test Cost Center - _TC", + + }, + # taxes + { + "doctype": "Sales Taxes and Charges", + "parentfield": "other_charges", + "charge_type": "Actual", + "account_head": "_Test Account Shipping Charges - _TC", + "cost_center": "_Test Cost Center - _TC", + "description": "Shipping Charges", + "rate": 100 + }, + { + "doctype": "Sales Taxes and Charges", + "parentfield": "other_charges", + "charge_type": "On Net Total", + "account_head": "_Test Account Customs Duty - _TC", + "cost_center": "_Test Cost Center - _TC", + "description": "Customs Duty", + "rate": 10 + }, + { + "doctype": "Sales Taxes and Charges", + "parentfield": "other_charges", + "charge_type": "On Net Total", + "account_head": "_Test Account Excise Duty - _TC", + "cost_center": "_Test Cost Center - _TC", + "description": "Excise Duty", + "rate": 12 + }, + { + "doctype": "Sales Taxes and Charges", + "parentfield": "other_charges", + "charge_type": "On Previous Row Amount", + "account_head": "_Test Account Education Cess - _TC", + "cost_center": "_Test Cost Center - _TC", + "description": "Education Cess", + "rate": 2, + "row_id": 3 + }, + { + "doctype": "Sales Taxes and Charges", + "parentfield": "other_charges", + "charge_type": "On Previous Row Amount", + "account_head": "_Test Account S&H Education Cess - _TC", + "cost_center": "_Test Cost Center - _TC", + "description": "S&H Education Cess", + "rate": 1, + "row_id": 3 + }, + { + "doctype": "Sales Taxes and Charges", + "parentfield": "other_charges", + "charge_type": "On Previous Row Total", + "account_head": "_Test Account CST - _TC", + "cost_center": "_Test Cost Center - _TC", + "description": "CST", + "rate": 2, + "row_id": 5 + }, + { + "doctype": "Sales Taxes and Charges", + "parentfield": "other_charges", + "charge_type": "On Net Total", + "account_head": "_Test Account VAT - _TC", + "cost_center": "_Test Cost Center - _TC", + "description": "VAT", + "rate": 12.5 + }, + { + "doctype": "Sales Taxes and Charges", + "parentfield": "other_charges", + "charge_type": "On Previous Row Total", + "account_head": "_Test Account Discount - _TC", + "cost_center": "_Test Cost Center - _TC", + "description": "Discount", + "rate": -10, + "row_id": 7 + }, + ], + [ + { + "naming_series": "_T-Sales Invoice-", + "company": "_Test Company", + "conversion_rate": 1.0, + "currency": "INR", + "debit_to": "_Test Customer - _TC", + "customer": "_Test Customer", + "customer_name": "_Test Customer", + "doctype": "Sales Invoice", + "due_date": "2013-01-23", + "fiscal_year": "_Test Fiscal Year 2013", + "grand_total_export": 0, + "plc_conversion_rate": 1.0, + "posting_date": "2013-01-23", + "price_list_currency": "INR", + "price_list_name": "_Test Price List", + "territory": "_Test Territory", + }, + # items + { + "doctype": "Sales Invoice Item", + "parentfield": "entries", + "item_code": "_Test Item Home Desktop 100", + "item_name": "_Test Item Home Desktop 100", + "qty": 10, + "ref_rate": 62.5, + "export_rate": 62.5, + "stock_uom": "_Test UOM", + "item_tax_rate": json.dumps({"_Test Account Excise Duty - _TC": 10}), + "income_account": "Sales - _TC", + "cost_center": "_Test Cost Center - _TC", + + }, + { + "doctype": "Sales Invoice Item", + "parentfield": "entries", + "item_code": "_Test Item Home Desktop 200", + "item_name": "_Test Item Home Desktop 200", + "qty": 5, + "ref_rate": 190.66, + "export_rate": 190.66, + "stock_uom": "_Test UOM", + "income_account": "Sales - _TC", + "cost_center": "_Test Cost Center - _TC", + + }, + # taxes + { + "doctype": "Sales Taxes and Charges", + "parentfield": "other_charges", + "charge_type": "On Net Total", + "account_head": "_Test Account Excise Duty - _TC", + "cost_center": "_Test Cost Center - _TC", + "description": "Excise Duty", + "rate": 12, + "included_in_print_rate": 1, + "idx": 1 + }, + { + "doctype": "Sales Taxes and Charges", + "parentfield": "other_charges", + "charge_type": "On Previous Row Amount", + "account_head": "_Test Account Education Cess - _TC", + "cost_center": "_Test Cost Center - _TC", + "description": "Education Cess", + "rate": 2, + "row_id": 1, + "included_in_print_rate": 1, + "idx": 2 + }, + { + "doctype": "Sales Taxes and Charges", + "parentfield": "other_charges", + "charge_type": "On Previous Row Amount", + "account_head": "_Test Account S&H Education Cess - _TC", + "cost_center": "_Test Cost Center - _TC", + "description": "S&H Education Cess", + "rate": 1, + "row_id": 1, + "included_in_print_rate": 1, + "idx": 3 + }, + { + "doctype": "Sales Taxes and Charges", + "parentfield": "other_charges", + "charge_type": "On Previous Row Total", + "account_head": "_Test Account CST - _TC", + "cost_center": "_Test Cost Center - _TC", + "description": "CST", + "rate": 2, + "row_id": 3, + "included_in_print_rate": 1, + "idx": 4 + }, + { + "doctype": "Sales Taxes and Charges", + "parentfield": "other_charges", + "charge_type": "On Net Total", + "account_head": "_Test Account VAT - _TC", + "cost_center": "_Test Cost Center - _TC", + "description": "VAT", + "rate": 12.5, + "included_in_print_rate": 1, + "idx": 5 + }, + { + "doctype": "Sales Taxes and Charges", + "parentfield": "other_charges", + "charge_type": "On Net Total", + "account_head": "_Test Account Customs Duty - _TC", + "cost_center": "_Test Cost Center - _TC", + "description": "Customs Duty", + "rate": 10, + "idx": 6 + }, + { + "doctype": "Sales Taxes and Charges", + "parentfield": "other_charges", + "charge_type": "Actual", + "account_head": "_Test Account Shipping Charges - _TC", + "cost_center": "_Test Cost Center - _TC", + "description": "Shipping Charges", + "rate": 100, + "idx": 7 + }, + { + "doctype": "Sales Taxes and Charges", + "parentfield": "other_charges", + "charge_type": "On Previous Row Total", + "account_head": "_Test Account Discount - _TC", + "cost_center": "_Test Cost Center - _TC", + "description": "Discount", + "rate": -10, + "row_id": 7, + "idx": 8 + }, + ], ] \ No newline at end of file diff --git a/accounts/doctype/sales_invoice_item/sales_invoice_item.txt b/accounts/doctype/sales_invoice_item/sales_invoice_item.txt index 89c86f8219..014a9f453c 100644 --- a/accounts/doctype/sales_invoice_item/sales_invoice_item.txt +++ b/accounts/doctype/sales_invoice_item/sales_invoice_item.txt @@ -2,7 +2,7 @@ { "creation": "2013-04-19 11:00:07", "docstatus": 0, - "modified": "2013-05-22 12:06:15", + "modified": "2013-05-22 12:07:00", "modified_by": "Administrator", "owner": "Administrator" }, @@ -107,7 +107,7 @@ "oldfieldtype": "Currency", "options": "currency", "print_hide": 1, - "read_only": 0, + "read_only": 1, "reqd": 0 }, { @@ -163,7 +163,7 @@ "oldfieldtype": "Currency", "options": "Company:company:default_currency", "print_hide": 1, - "read_only": 0, + "read_only": 1, "reqd": 1, "search_index": 0 }, diff --git a/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.txt b/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.txt index 161eb008ea..ba9f90724a 100644 --- a/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.txt +++ b/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.txt @@ -1,8 +1,8 @@ [ { - "creation": "2013-02-22 01:27:41", + "creation": "2013-04-24 11:39:32", "docstatus": 0, - "modified": "2013-04-17 14:05:18", + "modified": "2013-05-28 11:59:02", "modified_by": "Administrator", "owner": "Administrator" }, @@ -50,7 +50,7 @@ { "default": ":Company", "doctype": "DocField", - "fieldname": "cost_center_other_charges", + "fieldname": "cost_center", "fieldtype": "Link", "label": "Cost Center", "oldfieldname": "cost_center_other_charges", @@ -85,6 +85,7 @@ "oldfieldname": "tax_amount", "oldfieldtype": "Currency", "options": "Company:company:default_currency", + "read_only": 1, "reqd": 0 }, { @@ -128,34 +129,6 @@ "print_hide": 1, "search_index": 1 }, - { - "description": "Cheating Field\nPlease do not delete ", - "doctype": "DocField", - "fieldname": "total_tax_amount", - "fieldtype": "Currency", - "hidden": 1, - "label": "Total Tax Amount", - "no_copy": 1, - "oldfieldname": "total_tax_amount", - "oldfieldtype": "Currency", - "options": "Company:company:default_currency", - "print_hide": 1, - "report_hide": 1 - }, - { - "description": "Cheating Field\nPlease do not delete ", - "doctype": "DocField", - "fieldname": "total_amount", - "fieldtype": "Currency", - "hidden": 1, - "label": "Total Amount", - "no_copy": 1, - "oldfieldname": "total_amount", - "oldfieldtype": "Currency", - "options": "Company:company:default_currency", - "print_hide": 1, - "report_hide": 1 - }, { "allow_on_submit": 0, "description": "If checked, the tax amount will be considered as already included in the Print Rate / Print Amount", diff --git a/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js b/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js index 1e72010f26..5787427339 100644 --- a/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js +++ b/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js @@ -140,7 +140,7 @@ cur_frm.fields_dict['other_charges'].grid.get_field("account_head").get_query = return 'SELECT tabAccount.name FROM tabAccount WHERE tabAccount.group_or_ledger="Ledger" AND tabAccount.docstatus != 2 AND tabAccount.account_type in ("Tax", "Chargeable", "Income Account") AND tabAccount.company = "'+doc.company+'" AND tabAccount.name LIKE "%s"' } -cur_frm.fields_dict['other_charges'].grid.get_field("cost_center_other_charges").get_query = function(doc) { +cur_frm.fields_dict['other_charges'].grid.get_field("cost_center").get_query = function(doc) { 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'; } diff --git a/accounts/page/accounts_browser/README.md b/accounts/page/accounts_browser/README.md new file mode 100644 index 0000000000..b8795613fc --- /dev/null +++ b/accounts/page/accounts_browser/README.md @@ -0,0 +1 @@ +Tree view browser for Chart of Accounts and Chart of Cost Centers \ No newline at end of file diff --git a/accounts/page/accounts_browser/accounts_browser.html b/accounts/page/accounts_browser/accounts_browser.html deleted file mode 100644 index 91a1e26b94..0000000000 --- a/accounts/page/accounts_browser/accounts_browser.html +++ /dev/null @@ -1,18 +0,0 @@ -
-
-
-
-
-
-

Quick Help

-
    -
  1. To add child nodes, explore tree and click on the node under which you want to add more nodes. -
  2. Accounting Entries can be made against leaf nodes, called Ledgers. Entries against Groups are not allowed. -
  3. Please do NOT create Account (Ledgers) for Customers and Suppliers. They are created directly from the Customer / Supplier masters. -
  4. To create a Bank Account: Go to the appropriate group (usually Application of Funds > Current Assets > Bank Accounts) and create a new Account Ledger (by clicking on Add Child) of type "Bank or Cash" -
  5. To create a Tax Account: Go to the appropriate group (usually Source of Funds > Current Liabilities > Taxes and Duties) and create a new Account Ledger (by clicking on Add Child) of type "Tax" and do mention the Tax rate. -
-

Please setup your chart of accounts before you start Accounting Entries

-
-
-
\ No newline at end of file diff --git a/accounts/page/accounts_browser/accounts_browser.js b/accounts/page/accounts_browser/accounts_browser.js index 2e8cc820a6..534201afdb 100644 --- a/accounts/page/accounts_browser/accounts_browser.js +++ b/accounts/page/accounts_browser/accounts_browser.js @@ -21,9 +21,37 @@ // see ledger pscript['onload_Accounts Browser'] = function(wrapper){ - wrapper.appframe = new wn.ui.AppFrame($(wrapper).find('.appframe-area')); - wrapper.appframe.add_home_breadcrumb() - wrapper.appframe.add_module_breadcrumb("Accounts") + wn.ui.make_app_page({ + parent: wrapper, + single_column: true + }) + + wrapper.appframe.add_module_icon("Accounts"); + + var main = $(wrapper).find(".layout-main"), + chart_area = $("
") + .css({"margin-bottom": "15px"}) + .appendTo(main), + help_area = $('
\ +

Quick Help

\ +
    \ +
  1. To add child nodes, explore tree and click on the node under which you \ + want to add more nodes.\ +
  2. Accounting Entries can be made against leaf nodes, called Ledgers.\ + Entries against Groups are not allowed.\ +
  3. Please do NOT create Account (Ledgers) for Customers and Suppliers. \ + They are created directly from the Customer / Supplier masters.\ +
  4. To create a Bank Account: Go to the appropriate group \ + (usually Application of Funds > Current Assets > Bank Accounts)\ + and create a new Account Ledger (by clicking on Add Child) of \ + type "Bank or Cash"\ +
  5. To create a Tax Account: Go to the appropriate group \ + (usually Source of Funds > Current Liabilities > Taxes and Duties) \ + and create a new Account Ledger (by clicking on Add Child) of type\ + "Tax" and do mention the Tax rate.\ +
\ +

Please setup your chart of accounts before you start Accounting Entries

\ +
').appendTo(main); if (wn.boot.profile.can_create.indexOf("Company") !== -1) { wrapper.appframe.add_button('New Company', function() { newdoc('Company'); }, @@ -35,13 +63,13 @@ pscript['onload_Accounts Browser'] = function(wrapper){ }, 'icon-refresh'); // company-select - wrapper.$company_select = $('') + wrapper.$company_select = wrapper.appframe.add_select("Company", []) .change(function() { var ctype = wn.get_route()[1] || 'Account'; - erpnext.account_chart = new erpnext.AccountsChart(ctype, $(this).val(), wrapper); + erpnext.account_chart = new erpnext.AccountsChart(ctype, $(this).val(), + chart_area.get(0)); pscript.set_title(wrapper, ctype, $(this).val()); }) - .appendTo(wrapper.appframe.$w.find('.appframe-toolbar')); // load up companies wn.call({ @@ -77,7 +105,7 @@ pscript['onshow_Accounts Browser'] = function(wrapper){ erpnext.AccountsChart = Class.extend({ init: function(ctype, company, wrapper) { - $(wrapper).find('.tree-area').empty(); + $(wrapper).empty(); var me = this; me.ctype = ctype; me.can_create = wn.model.can_create(this.ctype); @@ -87,7 +115,7 @@ erpnext.AccountsChart = Class.extend({ me.company = company; this.tree = new wn.ui.Tree({ - parent: $(wrapper).find('.tree-area'), + parent: $(wrapper), label: company, args: {ctype: ctype, comp: company}, method: 'accounts.page.accounts_browser.accounts_browser.get_children', diff --git a/accounts/page/financial_analytics/financial_analytics.js b/accounts/page/financial_analytics/financial_analytics.js index f7145490a1..aac7076519 100644 --- a/accounts/page/financial_analytics/financial_analytics.js +++ b/accounts/page/financial_analytics/financial_analytics.js @@ -25,7 +25,7 @@ wn.pages['financial-analytics'].onload = function(wrapper) { erpnext.trial_balance = new erpnext.FinancialAnalytics(wrapper, 'Financial Analytics'); wrapper.appframe.add_home_breadcrumb() - wrapper.appframe.add_module_breadcrumb("Accounts") + wrapper.appframe.add_module_icon("Accounts") wrapper.appframe.add_breadcrumb("icon-bar-chart") } diff --git a/accounts/page/financial_statements/financial_statements.html b/accounts/page/financial_statements/financial_statements.html index e6735facdc..bc2fce0ca7 100644 --- a/accounts/page/financial_statements/financial_statements.html +++ b/accounts/page/financial_statements/financial_statements.html @@ -1,28 +1,5 @@ -
+
-