Validate taxes and charges input, commonified

This commit is contained in:
Nabin Hait
2015-02-23 11:58:15 +05:30
parent 34afcfb4a1
commit 613d081a60
18 changed files with 242 additions and 340 deletions

View File

@@ -4,7 +4,7 @@
from __future__ import unicode_literals
import frappe
from frappe import _, throw
from frappe.utils import today, flt
from frappe.utils import today, flt, cint
from erpnext.setup.utils import get_company_currency, get_exchange_rate
from erpnext.accounts.utils import get_fiscal_year, validate_fiscal_year
from erpnext.utilities.transaction_base import TransactionBase
@@ -357,3 +357,34 @@ def validate_conversion_rate(currency, conversion_rate, conversion_rate_label, c
if not conversion_rate:
throw(_("{0} is mandatory. Maybe Currency Exchange record is not created for {1} to {2}.").format(
conversion_rate_label, currency, company_currency))
def validate_taxes_and_charges(tax):
if not tax.charge_type and (tax.row_id or tax.rate or tax.tax_amount):
frappe.throw(_("Please select Charge Type first"))
elif tax.charge_type in ['Actual', 'On Net Total'] and tax.row_id:
frappe.throw(_("Can refer row only if the charge type is 'On Previous Row Amount' or 'Previous Row Total'"))
elif tax.charge_type in ['On Previous Row Amount', 'On Previous Row Total'] and tax.row_id:
if cint(tax.idx) == 1:
frappe.throw(_("Cannot select charge type as 'On Previous Row Amount' or 'On Previous Row Total' for first row"))
elif not tax.row_id:
frappe.throw(_("Please specify a valid Row ID for row {0} in table {1}".format(tax.idx, _(tax.doctype))))
elif tax.row_id and cint(tax.row_id) >= cint(tax.idx):
frappe.throw(_("Cannot refer row number greater than or equal to current row number for this Charge type"))
def validate_inclusive_tax(tax, doc):
def _on_previous_row_error(row_range):
throw(_("To include tax in row {0} in Item rate, taxes in rows {1} must also be included").format(tax.idx,
row_range))
if cint(getattr(tax, "included_in_print_rate", None)):
if tax.charge_type == "Actual":
# inclusive tax cannot be of type Actual
throw(_("Charge of type 'Actual' in row {0} cannot be included in Item Rate").format(tax.idx))
elif tax.charge_type == "On Previous Row Amount" and \
not cint(doc.get("taxes")[cint(tax.row_id) - 1].included_in_print_rate):
# referred row should also be inclusive
_on_previous_row_error(tax.row_id)
elif tax.charge_type == "On Previous Row Total" and \
not all([cint(t.included_in_print_rate) for t in doc.get("taxes")[:cint(tax.row_id) - 1]]):
# all rows about the reffered tax should be inclusive
_on_previous_row_error("1 - %d" % (tax.row_id,))

View File

@@ -3,10 +3,10 @@
from __future__ import unicode_literals
import json
from frappe import _, throw
from frappe.utils import cint, flt, rounded
from erpnext.setup.utils import get_company_currency
from erpnext.controllers.accounts_controller import validate_conversion_rate
from erpnext.controllers.accounts_controller import validate_conversion_rate, \
validate_taxes_and_charges, validate_inclusive_tax
class calculate_taxes_and_totals(object):
def __init__(self, doc):
@@ -71,6 +71,9 @@ class calculate_taxes_and_totals(object):
def initialize_taxes(self):
for tax in self.doc.get("taxes"):
validate_taxes_and_charges(tax)
validate_inclusive_tax(tax, self.doc)
tax.item_wise_tax_detail = {}
tax_fields = ["total", "tax_amount_after_discount_amount",
"tax_amount_for_current_item", "grand_total_for_current_item",
@@ -83,37 +86,8 @@ class calculate_taxes_and_totals(object):
for fieldname in tax_fields:
tax.set(fieldname, 0.0)
self.validate_on_previous_row(tax)
self.validate_inclusive_tax(tax)
self.doc.round_floats_in(tax)
def validate_on_previous_row(self, tax):
"""
validate if a valid row id is mentioned in case of
On Previous Row Amount and On Previous Row Total
"""
if tax.charge_type in ["On Previous Row Amount", "On Previous Row Total"] and \
(not tax.row_id or cint(tax.row_id) >= tax.idx):
throw(_("Please specify a valid Row ID for {0} in row {1}").format(_(tax.doctype), tax.idx))
def validate_inclusive_tax(self, tax):
def _on_previous_row_error(row_range):
throw(_("To include tax in row {0} in Item rate, taxes in rows {1} must also be included").format(tax.idx,
row_range))
if cint(getattr(tax, "included_in_print_rate", None)):
if tax.charge_type == "Actual":
# inclusive tax cannot be of type Actual
throw(_("Charge of type 'Actual' in row {0} cannot be included in Item Rate").format(tax.idx))
elif tax.charge_type == "On Previous Row Amount" and \
not cint(self.doc.get("taxes")[cint(tax.row_id) - 1].included_in_print_rate):
# referred row should also be inclusive
_on_previous_row_error(tax.row_id)
elif tax.charge_type == "On Previous Row Total" and \
not all([cint(t.included_in_print_rate) for t in self.doc.get("taxes")[:cint(tax.row_id) - 1]]):
# all rows about the reffered tax should be inclusive
_on_previous_row_error("1 - %d" % (tax.row_id,))
def determine_exclusive_rate(self):
if not any((cint(tax.included_in_print_rate) for tax in self.doc.get("taxes"))) or \
self.doc.doctype not in ["Quotation", "Sales Order", "Delivery Note", "Sales Invoice"]: