[flat discount] flat discount implemented on sales cycle
This commit is contained in:
commit
d203aea7c2
@ -2,14 +2,14 @@
|
|||||||
{
|
{
|
||||||
"creation": "2011-12-21 11:08:55",
|
"creation": "2011-12-21 11:08:55",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"modified": "2013-09-13 17:17:47",
|
"modified": "2013-12-26 18:13:48",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"owner": "Administrator"
|
"owner": "Administrator"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"doc_type": "Sales Invoice",
|
"doc_type": "Sales Invoice",
|
||||||
"doctype": "Print Format",
|
"doctype": "Print Format",
|
||||||
"html": "<html>\n<head>\n<!--Item Table, Totals and Other Charges-->\n<script>\nfunction get_print_format() {\n var oc = getchildren('Sales Invoice Item', doc.name, 'entries');\n\tvar rows = '<table width=\"100%\" cellpadding=\"0\" class=\"cart\">\\\n <tr>\\\n <td colspan=\"3\"><hr></td>\\\n </tr>\\\n <tr>\\\n <td width=\"60%\" align=\"left\">ITEM NAME.</td>\\\n <td width=\"10%\" align=\"right\">QTY</td>\\\n <td width=\"30%\" align=\"right\">AMOUNT</td>\\\n </tr>\\\n <tr>\\\n <td colspan=\"3\"><hr></td>\\\n </tr>';\n\tfor (var x=0; x<oc.length; x++) {\n console.log(oc[x].item_code!=oc[x].item_name);\n\t\trows += '<tr>\\\n <td align=\"left\">' + oc[x].item_code + \n (oc[x].item_code!=oc[x].item_name ? ('<br>' + oc[x].item_name) : '') + '</td>\\\n <td align=\"right\" style=\"vertical-align:top;\">' + oc[x].qty + '</td>\\\n <td align=\"right\" valign=\"top\">' + format_currency(oc[x].export_amount, doc.currency) + '</td>\\\n </tr>';\n\t}\n rows += '<tr>\\\n <td colspan=\"3\"><hr></td>\\\n </tr>\\\n <tr>\\\n <td colspan=\"2\" align=\"right\">Net Total</td>\\\n <td align=\"right\">' + format_currency(doc.net_total_export, doc.currency) + '</td>\\\n </tr>';\n if (doc.other_charges_total_export != 0) {\n var taxes = wn.model.get_children(\"Sales Taxes and Charges\", doc.name, \"other_charges\", \"Sales Invoice\");\n\t\t$.each(taxes, function(i, d) {\n\t\t\trows += '<tr>\\\n \t\t\t\t<td colspan=\"2\" align=\"right\">' + d.description + '</td>\\\n \t\t\t\t<td style=\"text-align: right;\">' + format_currency(d.tax_amount / doc.conversion_rate, doc.currency) + '</td>\\\n \t\t\t<tr>';\n\t\t});\n }\n rows += '<tr>\\\n <td colspan=\"2\" align=\"right\" style=\"vertical-align:middle;\">Grand Total</td>\\\n <td align=\"right\"><hr width=\"90%\" align=\"right\">' + format_currency(doc.grand_total_export, doc.currency) + '<br>\\\n <hr width=\"90%\" align=\"right\"></td>\\\n </tr>\\\n <tr>\\\n <td align=\"center\" colspan=\"3\">Thank You. Please visit again.</td>\\\n </tr>\\\n </table>';\n\treturn rows;\n}\n</script>\n<style>\n table, tr, td, div, p {\n font-family: Monospace;\n line-height: 200%;\n }\n h1, h2, h3, h4, h5, h6 {\n text-align: center;\n }\n\t@media screen {\n\t\tbody {\n\t\t\twidth: 4in;\n\t\t}\n\t}\n</style>\n</head>\n\n<body>\n<table width=\"100%\" cellpadding=\"4\">\n <tr>\n <td align=\"left\">RECEIPT NO: <script>doc.name</script></td>\n <td align=\"right\">DATE: <script>date.str_to_user(doc.posting_date)</script></td>\n </tr>\n <tr>\n <td>M/s <script>doc.customer</script></td>\n </tr>\n</table>\n<!--Item Table & Totals-->\n<div><script>get_print_format();</script></div>\n</body>\n</html>\n",
|
"html": "<html>\n<head>\n<!--Item Table, Totals and Other Charges-->\n<script>\nfunction get_print_format() {\n\tvar oc = getchildren('Sales Invoice Item', doc.name, 'entries');\n\tvar rows = '<table width=\"100%\" cellpadding=\"0\" class=\"cart\">\\\n <tr>\\\n <td colspan=\"3\"><hr></td>\\\n </tr>\\\n <tr>\\\n <td width=\"60%\" align=\"left\">ITEM NAME</td>\\\n <td width=\"10%\" align=\"right\">QTY</td>\\\n <td width=\"30%\" align=\"right\">AMOUNT</td>\\\n </tr>\\\n <tr>\\\n <td colspan=\"3\"><hr></td>\\\n </tr>';\n\n\tfor (var x=0; x<oc.length; x++) {\n\t\trows += '<tr>\\\n <td align=\"left\">' + oc[x].item_code + \n (oc[x].item_code!=oc[x].item_name ? ('<br>' + oc[x].item_name) : '') + '</td>\\\n <td align=\"right\" style=\"vertical-align:top;\">' + oc[x].qty + '</td>\\\n <td align=\"right\" valign=\"top\">' + format_currency(oc[x].export_amount, doc.currency) + '</td>\\\n </tr>';\n\t}\n\n rows += '<tr>\\\n <td colspan=\"3\"><hr></td>\\\n </tr>\\\n <tr>\\\n <td colspan=\"2\" align=\"right\"><b>Net Total</b></td>\\\n <td align=\"right\">' + format_currency(doc.net_total_export, doc.currency) + '</td>\\\n </tr>';\n\n if (doc.other_charges_total_export != 0) {\n var taxes = wn.model.get_children(\"Sales Taxes and Charges\", doc.name, \"other_charges\", \"Sales Invoice\");\n\t\t$.each(taxes, function(i, d) {\n\t\t\trows += '<tr>\\\n \t\t\t\t<td colspan=\"2\" align=\"right\">' + d.description + '</td>\\\n \t\t\t\t<td style=\"text-align: right;\">' + format_currency(d.tax_amount / doc.conversion_rate, doc.currency) + '</td>\\\n \t\t\t<tr>';\n\t\t});\n }\n\n if (doc.flat_discount) {\n\t\trows += '<tr>\\\n \t\t\t<td colspan=\"2\" align=\"right\" style=\"vertical-align:middle;\">Flat Discount</td>\\\n \t\t\t<td style=\"text-align: right;\">' + format_currency(doc.flat_discount, doc.currency) + '</td>\\\n \t\t<tr>';\n }\n\n rows += '<tr>\\\n <td colspan=\"2\" align=\"right\" style=\"vertical-align:middle;\"><b>Grand Total</b></td>\\\n <td align=\"right\"><hr width=\"90%\" align=\"right\">' + format_currency(doc.grand_total_export, doc.currency) + '<br>\\\n <hr width=\"90%\" align=\"right\"></td>\\\n </tr>\\\n <tr>\\\n <td align=\"center\" colspan=\"3\">Thank You. Please visit again.</td>\\\n </tr>\\\n </table>';\n\treturn rows;\n}\n</script>\n<style>\n table, tr, td, div, p {\n font-family: Monospace;\n line-height: 200%;\n }\n h1, h2, h3, h4, h5, h6 {\n text-align: center;\n }\n\t@media screen {\n\t\tbody {\n\t\t\twidth: 4in;\n\t\t}\n\t}\n</style>\n</head>\n\n<body>\n<table width=\"100%\" cellpadding=\"4\">\n <tr>\n <td align=\"left\">RECEIPT NO: <script>doc.name</script></td>\n <td align=\"right\">DATE: <script>date.str_to_user(doc.posting_date)</script></td>\n </tr>\n <tr>\n <td>M/s <script>doc.customer</script></td>\n </tr>\n</table>\n<!--Item Table & Totals-->\n<div><script>get_print_format();</script></div>\n</body>\n</html>\n",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "__common__",
|
"name": "__common__",
|
||||||
"print_format_type": "Client",
|
"print_format_type": "Client",
|
||||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -30,12 +30,14 @@ erpnext.POS = Class.extend({
|
|||||||
</div>\
|
</div>\
|
||||||
<br>\
|
<br>\
|
||||||
<div class="totals-area" style="margin-left: 40%;">\
|
<div class="totals-area" style="margin-left: 40%;">\
|
||||||
<table class="table table-condensed">\
|
<div class="net-total-area">\
|
||||||
<tr>\
|
<table class="table table-condensed">\
|
||||||
<td><b>Net Total</b></td>\
|
<tr>\
|
||||||
<td style="text-align: right;" class="net-total"></td>\
|
<td><b>Net Total</b></td>\
|
||||||
</tr>\
|
<td style="text-align: right;" class="net-total"></td>\
|
||||||
</table>\
|
</tr>\
|
||||||
|
</table>\
|
||||||
|
</div>\
|
||||||
<div class="tax-table" style="display: none;">\
|
<div class="tax-table" style="display: none;">\
|
||||||
<table class="table table-condensed">\
|
<table class="table table-condensed">\
|
||||||
<thead>\
|
<thead>\
|
||||||
@ -48,6 +50,18 @@ erpnext.POS = Class.extend({
|
|||||||
</tbody>\
|
</tbody>\
|
||||||
</table>\
|
</table>\
|
||||||
</div>\
|
</div>\
|
||||||
|
<div class="flat-discount-area">\
|
||||||
|
<table class="table table-condensed">\
|
||||||
|
<tr>\
|
||||||
|
<td style="vertical-align: middle;" width="50%"><b>Flat Discount</b></td>\
|
||||||
|
<td width="20%"></td>\
|
||||||
|
<td style="text-align: right;">\
|
||||||
|
<input type="text" class="form-control flat-discount" \
|
||||||
|
style="text-align: right;">\
|
||||||
|
</td>\
|
||||||
|
</tr>\
|
||||||
|
</table>\
|
||||||
|
</div>\
|
||||||
<div class="grand-total-area">\
|
<div class="grand-total-area">\
|
||||||
<table class="table table-condensed">\
|
<table class="table table-condensed">\
|
||||||
<tr>\
|
<tr>\
|
||||||
@ -82,6 +96,10 @@ erpnext.POS = Class.extend({
|
|||||||
me.refresh();
|
me.refresh();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.wrapper.find('input.flat-discount').on("change", function() {
|
||||||
|
wn.model.set_value(me.frm.doctype, me.frm.docname, "flat_discount", this.value);
|
||||||
|
});
|
||||||
|
|
||||||
this.call_function("delete-items", function() {me.remove_selected_item();});
|
this.call_function("delete-items", function() {me.remove_selected_item();});
|
||||||
this.call_function("make-payment", function() {me.make_payment();});
|
this.call_function("make-payment", function() {me.make_payment();});
|
||||||
},
|
},
|
||||||
@ -112,9 +130,9 @@ erpnext.POS = Class.extend({
|
|||||||
},
|
},
|
||||||
make: function() {
|
make: function() {
|
||||||
this.make_party();
|
this.make_party();
|
||||||
this.make_item_group();
|
|
||||||
this.make_search();
|
|
||||||
this.make_barcode();
|
this.make_barcode();
|
||||||
|
this.make_search();
|
||||||
|
this.make_item_group();
|
||||||
this.make_item_list();
|
this.make_item_list();
|
||||||
},
|
},
|
||||||
make_party: function() {
|
make_party: function() {
|
||||||
@ -137,23 +155,23 @@ erpnext.POS = Class.extend({
|
|||||||
me.party.toLowerCase(), this.value);
|
me.party.toLowerCase(), this.value);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
make_item_group: function() {
|
make_barcode: function() {
|
||||||
var me = this;
|
var me = this;
|
||||||
this.item_group = wn.ui.form.make_control({
|
this.barcode = wn.ui.form.make_control({
|
||||||
df: {
|
df: {
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Data",
|
||||||
"options": "Item Group",
|
"label": "Barcode",
|
||||||
"label": "Item Group",
|
"fieldname": "pos_barcode",
|
||||||
"fieldname": "pos_item_group",
|
"placeholder": "Barcode / Serial No"
|
||||||
"placeholder": "Item Group"
|
|
||||||
},
|
},
|
||||||
parent: this.wrapper.find(".item-group-area"),
|
parent: this.wrapper.find(".barcode-area"),
|
||||||
only_input: true,
|
only_input: true,
|
||||||
});
|
});
|
||||||
this.item_group.make_input();
|
this.barcode.make_input();
|
||||||
this.item_group.$input.on("change", function() {
|
this.barcode.$input.on("keypress", function() {
|
||||||
if(!me.item_group.autocomplete_open)
|
if(me.barcode_timeout)
|
||||||
me.make_item_list();
|
clearTimeout(me.barcode_timeout);
|
||||||
|
me.barcode_timeout = setTimeout(function() { me.add_item_thru_barcode(); }, 1000);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
make_search: function() {
|
make_search: function() {
|
||||||
@ -176,23 +194,23 @@ erpnext.POS = Class.extend({
|
|||||||
me.item_timeout = setTimeout(function() { me.make_item_list(); }, 1000);
|
me.item_timeout = setTimeout(function() { me.make_item_list(); }, 1000);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
make_barcode: function() {
|
make_item_group: function() {
|
||||||
var me = this;
|
var me = this;
|
||||||
this.barcode = wn.ui.form.make_control({
|
this.item_group = wn.ui.form.make_control({
|
||||||
df: {
|
df: {
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Link",
|
||||||
"label": "Barcode",
|
"options": "Item Group",
|
||||||
"fieldname": "pos_barcode",
|
"label": "Item Group",
|
||||||
"placeholder": "Barcode / Serial No"
|
"fieldname": "pos_item_group",
|
||||||
|
"placeholder": "Item Group"
|
||||||
},
|
},
|
||||||
parent: this.wrapper.find(".barcode-area"),
|
parent: this.wrapper.find(".item-group-area"),
|
||||||
only_input: true,
|
only_input: true,
|
||||||
});
|
});
|
||||||
this.barcode.make_input();
|
this.item_group.make_input();
|
||||||
this.barcode.$input.on("keypress", function() {
|
this.item_group.$input.on("change", function() {
|
||||||
if(me.barcode_timeout)
|
if(!me.item_group.autocomplete_open)
|
||||||
clearTimeout(me.barcode_timeout);
|
me.make_item_list();
|
||||||
me.barcode_timeout = setTimeout(function() { me.add_item_thru_barcode(); }, 1000);
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
make_item_list: function() {
|
make_item_list: function() {
|
||||||
@ -321,6 +339,7 @@ erpnext.POS = Class.extend({
|
|||||||
refresh: function() {
|
refresh: function() {
|
||||||
var me = this;
|
var me = this;
|
||||||
this.party_field.set_input(this.frm.doc[this.party.toLowerCase()]);
|
this.party_field.set_input(this.frm.doc[this.party.toLowerCase()]);
|
||||||
|
this.wrapper.find('input.flat-discount').val(this.frm.doc.flat_discount);
|
||||||
this.barcode.set_input("");
|
this.barcode.set_input("");
|
||||||
|
|
||||||
this.show_items_in_item_cart();
|
this.show_items_in_item_cart();
|
||||||
|
@ -25,7 +25,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
|||||||
}
|
}
|
||||||
|
|
||||||
// toggle to pos view if is_pos is 1 in user_defaults
|
// toggle to pos view if is_pos is 1 in user_defaults
|
||||||
if ((cint(wn.defaults.get_user_defaults("is_pos"))===1 || cur_frm.doc.is_pos)) {
|
if ((cint(wn.defaults.get_user_defaults("is_pos"))===1 || this.frm.doc.is_pos)) {
|
||||||
if(this.frm.doc.__islocal && !this.frm.doc.amended_from && !this.frm.doc.customer) {
|
if(this.frm.doc.__islocal && !this.frm.doc.amended_from && !this.frm.doc.customer) {
|
||||||
this.frm.set_value("is_pos", 1);
|
this.frm.set_value("is_pos", 1);
|
||||||
this.is_pos(function() {
|
this.is_pos(function() {
|
||||||
@ -145,8 +145,8 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
|||||||
me.set_default_values();
|
me.set_default_values();
|
||||||
me.set_dynamic_labels();
|
me.set_dynamic_labels();
|
||||||
me.calculate_taxes_and_totals();
|
me.calculate_taxes_and_totals();
|
||||||
|
|
||||||
if(callback_fn) callback_fn()
|
if(callback_fn) callback_fn();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -334,7 +334,7 @@ cur_frm.fields_dict['project_name'].get_query = function(doc, cdt, cdn) {
|
|||||||
// --------------------------------
|
// --------------------------------
|
||||||
cur_frm.set_query("income_account", "entries", function(doc) {
|
cur_frm.set_query("income_account", "entries", function(doc) {
|
||||||
return{
|
return{
|
||||||
query: "accounts.doctype.sales_invoice.sales_invoice.get_income_account",
|
query: "erpnext.accounts.doctype.sales_invoice.sales_invoice.get_income_account",
|
||||||
filters: {'company': doc.company}
|
filters: {'company': doc.company}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -556,12 +556,12 @@ class DocType(SellingController):
|
|||||||
|
|
||||||
def make_tax_gl_entries(self, gl_entries):
|
def make_tax_gl_entries(self, gl_entries):
|
||||||
for tax in self.doclist.get({"parentfield": "other_charges"}):
|
for tax in self.doclist.get({"parentfield": "other_charges"}):
|
||||||
if flt(tax.tax_amount):
|
if flt(tax.tax_amount_after_flat_discount):
|
||||||
gl_entries.append(
|
gl_entries.append(
|
||||||
self.get_gl_dict({
|
self.get_gl_dict({
|
||||||
"account": tax.account_head,
|
"account": tax.account_head,
|
||||||
"against": self.doc.debit_to,
|
"against": self.doc.debit_to,
|
||||||
"credit": flt(tax.tax_amount),
|
"credit": flt(tax.tax_amount_after_flat_discount),
|
||||||
"remarks": self.doc.remarks,
|
"remarks": self.doc.remarks,
|
||||||
"cost_center": tax.cost_center
|
"cost_center": tax.cost_center
|
||||||
})
|
})
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
{
|
{
|
||||||
"creation": "2013-05-24 19:29:05",
|
"creation": "2013-05-24 19:29:05",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"modified": "2013-12-20 19:24:29",
|
"modified": "2013-12-26 17:50:21",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"owner": "Administrator"
|
"owner": "Administrator"
|
||||||
},
|
},
|
||||||
@ -455,6 +455,14 @@
|
|||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"doctype": "DocField",
|
||||||
|
"fieldname": "flat_discount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"label": "Flat Discount",
|
||||||
|
"options": "Company:company:default_currency",
|
||||||
|
"print_hide": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"doctype": "DocField",
|
"doctype": "DocField",
|
||||||
"fieldname": "totals",
|
"fieldname": "totals",
|
||||||
|
@ -44,7 +44,6 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
|
|
||||||
def test_sales_invoice_calculation_base_currency(self):
|
def test_sales_invoice_calculation_base_currency(self):
|
||||||
si = webnotes.bean(copy=test_records[2])
|
si = webnotes.bean(copy=test_records[2])
|
||||||
si.run_method("calculate_taxes_and_totals")
|
|
||||||
si.insert()
|
si.insert()
|
||||||
|
|
||||||
expected_values = {
|
expected_values = {
|
||||||
@ -136,7 +135,114 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertEquals(si.doc.grand_total, 1627.05)
|
self.assertEquals(si.doc.grand_total, 1627.05)
|
||||||
self.assertEquals(si.doc.grand_total_export, 32.54)
|
self.assertEquals(si.doc.grand_total_export, 32.54)
|
||||||
|
|
||||||
|
def test_sales_invoice_flat_discount(self):
|
||||||
|
si = webnotes.bean(copy=test_records[3])
|
||||||
|
si.doc.flat_discount = 104.95
|
||||||
|
si.doclist.append({
|
||||||
|
"doctype": "Sales Taxes and Charges",
|
||||||
|
"parentfield": "other_charges",
|
||||||
|
"charge_type": "On Previous Row Amount",
|
||||||
|
"account_head": "_Test Account Service Tax - _TC",
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
"description": "Service Tax",
|
||||||
|
"rate": 10,
|
||||||
|
"row_id": 8,
|
||||||
|
"idx": 9
|
||||||
|
})
|
||||||
|
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, 465.37],
|
||||||
|
"_Test Item Home Desktop 200": [190.66, 0, 190.66, 953.3, 150, 150, 698.08],
|
||||||
|
}
|
||||||
|
|
||||||
|
# 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, 1163.45)
|
||||||
|
self.assertEquals(si.doc.net_total_export, 1578.3)
|
||||||
|
|
||||||
|
# check tax calculation
|
||||||
|
expected_values = {
|
||||||
|
"keys": ["tax_amount", "tax_amount_after_flat_discount", "total"],
|
||||||
|
"_Test Account Excise Duty - _TC": [140, 130.31, 1293.76],
|
||||||
|
"_Test Account Education Cess - _TC": [2.8, 2.61, 1296.37],
|
||||||
|
"_Test Account S&H Education Cess - _TC": [1.4, 1.31, 1297.68],
|
||||||
|
"_Test Account CST - _TC": [27.88, 25.96, 1323.64],
|
||||||
|
"_Test Account VAT - _TC": [156.25, 145.43, 1469.07],
|
||||||
|
"_Test Account Customs Duty - _TC": [125, 116.35, 1585.42],
|
||||||
|
"_Test Account Shipping Charges - _TC": [100, 100, 1685.42],
|
||||||
|
"_Test Account Discount - _TC": [-180.33, -168.54, 1516.88],
|
||||||
|
"_Test Account Service Tax - _TC": [-18.03, -16.88, 1500]
|
||||||
|
}
|
||||||
|
|
||||||
|
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, 1500)
|
||||||
|
self.assertEquals(si.doc.grand_total_export, 1500)
|
||||||
|
|
||||||
|
def test_flat_discount_gl_entry(self):
|
||||||
|
si = webnotes.bean(copy=test_records[3])
|
||||||
|
si.doc.flat_discount = 104.95
|
||||||
|
si.doclist.append({
|
||||||
|
"doctype": "Sales Taxes and Charges",
|
||||||
|
"parentfield": "other_charges",
|
||||||
|
"charge_type": "On Previous Row Amount",
|
||||||
|
"account_head": "_Test Account Service Tax - _TC",
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
"description": "Service Tax",
|
||||||
|
"rate": 10,
|
||||||
|
"row_id": 8,
|
||||||
|
"idx": 9
|
||||||
|
})
|
||||||
|
si.insert()
|
||||||
|
si.submit()
|
||||||
|
|
||||||
|
gl_entries = webnotes.conn.sql("""select account, debit, credit
|
||||||
|
from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s
|
||||||
|
order by account asc""", si.doc.name, as_dict=1)
|
||||||
|
|
||||||
|
self.assertTrue(gl_entries)
|
||||||
|
|
||||||
|
expected_values = sorted([
|
||||||
|
[si.doc.debit_to, 1500, 0.0],
|
||||||
|
[test_records[3][1]["income_account"], 0.0, 1163.45],
|
||||||
|
[test_records[3][3]["account_head"], 0.0, 130.31],
|
||||||
|
[test_records[3][4]["account_head"], 0.0, 2.61],
|
||||||
|
[test_records[3][5]["account_head"], 0.0, 1.31],
|
||||||
|
[test_records[3][6]["account_head"], 0.0, 25.96],
|
||||||
|
[test_records[3][7]["account_head"], 0.0, 145.43],
|
||||||
|
[test_records[3][8]["account_head"], 0.0, 116.35],
|
||||||
|
[test_records[3][9]["account_head"], 0.0, 100],
|
||||||
|
[test_records[3][10]["account_head"], 168.54, 0.0],
|
||||||
|
["_Test Account Service Tax - _TC", 16.88, 0.0],
|
||||||
|
])
|
||||||
|
|
||||||
|
for i, gle in enumerate(gl_entries):
|
||||||
|
self.assertEquals(expected_values[i][0], gle.account)
|
||||||
|
self.assertEquals(expected_values[i][1], gle.debit)
|
||||||
|
self.assertEquals(expected_values[i][2], gle.credit)
|
||||||
|
|
||||||
|
# cancel
|
||||||
|
si.cancel()
|
||||||
|
|
||||||
|
gle = webnotes.conn.sql("""select * from `tabGL Entry`
|
||||||
|
where voucher_type='Sales Invoice' and voucher_no=%s""", si.doc.name)
|
||||||
|
|
||||||
|
self.assertFalse(gle)
|
||||||
|
|
||||||
def test_inclusive_rate_validations(self):
|
def test_inclusive_rate_validations(self):
|
||||||
si = webnotes.bean(copy=test_records[2])
|
si = webnotes.bean(copy=test_records[2])
|
||||||
for i, tax in enumerate(si.doclist.get({"parentfield": "other_charges"})):
|
for i, tax in enumerate(si.doclist.get({"parentfield": "other_charges"})):
|
||||||
@ -148,16 +254,15 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
si.doclist[i].included_in_print_rate = 1
|
si.doclist[i].included_in_print_rate = 1
|
||||||
|
|
||||||
# tax type "Actual" cannot be inclusive
|
# tax type "Actual" cannot be inclusive
|
||||||
self.assertRaises(webnotes.ValidationError, si.run_method, "calculate_taxes_and_totals")
|
self.assertRaises(webnotes.ValidationError, si.insert)
|
||||||
|
|
||||||
# taxes above included type 'On Previous Row Total' should also be included
|
# taxes above included type 'On Previous Row Total' should also be included
|
||||||
si.doclist[3].included_in_print_rate = 0
|
si.doclist[3].included_in_print_rate = 0
|
||||||
self.assertRaises(webnotes.ValidationError, si.run_method, "calculate_taxes_and_totals")
|
self.assertRaises(webnotes.ValidationError, si.insert)
|
||||||
|
|
||||||
def test_sales_invoice_calculation_base_currency_with_tax_inclusive_price(self):
|
def test_sales_invoice_calculation_base_currency_with_tax_inclusive_price(self):
|
||||||
# prepare
|
# prepare
|
||||||
si = webnotes.bean(copy=test_records[3])
|
si = webnotes.bean(copy=test_records[3])
|
||||||
si.run_method("calculate_taxes_and_totals")
|
|
||||||
si.insert()
|
si.insert()
|
||||||
|
|
||||||
expected_values = {
|
expected_values = {
|
||||||
@ -195,7 +300,7 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
|
|
||||||
for d in si.doclist.get({"parentfield": "other_charges"}):
|
for d in si.doclist.get({"parentfield": "other_charges"}):
|
||||||
for i, k in enumerate(expected_values["keys"]):
|
for i, k in enumerate(expected_values["keys"]):
|
||||||
self.assertEquals(flt(d.fields.get(k), 6), expected_values[d.account_head][i])
|
self.assertEquals(d.fields.get(k), expected_values[d.account_head][i])
|
||||||
|
|
||||||
self.assertEquals(si.doc.grand_total, 1622.98)
|
self.assertEquals(si.doc.grand_total, 1622.98)
|
||||||
self.assertEquals(si.doc.grand_total_export, 1622.98)
|
self.assertEquals(si.doc.grand_total_export, 1622.98)
|
||||||
@ -211,7 +316,6 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
si.doclist[2].adj_rate = 20
|
si.doclist[2].adj_rate = 20
|
||||||
si.doclist[9].rate = 5000
|
si.doclist[9].rate = 5000
|
||||||
|
|
||||||
si.run_method("calculate_taxes_and_totals")
|
|
||||||
si.insert()
|
si.insert()
|
||||||
|
|
||||||
expected_values = {
|
expected_values = {
|
||||||
@ -249,7 +353,7 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
|
|
||||||
for d in si.doclist.get({"parentfield": "other_charges"}):
|
for d in si.doclist.get({"parentfield": "other_charges"}):
|
||||||
for i, k in enumerate(expected_values["keys"]):
|
for i, k in enumerate(expected_values["keys"]):
|
||||||
self.assertEquals(flt(d.fields.get(k), 6), expected_values[d.account_head][i])
|
self.assertEquals(d.fields.get(k), expected_values[d.account_head][i])
|
||||||
|
|
||||||
self.assertEquals(si.doc.grand_total, 65205.16)
|
self.assertEquals(si.doc.grand_total, 65205.16)
|
||||||
self.assertEquals(si.doc.grand_total_export, 1304.1)
|
self.assertEquals(si.doc.grand_total_export, 1304.1)
|
||||||
@ -364,7 +468,6 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s
|
from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s
|
||||||
order by account asc, debit asc""", si.doc.name, as_dict=1)
|
order by account asc, debit asc""", si.doc.name, as_dict=1)
|
||||||
self.assertTrue(gl_entries)
|
self.assertTrue(gl_entries)
|
||||||
# print gl_entries
|
|
||||||
|
|
||||||
stock_in_hand = webnotes.conn.get_value("Account", {"master_name": "_Test Warehouse - _TC"})
|
stock_in_hand = webnotes.conn.get_value("Account", {"master_name": "_Test Warehouse - _TC"})
|
||||||
|
|
||||||
@ -404,7 +507,6 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
pr = webnotes.bean(copy=pr_test_records[0])
|
pr = webnotes.bean(copy=pr_test_records[0])
|
||||||
pr.doc.naming_series = "_T-Purchase Receipt-"
|
pr.doc.naming_series = "_T-Purchase Receipt-"
|
||||||
pr.doclist[1].warehouse = "_Test Warehouse No Account - _TC"
|
pr.doclist[1].warehouse = "_Test Warehouse No Account - _TC"
|
||||||
pr.run_method("calculate_taxes_and_totals")
|
|
||||||
pr.insert()
|
pr.insert()
|
||||||
pr.submit()
|
pr.submit()
|
||||||
|
|
||||||
@ -449,7 +551,7 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
self.assertFalse(gle)
|
self.assertFalse(gle)
|
||||||
set_perpetual_inventory(0)
|
set_perpetual_inventory(0)
|
||||||
|
|
||||||
def test_sales_invoice_gl_entry_with_aii_no_item_code(self):
|
def test_sales_invoice_gl_entry_with_aii_no_item_code(self):
|
||||||
self.clear_stock_account_balance()
|
self.clear_stock_account_balance()
|
||||||
set_perpetual_inventory()
|
set_perpetual_inventory()
|
||||||
|
|
||||||
@ -509,7 +611,6 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
as pr_test_records
|
as pr_test_records
|
||||||
pr = webnotes.bean(copy=pr_test_records[0])
|
pr = webnotes.bean(copy=pr_test_records[0])
|
||||||
pr.doc.naming_series = "_T-Purchase Receipt-"
|
pr.doc.naming_series = "_T-Purchase Receipt-"
|
||||||
pr.run_method("calculate_taxes_and_totals")
|
|
||||||
pr.insert()
|
pr.insert()
|
||||||
pr.submit()
|
pr.submit()
|
||||||
|
|
||||||
|
@ -131,12 +131,21 @@
|
|||||||
"options": "Company:company:default_currency",
|
"options": "Company:company:default_currency",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"doctype": "DocField",
|
||||||
|
"fieldname": "tax_amount_after_flat_discount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"hidden": 1,
|
||||||
|
"label": "Tax Amount After Flat Discount",
|
||||||
|
"options": "Company:company:default_currency",
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"doctype": "DocField",
|
"doctype": "DocField",
|
||||||
"fieldname": "item_wise_tax_detail",
|
"fieldname": "item_wise_tax_detail",
|
||||||
"fieldtype": "Small Text",
|
"fieldtype": "Small Text",
|
||||||
"hidden": 1,
|
"hidden": 1,
|
||||||
"label": "Item Wise Tax Detail ",
|
"label": "Item Wise Tax Detail",
|
||||||
"oldfieldname": "item_wise_tax_detail",
|
"oldfieldname": "item_wise_tax_detail",
|
||||||
"oldfieldtype": "Small Text",
|
"oldfieldtype": "Small Text",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
|
@ -19,6 +19,10 @@ cur_frm.pformat.net_total_export = function(doc) {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cur_frm.pformat.flat_discount = function(doc) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
cur_frm.pformat.grand_total_export = function(doc) {
|
cur_frm.pformat.grand_total_export = function(doc) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
@ -33,10 +37,10 @@ cur_frm.pformat.in_words_export = function(doc) {
|
|||||||
|
|
||||||
cur_frm.pformat.other_charges= function(doc){
|
cur_frm.pformat.other_charges= function(doc){
|
||||||
//function to make row of table
|
//function to make row of table
|
||||||
var make_row = function(title,val,bold){
|
var make_row = function(title, val, bold){
|
||||||
var bstart = '<b>'; var bend = '</b>';
|
var bstart = '<b>'; var bend = '</b>';
|
||||||
return '<tr><td style="width:50%;">'+(bold?bstart:'')+title+(bold?bend:'')+'</td>'
|
return '<tr><td style="width:50%;">' + (bold?bstart:'') + title + (bold?bend:'') + '</td>'
|
||||||
+'<td style="width:50%;text-align:right;">'+format_currency(val, doc.currency)+'</td>'
|
+'<td style="width:50%;text-align:right;">' + format_currency(val, doc.currency) + '</td>'
|
||||||
+'</tr>'
|
+'</tr>'
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,7 +56,7 @@ cur_frm.pformat.other_charges= function(doc){
|
|||||||
|
|
||||||
out ='';
|
out ='';
|
||||||
if (!doc.print_without_amount) {
|
if (!doc.print_without_amount) {
|
||||||
var cl = getchildren('Sales Taxes and Charges',doc.name,'other_charges');
|
var cl = getchildren('Sales Taxes and Charges', doc.name, 'other_charges');
|
||||||
|
|
||||||
// outer table
|
// outer table
|
||||||
var out='<div><table class="noborder" style="width:100%"><tr><td style="width: 60%"></td><td>';
|
var out='<div><table class="noborder" style="width:100%"><tr><td style="width: 60%"></td><td>';
|
||||||
@ -60,6 +64,7 @@ cur_frm.pformat.other_charges= function(doc){
|
|||||||
// main table
|
// main table
|
||||||
|
|
||||||
out +='<table class="noborder" style="width:100%">';
|
out +='<table class="noborder" style="width:100%">';
|
||||||
|
|
||||||
if(!print_hide('net_total_export')) {
|
if(!print_hide('net_total_export')) {
|
||||||
out += make_row('Net Total', doc.net_total_export, 1);
|
out += make_row('Net Total', doc.net_total_export, 1);
|
||||||
}
|
}
|
||||||
@ -68,26 +73,31 @@ cur_frm.pformat.other_charges= function(doc){
|
|||||||
if(cl.length){
|
if(cl.length){
|
||||||
for(var i=0;i<cl.length;i++){
|
for(var i=0;i<cl.length;i++){
|
||||||
if(convert_rate(cl[i].tax_amount)!=0 && !cl[i].included_in_print_rate)
|
if(convert_rate(cl[i].tax_amount)!=0 && !cl[i].included_in_print_rate)
|
||||||
out += make_row(cl[i].description,convert_rate(cl[i].tax_amount),0);
|
out += make_row(cl[i].description, convert_rate(cl[i].tax_amount), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// flat discount
|
||||||
|
if(!print_hide('flat_discount') && doc.flat_discount) {
|
||||||
|
out += make_row('Flat Discount', doc.flat_discount, 0);
|
||||||
|
}
|
||||||
|
|
||||||
// grand total
|
// grand total
|
||||||
if(!print_hide('grand_total_export')) {
|
if(!print_hide('grand_total_export')) {
|
||||||
out += make_row('Grand Total',doc.grand_total_export,1);
|
out += make_row('Grand Total', doc.grand_total_export, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!print_hide('rounded_total_export')) {
|
if(!print_hide('rounded_total_export')) {
|
||||||
out += make_row('Rounded Total',doc.rounded_total_export,1);
|
out += make_row('Rounded Total', doc.rounded_total_export, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(doc.in_words_export && !print_hide('in_words_export')){
|
if(doc.in_words_export && !print_hide('in_words_export')){
|
||||||
out +='</table></td></tr>';
|
out +='</table></td></tr>';
|
||||||
out += '<tr><td colspan = "2">';
|
out += '<tr><td colspan = "2">';
|
||||||
out += '<table><tr><td style="width:25%;"><b>In Words</b></td>'
|
out += '<table><tr><td style="width:25%;"><b>In Words</b></td>'
|
||||||
out+= '<td style="width:50%;">'+doc.in_words_export+'</td></tr>'
|
out += '<td style="width:50%;">' + doc.in_words_export + '</td></tr>'
|
||||||
}
|
}
|
||||||
out +='</table></td></tr></table></div>';
|
out += '</table></td></tr></table></div>';
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@ -99,7 +109,7 @@ cur_frm.cscript.charge_type = function(doc, cdt, cdn) {
|
|||||||
d.charge_type = '';
|
d.charge_type = '';
|
||||||
}
|
}
|
||||||
validated = false;
|
validated = false;
|
||||||
refresh_field('charge_type',d.name,'other_charges');
|
refresh_field('charge_type', d.name, 'other_charges');
|
||||||
cur_frm.cscript.row_id(doc, cdt, cdn);
|
cur_frm.cscript.row_id(doc, cdt, cdn);
|
||||||
cur_frm.cscript.rate(doc, cdt, cdn);
|
cur_frm.cscript.rate(doc, cdt, cdn);
|
||||||
cur_frm.cscript.tax_amount(doc, cdt, cdn);
|
cur_frm.cscript.tax_amount(doc, cdt, cdn);
|
||||||
@ -122,7 +132,7 @@ cur_frm.cscript.row_id = function(doc, cdt, cdn) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
validated = false;
|
validated = false;
|
||||||
refresh_field('row_id',d.name,'other_charges');
|
refresh_field('row_id', d.name, 'other_charges');
|
||||||
}
|
}
|
||||||
|
|
||||||
/*---------------------- Get rate if account_head has account_type as TAX or CHARGEABLE-------------------------------------*/
|
/*---------------------- Get rate if account_head has account_type as TAX or CHARGEABLE-------------------------------------*/
|
||||||
@ -152,7 +162,7 @@ cur_frm.cscript.rate = function(doc, cdt, cdn) {
|
|||||||
d.rate = '';
|
d.rate = '';
|
||||||
}
|
}
|
||||||
validated = false;
|
validated = false;
|
||||||
refresh_field('rate',d.name,'other_charges');
|
refresh_field('rate', d.name, 'other_charges');
|
||||||
}
|
}
|
||||||
|
|
||||||
cur_frm.cscript.tax_amount = function(doc, cdt, cdn) {
|
cur_frm.cscript.tax_amount = function(doc, cdt, cdn) {
|
||||||
@ -166,5 +176,5 @@ cur_frm.cscript.tax_amount = function(doc, cdt, cdn) {
|
|||||||
d.tax_amount = '';
|
d.tax_amount = '';
|
||||||
}
|
}
|
||||||
validated = false;
|
validated = false;
|
||||||
refresh_field('tax_amount',d.name,'other_charges');
|
refresh_field('tax_amount', d.name, 'other_charges');
|
||||||
};
|
};
|
@ -79,7 +79,7 @@ def get_columns(invoice_list):
|
|||||||
|
|
||||||
tax_accounts = webnotes.conn.sql_list("""select distinct account_head
|
tax_accounts = webnotes.conn.sql_list("""select distinct account_head
|
||||||
from `tabSales Taxes and Charges` where parenttype = 'Sales Invoice'
|
from `tabSales Taxes and Charges` where parenttype = 'Sales Invoice'
|
||||||
and docstatus = 1 and ifnull(tax_amount, 0) != 0
|
and docstatus = 1 and ifnull(tax_amount_after_flat_discount, 0) != 0
|
||||||
and parent in (%s) order by account_head""" %
|
and parent in (%s) order by account_head""" %
|
||||||
', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]))
|
', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]))
|
||||||
|
|
||||||
@ -126,7 +126,8 @@ def get_invoice_income_map(invoice_list):
|
|||||||
return invoice_income_map
|
return invoice_income_map
|
||||||
|
|
||||||
def get_invoice_tax_map(invoice_list, invoice_income_map, income_accounts):
|
def get_invoice_tax_map(invoice_list, invoice_income_map, income_accounts):
|
||||||
tax_details = webnotes.conn.sql("""select parent, account_head, sum(tax_amount) as tax_amount
|
tax_details = webnotes.conn.sql("""select parent, account_head,
|
||||||
|
sum(tax_amount_after_flat_discount) as tax_amount
|
||||||
from `tabSales Taxes and Charges` where parent in (%s) group by parent, account_head""" %
|
from `tabSales Taxes and Charges` where parent in (%s) group by parent, account_head""" %
|
||||||
', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1)
|
', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1)
|
||||||
|
|
||||||
|
@ -360,6 +360,14 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(this.frm.tax_doclist.length) {
|
||||||
|
if(!wn.meta.get_docfield(this.frm.tax_doclist[0].doctype, "tax_amount_after_flat_discount", this.frm.doctype)) {
|
||||||
|
$.each(this.frm.tax_doclist, function(i, tax) {
|
||||||
|
delete tax["tax_amount_after_flat_discount"];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
calculate_outstanding_amount: function() {
|
calculate_outstanding_amount: function() {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||||
# License: GNU General Public License v3. See license.txt
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import unittest
|
import unittest
|
||||||
import webnotes
|
import webnotes
|
||||||
|
@ -16,7 +16,10 @@ class AccountsController(TransactionBase):
|
|||||||
self.set_missing_values(for_validate=True)
|
self.set_missing_values(for_validate=True)
|
||||||
self.validate_date_with_fiscal_year()
|
self.validate_date_with_fiscal_year()
|
||||||
if self.meta.get_field("currency"):
|
if self.meta.get_field("currency"):
|
||||||
|
self.flat_discount_applied = False
|
||||||
self.calculate_taxes_and_totals()
|
self.calculate_taxes_and_totals()
|
||||||
|
if hasattr(self, "apply_flat_discount"):
|
||||||
|
self.apply_flat_discount()
|
||||||
self.validate_value("grand_total", ">=", 0)
|
self.validate_value("grand_total", ">=", 0)
|
||||||
self.set_total_in_words()
|
self.set_total_in_words()
|
||||||
|
|
||||||
@ -141,10 +144,14 @@ class AccountsController(TransactionBase):
|
|||||||
else:
|
else:
|
||||||
validate_conversion_rate(self.doc.currency, self.doc.conversion_rate,
|
validate_conversion_rate(self.doc.currency, self.doc.conversion_rate,
|
||||||
self.meta.get_label("conversion_rate"), self.doc.company)
|
self.meta.get_label("conversion_rate"), self.doc.company)
|
||||||
|
|
||||||
self.doc.conversion_rate = flt(self.doc.conversion_rate)
|
self.doc.conversion_rate = flt(self.doc.conversion_rate)
|
||||||
self.item_doclist = self.doclist.get({"parentfield": self.fname})
|
self.item_doclist = self.doclist.get({"parentfield": self.fname})
|
||||||
self.tax_doclist = self.doclist.get({"parentfield": self.other_fname})
|
self.tax_doclist = self.doclist.get({"parentfield": self.other_fname})
|
||||||
|
|
||||||
|
# for buying
|
||||||
|
if not hasattr(self, "flat_discount_applied"):
|
||||||
|
self.flat_discount_applied = False
|
||||||
|
|
||||||
self.calculate_item_values()
|
self.calculate_item_values()
|
||||||
self.initialize_taxes()
|
self.initialize_taxes()
|
||||||
@ -163,11 +170,16 @@ class AccountsController(TransactionBase):
|
|||||||
def initialize_taxes(self):
|
def initialize_taxes(self):
|
||||||
for tax in self.tax_doclist:
|
for tax in self.tax_doclist:
|
||||||
tax.item_wise_tax_detail = {}
|
tax.item_wise_tax_detail = {}
|
||||||
for fieldname in ["tax_amount", "total",
|
tax_fields = ["total", "tax_amount_after_flat_discount",
|
||||||
"tax_amount_for_current_item", "grand_total_for_current_item",
|
"tax_amount_for_current_item", "grand_total_for_current_item",
|
||||||
"tax_fraction_for_current_item", "grand_total_fraction_for_current_item"]:
|
"tax_fraction_for_current_item", "grand_total_fraction_for_current_item"]
|
||||||
tax.fields[fieldname] = 0.0
|
|
||||||
|
if not self.flat_discount_applied:
|
||||||
|
tax_fields.append("tax_amount")
|
||||||
|
|
||||||
|
for fieldname in tax_fields:
|
||||||
|
tax.fields[fieldname] = 0.0
|
||||||
|
|
||||||
self.validate_on_previous_row(tax)
|
self.validate_on_previous_row(tax)
|
||||||
self.validate_inclusive_tax(tax)
|
self.validate_inclusive_tax(tax)
|
||||||
self.round_floats_in(tax)
|
self.round_floats_in(tax)
|
||||||
@ -215,39 +227,44 @@ class AccountsController(TransactionBase):
|
|||||||
"charge_type": tax.charge_type,
|
"charge_type": tax.charge_type,
|
||||||
}, raise_exception=True)
|
}, raise_exception=True)
|
||||||
elif tax.charge_type == "On Previous Row Amount" and \
|
elif tax.charge_type == "On Previous Row Amount" and \
|
||||||
not cint(self.tax_doclist[tax.row_id - 1].included_in_print_rate):
|
not cint(self.tax_doclist[cint(tax.row_id) - 1].included_in_print_rate):
|
||||||
# referred row should also be inclusive
|
# referred row should also be inclusive
|
||||||
_on_previous_row_error(tax.row_id)
|
_on_previous_row_error(tax.row_id)
|
||||||
elif tax.charge_type == "On Previous Row Total" and \
|
elif tax.charge_type == "On Previous Row Total" and \
|
||||||
not all([cint(t.included_in_print_rate) for t in self.tax_doclist[:tax.row_id - 1]]):
|
not all([cint(t.included_in_print_rate) for t in self.tax_doclist[:cint(tax.row_id) - 1]]):
|
||||||
# all rows about the reffered tax should be inclusive
|
# all rows about the reffered tax should be inclusive
|
||||||
_on_previous_row_error("1 - %d" % (tax.row_id,))
|
_on_previous_row_error("1 - %d" % (tax.row_id,))
|
||||||
|
|
||||||
def calculate_taxes(self):
|
def calculate_taxes(self):
|
||||||
for item in self.item_doclist:
|
# maintain actual tax rate based on idx
|
||||||
|
actual_tax_dict = dict([[tax.idx, tax.rate] for tax in self.tax_doclist
|
||||||
|
if tax.charge_type == "Actual"])
|
||||||
|
|
||||||
|
for n, item in enumerate(self.item_doclist):
|
||||||
item_tax_map = self._load_item_tax_rate(item.item_tax_rate)
|
item_tax_map = self._load_item_tax_rate(item.item_tax_rate)
|
||||||
|
|
||||||
for i, tax in enumerate(self.tax_doclist):
|
for i, tax in enumerate(self.tax_doclist):
|
||||||
# tax_amount represents the amount of tax for the current step
|
# tax_amount represents the amount of tax for the current step
|
||||||
current_tax_amount = self.get_current_tax_amount(item, tax, item_tax_map)
|
current_tax_amount = self.get_current_tax_amount(item, tax, item_tax_map)
|
||||||
|
|
||||||
|
# Adjust divisional loss to the last item
|
||||||
|
if tax.charge_type == "Actual":
|
||||||
|
actual_tax_dict[tax.idx] -= current_tax_amount
|
||||||
|
if n == len(self.item_doclist) - 1:
|
||||||
|
current_tax_amount += actual_tax_dict[tax.idx]
|
||||||
|
|
||||||
if hasattr(self, "set_item_tax_amount"):
|
if hasattr(self, "set_item_tax_amount"):
|
||||||
self.set_item_tax_amount(item, tax, current_tax_amount)
|
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 tax.charge_type=="Actual" and \
|
|
||||||
not (current_tax_amount or self.doc.net_total or tax.tax_amount):
|
|
||||||
zero_net_total_adjustment = flt(tax.rate, self.precision("tax_amount", tax))
|
|
||||||
current_tax_amount += zero_net_total_adjustment
|
|
||||||
|
|
||||||
# store tax_amount for current item as it will be used for
|
# store tax_amount for current item as it will be used for
|
||||||
# charge type = 'On Previous Row Amount'
|
# charge type = 'On Previous Row Amount'
|
||||||
tax.tax_amount_for_current_item = current_tax_amount
|
tax.tax_amount_for_current_item = current_tax_amount
|
||||||
|
|
||||||
# accumulate tax amount into tax.tax_amount
|
# accumulate tax amount into tax.tax_amount
|
||||||
tax.tax_amount += current_tax_amount
|
if not self.flat_discount_applied:
|
||||||
|
tax.tax_amount += current_tax_amount
|
||||||
|
|
||||||
|
tax.tax_amount_after_flat_discount += current_tax_amount
|
||||||
|
|
||||||
if tax.category:
|
if tax.category:
|
||||||
# if just for valuation, do not add the tax amount in total
|
# if just for valuation, do not add the tax amount in total
|
||||||
@ -260,17 +277,36 @@ class AccountsController(TransactionBase):
|
|||||||
# note: grand_total_for_current_item contains the contribution of
|
# note: grand_total_for_current_item contains the contribution of
|
||||||
# item's amount, previously applied tax and the current tax on that item
|
# item's amount, previously applied tax and the current tax on that item
|
||||||
if i==0:
|
if i==0:
|
||||||
tax.grand_total_for_current_item = flt(item.amount +
|
tax.grand_total_for_current_item = flt(item.amount + current_tax_amount,
|
||||||
current_tax_amount, self.precision("total", tax))
|
self.precision("total", tax))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
tax.grand_total_for_current_item = \
|
tax.grand_total_for_current_item = \
|
||||||
flt(self.tax_doclist[i-1].grand_total_for_current_item +
|
flt(self.tax_doclist[i-1].grand_total_for_current_item +
|
||||||
current_tax_amount, self.precision("total", tax))
|
current_tax_amount, self.precision("total", tax))
|
||||||
|
|
||||||
# in tax.total, accumulate grand total of each item
|
# in tax.total, accumulate grand total of each item
|
||||||
tax.total += tax.grand_total_for_current_item
|
tax.total += tax.grand_total_for_current_item
|
||||||
|
|
||||||
|
# set precision in the last item iteration
|
||||||
|
if n == len(self.item_doclist) - 1:
|
||||||
|
self.round_off_totals(tax)
|
||||||
|
|
||||||
|
# adjust flat discount loss in last tax iteration
|
||||||
|
if i == (len(self.tax_doclist) - 1) and self.flat_discount_applied:
|
||||||
|
self.adjust_flat_discount_loss(tax)
|
||||||
|
|
||||||
|
def round_off_totals(self, tax):
|
||||||
|
tax.total = flt(tax.total, self.precision("total", tax))
|
||||||
|
tax.tax_amount = flt(tax.tax_amount, self.precision("tax_amount", tax))
|
||||||
|
tax.tax_amount_after_flat_discount = flt(tax.tax_amount_after_flat_discount,
|
||||||
|
self.precision("tax_amount", tax))
|
||||||
|
|
||||||
|
def adjust_flat_discount_loss(self, tax):
|
||||||
|
flat_discount_loss = self.doc.grand_total - self.doc.flat_discount - tax.total
|
||||||
|
tax.tax_amount_after_flat_discount = flt(tax.tax_amount_after_flat_discount +
|
||||||
|
flat_discount_loss, self.precision("tax_amount", tax))
|
||||||
|
tax.total = flt(tax.total + flat_discount_loss, self.precision("total", tax))
|
||||||
|
|
||||||
def get_current_tax_amount(self, item, tax, item_tax_map):
|
def get_current_tax_amount(self, item, tax, item_tax_map):
|
||||||
tax_rate = self._get_tax_rate(tax, item_tax_map)
|
tax_rate = self._get_tax_rate(tax, item_tax_map)
|
||||||
current_tax_amount = 0.0
|
current_tax_amount = 0.0
|
||||||
@ -289,9 +325,9 @@ class AccountsController(TransactionBase):
|
|||||||
elif tax.charge_type == "On Previous Row Total":
|
elif tax.charge_type == "On Previous Row Total":
|
||||||
current_tax_amount = (tax_rate / 100.0) * \
|
current_tax_amount = (tax_rate / 100.0) * \
|
||||||
self.tax_doclist[cint(tax.row_id) - 1].grand_total_for_current_item
|
self.tax_doclist[cint(tax.row_id) - 1].grand_total_for_current_item
|
||||||
|
|
||||||
current_tax_amount = flt(current_tax_amount, self.precision("tax_amount", tax))
|
current_tax_amount = flt(current_tax_amount, self.precision("tax_amount", tax))
|
||||||
|
|
||||||
# store tax breakup for each item
|
# store tax breakup for each item
|
||||||
key = item.item_code or item.item_name
|
key = item.item_code or item.item_name
|
||||||
if tax.item_wise_tax_detail.get(key):
|
if tax.item_wise_tax_detail.get(key):
|
||||||
|
@ -5,7 +5,6 @@ from __future__ import unicode_literals
|
|||||||
import webnotes
|
import webnotes
|
||||||
from webnotes import _, msgprint
|
from webnotes import _, msgprint
|
||||||
from webnotes.utils import flt, _round
|
from webnotes.utils import flt, _round
|
||||||
|
|
||||||
from erpnext.buying.utils import get_item_details
|
from erpnext.buying.utils import get_item_details
|
||||||
from erpnext.setup.utils import get_company_currency
|
from erpnext.setup.utils import get_company_currency
|
||||||
|
|
||||||
@ -161,6 +160,10 @@ class BuyingController(StockController):
|
|||||||
if not self.meta.get_field("item_tax_amount", parentfield=self.fname):
|
if not self.meta.get_field("item_tax_amount", parentfield=self.fname):
|
||||||
for item in self.item_doclist:
|
for item in self.item_doclist:
|
||||||
del item.fields["item_tax_amount"]
|
del item.fields["item_tax_amount"]
|
||||||
|
|
||||||
|
if not self.meta.get_field("tax_amount_after_flat_discount", parentfield=self.other_fname):
|
||||||
|
for tax in self.tax_doclist:
|
||||||
|
del tax.fields["tax_amount_after_flat_discount"]
|
||||||
|
|
||||||
def set_item_tax_amount(self, item, tax, current_tax_amount):
|
def set_item_tax_amount(self, item, tax, current_tax_amount):
|
||||||
"""
|
"""
|
||||||
|
@ -121,7 +121,7 @@ class SellingController(StockController):
|
|||||||
|
|
||||||
cumulated_tax_fraction += tax.tax_fraction_for_current_item
|
cumulated_tax_fraction += tax.tax_fraction_for_current_item
|
||||||
|
|
||||||
if cumulated_tax_fraction:
|
if cumulated_tax_fraction and not self.flat_discount_applied:
|
||||||
item.amount = flt((item.export_amount * self.doc.conversion_rate) /
|
item.amount = flt((item.export_amount * self.doc.conversion_rate) /
|
||||||
(1 + cumulated_tax_fraction), self.precision("amount", item))
|
(1 + cumulated_tax_fraction), self.precision("amount", item))
|
||||||
|
|
||||||
@ -158,22 +158,23 @@ class SellingController(StockController):
|
|||||||
return current_tax_fraction
|
return current_tax_fraction
|
||||||
|
|
||||||
def calculate_item_values(self):
|
def calculate_item_values(self):
|
||||||
for item in self.item_doclist:
|
if not self.flat_discount_applied:
|
||||||
self.round_floats_in(item)
|
for item in self.item_doclist:
|
||||||
|
self.round_floats_in(item)
|
||||||
if item.adj_rate == 100:
|
|
||||||
item.export_rate = 0
|
if item.adj_rate == 100:
|
||||||
elif not item.export_rate:
|
item.export_rate = 0
|
||||||
item.export_rate = flt(item.ref_rate * (1.0 - (item.adj_rate / 100.0)),
|
elif not item.export_rate:
|
||||||
self.precision("export_rate", item))
|
item.export_rate = flt(item.ref_rate * (1.0 - (item.adj_rate / 100.0)),
|
||||||
|
self.precision("export_rate", item))
|
||||||
item.export_amount = flt(item.export_rate * item.qty,
|
|
||||||
self.precision("export_amount", item))
|
item.export_amount = flt(item.export_rate * item.qty,
|
||||||
|
self.precision("export_amount", item))
|
||||||
|
|
||||||
|
self._set_in_company_currency(item, "ref_rate", "base_ref_rate")
|
||||||
|
self._set_in_company_currency(item, "export_rate", "basic_rate")
|
||||||
|
self._set_in_company_currency(item, "export_amount", "amount")
|
||||||
|
|
||||||
self._set_in_company_currency(item, "ref_rate", "base_ref_rate")
|
|
||||||
self._set_in_company_currency(item, "export_rate", "basic_rate")
|
|
||||||
self._set_in_company_currency(item, "export_amount", "amount")
|
|
||||||
|
|
||||||
def calculate_net_total(self):
|
def calculate_net_total(self):
|
||||||
self.doc.net_total = self.doc.net_total_export = 0.0
|
self.doc.net_total = self.doc.net_total_export = 0.0
|
||||||
|
|
||||||
@ -191,12 +192,40 @@ class SellingController(StockController):
|
|||||||
|
|
||||||
self.doc.other_charges_total = flt(self.doc.grand_total - self.doc.net_total,
|
self.doc.other_charges_total = flt(self.doc.grand_total - self.doc.net_total,
|
||||||
self.precision("other_charges_total"))
|
self.precision("other_charges_total"))
|
||||||
self.doc.other_charges_total_export = flt(self.doc.grand_total_export - self.doc.net_total_export,
|
self.doc.other_charges_total_export = flt(self.doc.grand_total_export -
|
||||||
self.precision("other_charges_total_export"))
|
self.doc.net_total_export + flt(self.doc.flat_discount), self.precision("other_charges_total_export"))
|
||||||
|
|
||||||
self.doc.rounded_total = _round(self.doc.grand_total)
|
self.doc.rounded_total = _round(self.doc.grand_total)
|
||||||
self.doc.rounded_total_export = _round(self.doc.grand_total_export)
|
self.doc.rounded_total_export = _round(self.doc.grand_total_export)
|
||||||
|
|
||||||
|
def apply_flat_discount(self):
|
||||||
|
if self.doc.flat_discount:
|
||||||
|
total_amount_for_flat_discount = self.get_flat_discountable_amount()
|
||||||
|
|
||||||
|
if total_amount_for_flat_discount:
|
||||||
|
# calculate item amount after flat discount
|
||||||
|
for item in self.item_doclist:
|
||||||
|
distributed_amount = self.doc.flat_discount * item.amount / total_amount_for_flat_discount
|
||||||
|
item.amount = flt(item.amount - distributed_amount, self.precision("amount", item))
|
||||||
|
|
||||||
|
self.flat_discount_applied = True
|
||||||
|
self.calculate_taxes_and_totals()
|
||||||
|
|
||||||
|
def get_flat_discountable_amount(self):
|
||||||
|
actual_taxes_dict = {}
|
||||||
|
|
||||||
|
for tax in self.tax_doclist:
|
||||||
|
if tax.charge_type == "Actual":
|
||||||
|
actual_taxes_dict.setdefault(tax.idx, tax.tax_amount)
|
||||||
|
elif tax.row_id in actual_taxes_dict:
|
||||||
|
actual_tax_amount = flt(actual_taxes_dict.get(tax.row_id, 0)) * \
|
||||||
|
flt(tax.rate) / 100
|
||||||
|
actual_taxes_dict.setdefault(tax.idx, actual_tax_amount)
|
||||||
|
|
||||||
|
total_amount_for_flat_discount = flt(self.doc.grand_total - sum(actual_taxes_dict.values()),
|
||||||
|
self.precision("grand_total"))
|
||||||
|
return total_amount_for_flat_discount
|
||||||
|
|
||||||
def calculate_outstanding_amount(self):
|
def calculate_outstanding_amount(self):
|
||||||
# NOTE:
|
# NOTE:
|
||||||
# write_off_amount is only for POS Invoice
|
# write_off_amount is only for POS Invoice
|
||||||
|
@ -173,18 +173,18 @@ patch_list = [
|
|||||||
"patches.july_2013.p05_custom_doctypes_in_list_view",
|
"patches.july_2013.p05_custom_doctypes_in_list_view",
|
||||||
"patches.july_2013.p06_same_sales_rate",
|
"patches.july_2013.p06_same_sales_rate",
|
||||||
"patches.july_2013.p07_repost_billed_amt_in_sales_cycle",
|
"patches.july_2013.p07_repost_billed_amt_in_sales_cycle",
|
||||||
"execute:webnotes.reload_doc('accounts', 'Print Format', 'Sales Invoice Classic') # 2013-07-22",
|
"execute:webnotes.reload_doc('accounts', 'Print Format', 'Sales Invoice Classic') # 2013-12-26",
|
||||||
"execute:webnotes.reload_doc('accounts', 'Print Format', 'Sales Invoice Modern') # 2013-07-22",
|
"execute:webnotes.reload_doc('accounts', 'Print Format', 'Sales Invoice Modern') # 2013-12-26",
|
||||||
"execute:webnotes.reload_doc('accounts', 'Print Format', 'Sales Invoice Spartan') # 2013-07-22",
|
"execute:webnotes.reload_doc('accounts', 'Print Format', 'Sales Invoice Spartan') # 2013-12-26",
|
||||||
"execute:webnotes.reload_doc('selling', 'Print Format', 'Quotation Classic') # 2013-07-22",
|
"execute:webnotes.reload_doc('selling', 'Print Format', 'Quotation Classic') # 2013-12-26",
|
||||||
"execute:webnotes.reload_doc('selling', 'Print Format', 'Quotation Modern') # 2013-07-22",
|
"execute:webnotes.reload_doc('selling', 'Print Format', 'Quotation Modern') # 2013-12-26",
|
||||||
"execute:webnotes.reload_doc('selling', 'Print Format', 'Quotation Spartan') # 2013-07-22",
|
"execute:webnotes.reload_doc('selling', 'Print Format', 'Quotation Spartan') # 2013-12-26",
|
||||||
"execute:webnotes.reload_doc('selling', 'Print Format', 'Sales Order Classic') # 2013-07-22",
|
"execute:webnotes.reload_doc('selling', 'Print Format', 'Sales Order Classic') # 2013-12-26",
|
||||||
"execute:webnotes.reload_doc('selling', 'Print Format', 'Sales Order Modern') # 2013-07-22",
|
"execute:webnotes.reload_doc('selling', 'Print Format', 'Sales Order Modern') # 2013-12-26",
|
||||||
"execute:webnotes.reload_doc('selling', 'Print Format', 'Sales Order Spartan') # 2013-07-22",
|
"execute:webnotes.reload_doc('selling', 'Print Format', 'Sales Order Spartan') # 2013-12-26",
|
||||||
"execute:webnotes.reload_doc('stock', 'Print Format', 'Delivery Note Classic') # 2013-07-22",
|
"execute:webnotes.reload_doc('stock', 'Print Format', 'Delivery Note Classic') # 2013-12-26",
|
||||||
"execute:webnotes.reload_doc('stock', 'Print Format', 'Delivery Note Modern') # 2013-07-22",
|
"execute:webnotes.reload_doc('stock', 'Print Format', 'Delivery Note Modern') # 2013-12-26",
|
||||||
"execute:webnotes.reload_doc('stock', 'Print Format', 'Delivery Note Spartan') # 2013-07-22",
|
"execute:webnotes.reload_doc('stock', 'Print Format', 'Delivery Note Spartan') # 2013-12-26",
|
||||||
"patches.july_2013.p08_custom_print_format_net_total_export",
|
"patches.july_2013.p08_custom_print_format_net_total_export",
|
||||||
"patches.july_2013.p09_remove_website_pyc",
|
"patches.july_2013.p09_remove_website_pyc",
|
||||||
"patches.july_2013.p10_change_partner_user_to_website_user",
|
"patches.july_2013.p10_change_partner_user_to_website_user",
|
||||||
@ -263,4 +263,9 @@ patch_list = [
|
|||||||
"execute:webnotes.delete_doc('DocType', 'Warehouse Type')",
|
"execute:webnotes.delete_doc('DocType', 'Warehouse Type')",
|
||||||
"patches.1312.p01_delete_old_stock_reports",
|
"patches.1312.p01_delete_old_stock_reports",
|
||||||
"patches.1312.p02_update_item_details_in_item_price",
|
"patches.1312.p02_update_item_details_in_item_price",
|
||||||
|
"execute:webnotes.reload_doc('accounts', 'Print Format', 'POS Invoice') # 2013-12-26",
|
||||||
|
"execute:webnotes.reload_doc('accounts', 'doctype', 'sales_invoice') # 2013-12-26",
|
||||||
|
"execute:webnotes.reload_doc('selling', 'doctype', 'sales_order') # 2013-12-26",
|
||||||
|
"execute:webnotes.reload_doc('selling', 'doctype', 'quotation') # 2013-12-26",
|
||||||
|
"execute:webnotes.reload_doc('stock', 'doctype', 'delivery_note') # 2013-12-26",
|
||||||
]
|
]
|
@ -146,7 +146,9 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
validate: function() {
|
validate: function() {
|
||||||
|
this.flat_discount_applied = false;
|
||||||
this.calculate_taxes_and_totals();
|
this.calculate_taxes_and_totals();
|
||||||
|
this.apply_flat_discount && this.apply_flat_discount();
|
||||||
},
|
},
|
||||||
|
|
||||||
set_default_values: function() {
|
set_default_values: function() {
|
||||||
@ -514,7 +516,7 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
|
|||||||
this.validate_conversion_rate();
|
this.validate_conversion_rate();
|
||||||
this.frm.item_doclist = this.get_item_doclist();
|
this.frm.item_doclist = this.get_item_doclist();
|
||||||
this.frm.tax_doclist = this.get_tax_doclist();
|
this.frm.tax_doclist = this.get_tax_doclist();
|
||||||
|
|
||||||
this.calculate_item_values();
|
this.calculate_item_values();
|
||||||
this.initialize_taxes();
|
this.initialize_taxes();
|
||||||
this.determine_exclusive_rate && this.determine_exclusive_rate();
|
this.determine_exclusive_rate && this.determine_exclusive_rate();
|
||||||
@ -528,12 +530,17 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
|
|||||||
|
|
||||||
initialize_taxes: function() {
|
initialize_taxes: function() {
|
||||||
var me = this;
|
var me = this;
|
||||||
|
|
||||||
$.each(this.frm.tax_doclist, function(i, tax) {
|
$.each(this.frm.tax_doclist, function(i, tax) {
|
||||||
tax.item_wise_tax_detail = {};
|
tax.item_wise_tax_detail = {};
|
||||||
$.each(["tax_amount", "total",
|
tax_fields = ["total", "tax_amount_after_flat_discount",
|
||||||
"tax_amount_for_current_item", "grand_total_for_current_item",
|
"tax_amount_for_current_item", "grand_total_for_current_item",
|
||||||
"tax_fraction_for_current_item", "grand_total_fraction_for_current_item"],
|
"tax_fraction_for_current_item", "grand_total_fraction_for_current_item"]
|
||||||
function(i, fieldname) { tax[fieldname] = 0.0 });
|
|
||||||
|
if (!me.flat_discount_applied)
|
||||||
|
tax_fields.push("tax_amount");
|
||||||
|
|
||||||
|
$.each(tax_fields, function(i, fieldname) { tax[fieldname] = 0.0 });
|
||||||
|
|
||||||
me.validate_on_previous_row(tax);
|
me.validate_on_previous_row(tax);
|
||||||
me.validate_inclusive_tax(tax);
|
me.validate_inclusive_tax(tax);
|
||||||
@ -543,31 +550,41 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
|
|||||||
|
|
||||||
calculate_taxes: function() {
|
calculate_taxes: function() {
|
||||||
var me = this;
|
var me = this;
|
||||||
|
var actual_tax_dict = {};
|
||||||
|
|
||||||
|
// maintain actual tax rate based on idx
|
||||||
|
$.each(this.frm.tax_doclist, function(i, tax) {
|
||||||
|
if (tax.charge_type == "Actual") {
|
||||||
|
actual_tax_dict[tax.idx] = flt(tax.rate);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
$.each(this.frm.item_doclist, function(n, item) {
|
$.each(this.frm.item_doclist, function(n, item) {
|
||||||
var item_tax_map = me._load_item_tax_rate(item.item_tax_rate);
|
var item_tax_map = me._load_item_tax_rate(item.item_tax_rate);
|
||||||
|
|
||||||
$.each(me.frm.tax_doclist, function(i, tax) {
|
$.each(me.frm.tax_doclist, function(i, tax) {
|
||||||
// tax_amount represents the amount of tax for the current step
|
// tax_amount represents the amount of tax for the current step
|
||||||
var current_tax_amount = me.get_current_tax_amount(item, tax, item_tax_map);
|
var current_tax_amount = me.get_current_tax_amount(item, tax, item_tax_map);
|
||||||
|
|
||||||
me.set_item_tax_amount && me.set_item_tax_amount(item, tax, current_tax_amount);
|
// Adjust divisional loss to the last item
|
||||||
|
if (tax.charge_type == "Actual") {
|
||||||
// case when net total is 0 but there is an actual type charge
|
actual_tax_dict[tax.idx] -= current_tax_amount;
|
||||||
// in this case add the actual amount to tax.tax_amount
|
if (n == me.frm.item_doclist.length - 1) {
|
||||||
// and tax.grand_total_for_current_item for the first such iteration
|
current_tax_amount += actual_tax_dict[tax.idx]
|
||||||
if(tax.charge_type == "Actual" &&
|
|
||||||
!(current_tax_amount || me.frm.doc.net_total || tax.tax_amount)) {
|
|
||||||
var zero_net_total_adjustment = flt(tax.rate, precision("tax_amount", tax));
|
|
||||||
current_tax_amount += zero_net_total_adjustment;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
me.set_item_tax_amount && me.set_item_tax_amount(item, tax, current_tax_amount);
|
||||||
|
|
||||||
// store tax_amount for current item as it will be used for
|
// store tax_amount for current item as it will be used for
|
||||||
// charge type = 'On Previous Row Amount'
|
// charge type = 'On Previous Row Amount'
|
||||||
tax.tax_amount_for_current_item = current_tax_amount;
|
tax.tax_amount_for_current_item = current_tax_amount;
|
||||||
|
|
||||||
// accumulate tax amount into tax.tax_amount
|
// accumulate tax amount into tax.tax_amount
|
||||||
tax.tax_amount += current_tax_amount;
|
if (!me.flat_discount_applied)
|
||||||
|
tax.tax_amount += current_tax_amount;
|
||||||
|
|
||||||
|
tax.tax_amount_after_flat_discount += current_tax_amount;
|
||||||
|
|
||||||
// for buying
|
// for buying
|
||||||
if(tax.category) {
|
if(tax.category) {
|
||||||
@ -592,9 +609,32 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
|
|||||||
|
|
||||||
// in tax.total, accumulate grand total for each item
|
// in tax.total, accumulate grand total for each item
|
||||||
tax.total += tax.grand_total_for_current_item;
|
tax.total += tax.grand_total_for_current_item;
|
||||||
|
|
||||||
|
// set precision in the last item iteration
|
||||||
|
if (n == me.frm.item_doclist.length - 1) {
|
||||||
|
me.round_off_totals(tax);
|
||||||
|
|
||||||
|
// adjust flat discount loss in last tax iteration
|
||||||
|
if ((i == me.frm.tax_doclist.length - 1) && me.flat_discount_applied)
|
||||||
|
me.adjust_flat_discount_loss(tax);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
round_off_totals: function(tax) {
|
||||||
|
tax.total = flt(tax.total, precision("total", tax));
|
||||||
|
tax.tax_amount = flt(tax.tax_amount, precision("tax_amount", tax));
|
||||||
|
tax.tax_amount_after_flat_discount = flt(tax.tax_amount_after_flat_discount,
|
||||||
|
precision("tax_amount", tax));
|
||||||
|
},
|
||||||
|
|
||||||
|
adjust_flat_discount_loss: function(tax) {
|
||||||
|
var flat_discount_loss = this.frm.doc.grand_total - this.frm.doc.flat_discount - tax.total;
|
||||||
|
tax.tax_amount_after_flat_discount = flt(tax.tax_amount_after_flat_discount +
|
||||||
|
flat_discount_loss, precision("tax_amount", tax));
|
||||||
|
tax.total = flt(tax.total + flat_discount_loss, precision("total", tax));
|
||||||
|
},
|
||||||
|
|
||||||
get_current_tax_amount: function(item, tax, item_tax_map) {
|
get_current_tax_amount: function(item, tax, item_tax_map) {
|
||||||
var tax_rate = this._get_tax_rate(tax, item_tax_map);
|
var tax_rate = this._get_tax_rate(tax, item_tax_map);
|
||||||
@ -617,9 +657,8 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
|
|||||||
} else if(tax.charge_type == "On Previous Row Total") {
|
} else if(tax.charge_type == "On Previous Row Total") {
|
||||||
current_tax_amount = (tax_rate / 100.0) *
|
current_tax_amount = (tax_rate / 100.0) *
|
||||||
this.frm.tax_doclist[cint(tax.row_id) - 1].grand_total_for_current_item;
|
this.frm.tax_doclist[cint(tax.row_id) - 1].grand_total_for_current_item;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
current_tax_amount = flt(current_tax_amount, precision("tax_amount", tax));
|
current_tax_amount = flt(current_tax_amount, precision("tax_amount", tax));
|
||||||
|
|
||||||
// store tax breakup for each item
|
// store tax breakup for each item
|
||||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -2,7 +2,7 @@
|
|||||||
{
|
{
|
||||||
"creation": "2013-05-24 19:29:08",
|
"creation": "2013-05-24 19:29:08",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"modified": "2013-12-20 19:24:25",
|
"modified": "2013-12-26 17:54:55",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"owner": "Administrator"
|
"owner": "Administrator"
|
||||||
},
|
},
|
||||||
@ -460,6 +460,13 @@
|
|||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"doctype": "DocField",
|
||||||
|
"fieldname": "flat_discount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"label": "Flat Discount",
|
||||||
|
"options": "Company:company:default_currency"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"doctype": "DocField",
|
"doctype": "DocField",
|
||||||
"fieldname": "totals",
|
"fieldname": "totals",
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
{
|
{
|
||||||
"creation": "2013-06-18 12:39:59",
|
"creation": "2013-06-18 12:39:59",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"modified": "2013-12-20 19:24:32",
|
"modified": "2013-12-26 17:55:43",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"owner": "Administrator"
|
"owner": "Administrator"
|
||||||
},
|
},
|
||||||
@ -480,6 +480,13 @@
|
|||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"width": "150px"
|
"width": "150px"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"doctype": "DocField",
|
||||||
|
"fieldname": "flat_discount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"label": "Flat Discount",
|
||||||
|
"options": "Company:company:default_currency"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"doctype": "DocField",
|
"doctype": "DocField",
|
||||||
"fieldname": "totals",
|
"fieldname": "totals",
|
||||||
|
@ -225,6 +225,12 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
|
|||||||
|
|
||||||
this.calculate_taxes_and_totals();
|
this.calculate_taxes_and_totals();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
flat_discount: function() {
|
||||||
|
this.flat_discount_applied = false;
|
||||||
|
this.calculate_taxes_and_totals();
|
||||||
|
this.apply_flat_discount();
|
||||||
|
},
|
||||||
|
|
||||||
commission_rate: function() {
|
commission_rate: function() {
|
||||||
this.calculate_commission();
|
this.calculate_commission();
|
||||||
@ -310,15 +316,17 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
|
|||||||
|
|
||||||
calculate_item_values: function() {
|
calculate_item_values: function() {
|
||||||
var me = this;
|
var me = this;
|
||||||
$.each(this.frm.item_doclist, function(i, item) {
|
|
||||||
wn.model.round_floats_in(item);
|
|
||||||
item.export_amount = flt(item.export_rate * item.qty, precision("export_amount", item));
|
|
||||||
|
|
||||||
me._set_in_company_currency(item, "ref_rate", "base_ref_rate");
|
|
||||||
me._set_in_company_currency(item, "export_rate", "basic_rate");
|
|
||||||
me._set_in_company_currency(item, "export_amount", "amount");
|
|
||||||
});
|
|
||||||
|
|
||||||
|
if (!this.flat_discount_applied) {
|
||||||
|
$.each(this.frm.item_doclist, function(i, item) {
|
||||||
|
wn.model.round_floats_in(item);
|
||||||
|
item.export_amount = flt(item.export_rate * item.qty, precision("export_amount", item));
|
||||||
|
|
||||||
|
me._set_in_company_currency(item, "ref_rate", "base_ref_rate");
|
||||||
|
me._set_in_company_currency(item, "export_rate", "basic_rate");
|
||||||
|
me._set_in_company_currency(item, "export_amount", "amount");
|
||||||
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
determine_exclusive_rate: function() {
|
determine_exclusive_rate: function() {
|
||||||
@ -341,11 +349,11 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
|
|||||||
cumulated_tax_fraction += tax.tax_fraction_for_current_item;
|
cumulated_tax_fraction += tax.tax_fraction_for_current_item;
|
||||||
});
|
});
|
||||||
|
|
||||||
if(cumulated_tax_fraction) {
|
if(cumulated_tax_fraction && !me.flat_discount_applied) {
|
||||||
item.amount = flt(
|
item.amount = flt(
|
||||||
(item.export_amount * me.frm.doc.conversion_rate) / (1 + cumulated_tax_fraction),
|
(item.export_amount * me.frm.doc.conversion_rate) / (1 + cumulated_tax_fraction),
|
||||||
precision("amount", item));
|
precision("amount", item));
|
||||||
|
|
||||||
item.basic_rate = flt(item.amount / item.qty, precision("basic_rate", item));
|
item.basic_rate = flt(item.amount / item.qty, precision("basic_rate", item));
|
||||||
|
|
||||||
if(item.adj_rate == 100) {
|
if(item.adj_rate == 100) {
|
||||||
@ -385,18 +393,20 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
|
|||||||
|
|
||||||
calculate_net_total: function() {
|
calculate_net_total: function() {
|
||||||
var me = this;
|
var me = this;
|
||||||
|
|
||||||
this.frm.doc.net_total = this.frm.doc.net_total_export = 0.0;
|
this.frm.doc.net_total = this.frm.doc.net_total_export = 0.0;
|
||||||
|
|
||||||
$.each(this.frm.item_doclist, function(i, item) {
|
$.each(this.frm.item_doclist, function(i, item) {
|
||||||
me.frm.doc.net_total += item.amount;
|
me.frm.doc.net_total += item.amount;
|
||||||
me.frm.doc.net_total_export += item.export_amount;
|
me.frm.doc.net_total_export += item.export_amount;
|
||||||
});
|
});
|
||||||
|
|
||||||
wn.model.round_floats_in(this.frm.doc, ["net_total", "net_total_export"]);
|
wn.model.round_floats_in(this.frm.doc, ["net_total", "net_total_export"]);
|
||||||
},
|
},
|
||||||
|
|
||||||
calculate_totals: function() {
|
calculate_totals: function() {
|
||||||
|
var me = this;
|
||||||
var tax_count = this.frm.tax_doclist.length;
|
var tax_count = this.frm.tax_doclist.length;
|
||||||
|
|
||||||
this.frm.doc.grand_total = flt(
|
this.frm.doc.grand_total = flt(
|
||||||
tax_count ? this.frm.tax_doclist[tax_count - 1].total : this.frm.doc.net_total,
|
tax_count ? this.frm.tax_doclist[tax_count - 1].total : this.frm.doc.net_total,
|
||||||
precision("grand_total"));
|
precision("grand_total"));
|
||||||
@ -405,13 +415,54 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
|
|||||||
|
|
||||||
this.frm.doc.other_charges_total = flt(this.frm.doc.grand_total - this.frm.doc.net_total,
|
this.frm.doc.other_charges_total = flt(this.frm.doc.grand_total - this.frm.doc.net_total,
|
||||||
precision("other_charges_total"));
|
precision("other_charges_total"));
|
||||||
this.frm.doc.other_charges_total_export = flt(
|
this.frm.doc.other_charges_total_export = flt(this.frm.doc.grand_total_export -
|
||||||
this.frm.doc.grand_total_export - this.frm.doc.net_total_export,
|
this.frm.doc.net_total_export + this.frm.doc.flat_discount,
|
||||||
precision("other_charges_total_export"));
|
precision("other_charges_total_export"));
|
||||||
|
|
||||||
this.frm.doc.rounded_total = Math.round(this.frm.doc.grand_total);
|
this.frm.doc.rounded_total = Math.round(this.frm.doc.grand_total);
|
||||||
this.frm.doc.rounded_total_export = Math.round(this.frm.doc.grand_total_export);
|
this.frm.doc.rounded_total_export = Math.round(this.frm.doc.grand_total_export);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
apply_flat_discount: function() {
|
||||||
|
var me = this;
|
||||||
|
var distributed_amount = 0.0;
|
||||||
|
|
||||||
|
if (this.frm.doc.flat_discount) {
|
||||||
|
var total_amount_for_flat_discount = this.get_flat_discountable_amount();
|
||||||
|
// calculate item amount after flat discount
|
||||||
|
$.each(this.frm.item_doclist, function(i, item) {
|
||||||
|
distributed_amount = me.frm.doc.flat_discount * item.amount / total_amount_for_flat_discount;
|
||||||
|
item.amount = flt(item.amount - distributed_amount, precision("amount", item));
|
||||||
|
});
|
||||||
|
|
||||||
|
this.flat_discount_applied = true;
|
||||||
|
this.calculate_taxes_and_totals();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
get_flat_discountable_amount: function() {
|
||||||
|
var me = this;
|
||||||
|
var total_actual_tax = 0.0;
|
||||||
|
var actual_taxes_dict = {};
|
||||||
|
|
||||||
|
$.each(this.frm.tax_doclist, function(i, tax) {
|
||||||
|
if (tax.charge_type == "Actual")
|
||||||
|
actual_taxes_dict[tax.idx] = tax.tax_amount;
|
||||||
|
else if (actual_taxes_dict[tax.row_id] !== null) {
|
||||||
|
actual_tax_amount = flt(actual_taxes_dict[tax.row_id]) * flt(tax.rate) / 100;
|
||||||
|
actual_taxes_dict[tax.idx] = actual_tax_amount;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$.each(actual_taxes_dict, function(key, value) {
|
||||||
|
if (value)
|
||||||
|
total_actual_tax += value;
|
||||||
|
});
|
||||||
|
|
||||||
|
total_amount_for_flat_discount = flt(this.frm.doc.grand_total - total_actual_tax,
|
||||||
|
precision("grand_total"));
|
||||||
|
return total_amount_for_flat_discount;
|
||||||
|
},
|
||||||
|
|
||||||
calculate_outstanding_amount: function() {
|
calculate_outstanding_amount: function() {
|
||||||
// NOTE:
|
// NOTE:
|
||||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -2,7 +2,7 @@
|
|||||||
{
|
{
|
||||||
"creation": "2013-05-24 19:29:09",
|
"creation": "2013-05-24 19:29:09",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"modified": "2013-12-20 19:24:02",
|
"modified": "2013-12-26 18:01:33",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"owner": "Administrator"
|
"owner": "Administrator"
|
||||||
},
|
},
|
||||||
@ -468,7 +468,7 @@
|
|||||||
"fieldname": "other_charges_total_export",
|
"fieldname": "other_charges_total_export",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"label": "Taxes and Charges Total",
|
"label": "Taxes and Charges Total",
|
||||||
"options": "company",
|
"options": "Company:company:default_currency",
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
@ -490,6 +490,13 @@
|
|||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"width": "150px"
|
"width": "150px"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"doctype": "DocField",
|
||||||
|
"fieldname": "flat_discount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"label": "Flat Discount",
|
||||||
|
"options": "Company:company:default_currency"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"doctype": "DocField",
|
"doctype": "DocField",
|
||||||
"fieldname": "totals",
|
"fieldname": "totals",
|
||||||
|
@ -97,7 +97,8 @@ cur_frm.fields_dict['default_sales_cost_center'].get_query = function(doc) {
|
|||||||
cur_frm.fields_dict['item_tax'].grid.get_field("tax_type").get_query = function(doc, cdt, cdn) {
|
cur_frm.fields_dict['item_tax'].grid.get_field("tax_type").get_query = function(doc, cdt, cdn) {
|
||||||
return{
|
return{
|
||||||
filters:[
|
filters:[
|
||||||
['Account', 'account_type', 'in', 'Tax, Chargeable'],
|
['Account', 'account_type', 'in',
|
||||||
|
'Tax, Chargeable, Income Account, Expense Account'],
|
||||||
['Account', 'docstatus', '!=', 2]
|
['Account', 'docstatus', '!=', 2]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -151,8 +151,8 @@ class DocType(DocListController, WebsiteGenerator):
|
|||||||
if d.tax_type:
|
if d.tax_type:
|
||||||
account_type = webnotes.conn.get_value("Account", d.tax_type, "account_type")
|
account_type = webnotes.conn.get_value("Account", d.tax_type, "account_type")
|
||||||
|
|
||||||
if account_type not in ['Tax', 'Chargeable']:
|
if account_type not in ['Tax', 'Chargeable', 'Income Account', 'Expense Account']:
|
||||||
msgprint("'%s' is not Tax / Chargeable Account" % d.tax_type, raise_exception=1)
|
msgprint("'%s' is not Tax / Chargeable / Income / Expense Account" % d.tax_type, raise_exception=1)
|
||||||
else:
|
else:
|
||||||
if d.tax_type in check_list:
|
if d.tax_type in check_list:
|
||||||
msgprint("Rate is entered twice for: '%s'" % d.tax_type, raise_exception=1)
|
msgprint("Rate is entered twice for: '%s'" % d.tax_type, raise_exception=1)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user