Merge pull request #1316 from nabinhait/hotfix
rounding and divisional loss
This commit is contained in:
commit
5644ed37a4
@ -358,7 +358,8 @@ class DocType(BuyingController):
|
|||||||
# expense will be booked in sales invoice
|
# expense will be booked in sales invoice
|
||||||
stock_item_and_auto_accounting_for_stock = True
|
stock_item_and_auto_accounting_for_stock = True
|
||||||
|
|
||||||
valuation_amt = item.amount + item.item_tax_amount + item.rm_supp_cost
|
valuation_amt = flt(item.amount + item.item_tax_amount + item.rm_supp_cost,
|
||||||
|
self.precision("amount", item))
|
||||||
|
|
||||||
gl_entries.append(
|
gl_entries.append(
|
||||||
self.get_gl_dict({
|
self.get_gl_dict({
|
||||||
|
@ -223,20 +223,22 @@ class AccountsController(TransactionBase):
|
|||||||
_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)
|
||||||
|
|
||||||
# case when net total is 0 but there is an actual type charge
|
# Adjust divisional loss to the last item
|
||||||
# in this case add the actual amount to tax.tax_amount
|
if tax.charge_type == "Actual":
|
||||||
# and tax.grand_total_for_current_item for the first such iteration
|
actual_tax_dict[tax.idx] -= current_tax_amount
|
||||||
if tax.charge_type=="Actual" and \
|
if n == len(self.item_doclist) - 1:
|
||||||
not (current_tax_amount or self.doc.net_total or tax.tax_amount):
|
current_tax_amount += actual_tax_dict[tax.idx]
|
||||||
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'
|
||||||
@ -248,7 +250,8 @@ class AccountsController(TransactionBase):
|
|||||||
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
|
||||||
# hence, setting it as 0 for further steps
|
# hence, setting it as 0 for further steps
|
||||||
current_tax_amount = 0.0 if (tax.category == "Valuation") else current_tax_amount
|
current_tax_amount = 0.0 if (tax.category == "Valuation") \
|
||||||
|
else current_tax_amount
|
||||||
|
|
||||||
current_tax_amount *= -1.0 if (tax.add_deduct_tax == "Deduct") else 1.0
|
current_tax_amount *= -1.0 if (tax.add_deduct_tax == "Deduct") else 1.0
|
||||||
|
|
||||||
@ -267,6 +270,11 @@ class AccountsController(TransactionBase):
|
|||||||
# 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:
|
||||||
|
tax.total = flt(tax.total, self.precision("total", tax))
|
||||||
|
tax.tax_amount = flt(tax.tax_amount, self.precision("tax_amount", 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
|
||||||
|
@ -175,23 +175,31 @@ class BuyingController(StockController):
|
|||||||
stock_items = self.get_stock_items()
|
stock_items = self.get_stock_items()
|
||||||
|
|
||||||
stock_items_qty, stock_items_amount = 0, 0
|
stock_items_qty, stock_items_amount = 0, 0
|
||||||
|
last_stock_item_idx = 1
|
||||||
for d in self.doclist.get({"parentfield": parentfield}):
|
for d in self.doclist.get({"parentfield": parentfield}):
|
||||||
if d.item_code and d.item_code in stock_items:
|
if d.item_code and d.item_code in stock_items:
|
||||||
stock_items_qty += flt(d.qty)
|
stock_items_qty += flt(d.qty)
|
||||||
stock_items_amount += flt(d.amount)
|
stock_items_amount += flt(d.amount)
|
||||||
|
last_stock_item_idx = d.idx
|
||||||
|
|
||||||
total_valuation_amount = sum([flt(d.tax_amount) for d in
|
total_valuation_amount = sum([flt(d.tax_amount) for d in
|
||||||
self.doclist.get({"parentfield": "purchase_tax_details"})
|
self.doclist.get({"parentfield": "purchase_tax_details"})
|
||||||
if d.category in ["Valuation", "Valuation and Total"]])
|
if d.category in ["Valuation", "Valuation and Total"]])
|
||||||
|
|
||||||
|
|
||||||
for item in self.doclist.get({"parentfield": parentfield}):
|
valuation_amount_adjustment = total_valuation_amount
|
||||||
|
for i, item in enumerate(self.doclist.get({"parentfield": parentfield})):
|
||||||
if item.item_code and item.qty and item.item_code in stock_items:
|
if item.item_code and item.qty and item.item_code in stock_items:
|
||||||
item_proportion = flt(item.amount) / stock_items_amount if stock_items_amount \
|
item_proportion = flt(item.amount) / stock_items_amount if stock_items_amount \
|
||||||
else flt(item.qty) / stock_items_qty
|
else flt(item.qty) / stock_items_qty
|
||||||
|
|
||||||
|
if i == (last_stock_item_idx - 1):
|
||||||
|
item.item_tax_amount = flt(valuation_amount_adjustment,
|
||||||
|
self.precision("item_tax_amount", item))
|
||||||
|
else:
|
||||||
item.item_tax_amount = flt(item_proportion * total_valuation_amount,
|
item.item_tax_amount = flt(item_proportion * total_valuation_amount,
|
||||||
self.precision("item_tax_amount", item))
|
self.precision("item_tax_amount", item))
|
||||||
|
valuation_amount_adjustment -= item.item_tax_amount
|
||||||
|
|
||||||
self.round_floats_in(item)
|
self.round_floats_in(item)
|
||||||
|
|
||||||
|
@ -35,6 +35,7 @@ class TestProductionOrder(unittest.TestCase):
|
|||||||
|
|
||||||
stock_entry.doc.fg_completed_qty = 4
|
stock_entry.doc.fg_completed_qty = 4
|
||||||
stock_entry.doc.posting_date = "2013-05-12"
|
stock_entry.doc.posting_date = "2013-05-12"
|
||||||
|
stock_entry.doc.fiscal_year = "_Test Fiscal Year 2013"
|
||||||
stock_entry.run_method("get_items")
|
stock_entry.run_method("get_items")
|
||||||
stock_entry.submit()
|
stock_entry.submit()
|
||||||
|
|
||||||
@ -52,6 +53,7 @@ class TestProductionOrder(unittest.TestCase):
|
|||||||
stock_entry = make_stock_entry(pro_order, "Manufacture/Repack")
|
stock_entry = make_stock_entry(pro_order, "Manufacture/Repack")
|
||||||
stock_entry = webnotes.bean(stock_entry)
|
stock_entry = webnotes.bean(stock_entry)
|
||||||
stock_entry.doc.posting_date = "2013-05-12"
|
stock_entry.doc.posting_date = "2013-05-12"
|
||||||
|
stock_entry.doc.fiscal_year = "_Test Fiscal Year 2013"
|
||||||
stock_entry.doc.fg_completed_qty = 15
|
stock_entry.doc.fg_completed_qty = 15
|
||||||
stock_entry.run_method("get_items")
|
stock_entry.run_method("get_items")
|
||||||
stock_entry.insert()
|
stock_entry.insert()
|
||||||
|
@ -540,6 +540,14 @@ 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);
|
||||||
@ -550,14 +558,14 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
|
|||||||
|
|
||||||
me.set_item_tax_amount && me.set_item_tax_amount(item, tax, current_tax_amount);
|
me.set_item_tax_amount && me.set_item_tax_amount(item, tax, current_tax_amount);
|
||||||
|
|
||||||
// case when net total is 0 but there is an actual type charge
|
// Adjust divisional loss to the last item
|
||||||
// in this case add the actual amount to tax.tax_amount
|
if (tax.charge_type == "Actual") {
|
||||||
// and tax.grand_total_for_current_item for the first such iteration
|
actual_tax_dict[tax.idx] -= current_tax_amount;
|
||||||
if(tax.charge_type == "Actual" &&
|
if (n == me.frm.item_doclist.length - 1) {
|
||||||
!(current_tax_amount || me.frm.doc.net_total || tax.tax_amount)) {
|
current_tax_amount += actual_tax_dict[tax.idx]
|
||||||
var zero_net_total_adjustment = flt(tax.rate, 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'
|
||||||
@ -589,6 +597,11 @@ 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;
|
||||||
|
|
||||||
|
if (n == me.frm.item_doclist.length - 1) {
|
||||||
|
tax.total = flt(tax.total, precision("total", tax));
|
||||||
|
tax.tax_amount = flt(tax.tax_amount, precision("tax_amount", tax));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import webnotes
|
import webnotes
|
||||||
from webnotes import msgprint, _, throw
|
from webnotes import _, throw
|
||||||
from webnotes.utils import flt, cint, comma_and
|
from webnotes.utils import flt, cint
|
||||||
import json
|
import json
|
||||||
|
|
||||||
def get_customer_list(doctype, txt, searchfield, start, page_len, filters):
|
def get_customer_list(doctype, txt, searchfield, start, page_len, filters):
|
||||||
@ -121,10 +121,16 @@ def _validate_item_details(args, item):
|
|||||||
def _get_basic_details(args, item_bean, warehouse_fieldname):
|
def _get_basic_details(args, item_bean, warehouse_fieldname):
|
||||||
item = item_bean.doc
|
item = item_bean.doc
|
||||||
|
|
||||||
|
from webnotes.defaults import get_user_default_as_list
|
||||||
|
user_default_warehouse_list = get_user_default_as_list('warehouse')
|
||||||
|
user_default_warehouse = user_default_warehouse_list[0] \
|
||||||
|
if len(user_default_warehouse_list)==1 else ""
|
||||||
|
|
||||||
out = webnotes._dict({
|
out = webnotes._dict({
|
||||||
"item_code": item.name,
|
"item_code": item.name,
|
||||||
"description": item.description_html or item.description,
|
"description": item.description_html or item.description,
|
||||||
warehouse_fieldname: item.default_warehouse or args.get(warehouse_fieldname),
|
warehouse_fieldname: user_default_warehouse or item.default_warehouse \
|
||||||
|
or args.get(warehouse_fieldname),
|
||||||
"income_account": item.default_income_account or args.income_account \
|
"income_account": item.default_income_account or args.income_account \
|
||||||
or webnotes.conn.get_value("Company", args.company, "default_income_account"),
|
or webnotes.conn.get_value("Company", args.company, "default_income_account"),
|
||||||
"expense_account": item.purchase_account or args.expense_account \
|
"expense_account": item.purchase_account or args.expense_account \
|
||||||
|
Loading…
x
Reference in New Issue
Block a user