mirror of
https://github.com/frappe/erpnext.git
synced 2026-09-18 02:55:20 +00:00
Validate taxes and charges input, commonified
This commit is contained in:
@@ -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,))
|
||||
|
||||
@@ -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"]:
|
||||
|
||||
Reference in New Issue
Block a user