Commonified taxes and totals calculation in server side
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.utils import cint, flt, rounded, cstr, comma_or
|
||||
from frappe.utils import cint, flt, cstr, comma_or
|
||||
from erpnext.setup.utils import get_company_currency
|
||||
from frappe import _, throw
|
||||
from erpnext.stock.get_item_details import get_available_qty
|
||||
@@ -121,157 +121,6 @@ class SellingController(StockController):
|
||||
self.in_words = money_in_words(disable_rounded_total and
|
||||
self.grand_total or self.rounded_total, self.currency)
|
||||
|
||||
def calculate_taxes_and_totals(self):
|
||||
super(SellingController, self).calculate_taxes_and_totals()
|
||||
|
||||
self.calculate_total_advance("Sales Invoice", "advances")
|
||||
self.calculate_commission()
|
||||
self.calculate_contribution()
|
||||
|
||||
def determine_exclusive_rate(self):
|
||||
if not any((cint(tax.included_in_print_rate) for tax in self.get("taxes"))):
|
||||
# no inclusive tax
|
||||
return
|
||||
|
||||
for item in self.get("items"):
|
||||
item_tax_map = self._load_item_tax_rate(item.item_tax_rate)
|
||||
cumulated_tax_fraction = 0
|
||||
for i, tax in enumerate(self.get("taxes")):
|
||||
tax.tax_fraction_for_current_item = self.get_current_tax_fraction(tax, item_tax_map)
|
||||
|
||||
if i==0:
|
||||
tax.grand_total_fraction_for_current_item = 1 + tax.tax_fraction_for_current_item
|
||||
else:
|
||||
tax.grand_total_fraction_for_current_item = \
|
||||
self.get("taxes")[i-1].grand_total_fraction_for_current_item \
|
||||
+ tax.tax_fraction_for_current_item
|
||||
|
||||
cumulated_tax_fraction += tax.tax_fraction_for_current_item
|
||||
|
||||
if cumulated_tax_fraction and not self.discount_amount_applied and item.qty:
|
||||
item.base_amount = flt((item.amount * self.conversion_rate) /
|
||||
(1 + cumulated_tax_fraction), self.precision("base_amount", item))
|
||||
|
||||
item.base_rate = flt(item.base_amount / item.qty, self.precision("base_rate", item))
|
||||
item.discount_percentage = flt(item.discount_percentage, self.precision("discount_percentage", item))
|
||||
|
||||
if item.discount_percentage == 100:
|
||||
item.base_price_list_rate = item.base_rate
|
||||
item.base_rate = 0.0
|
||||
else:
|
||||
item.base_price_list_rate = flt(item.base_rate / (1 - (item.discount_percentage / 100.0)),
|
||||
self.precision("base_price_list_rate", item))
|
||||
|
||||
def get_current_tax_fraction(self, tax, item_tax_map):
|
||||
"""
|
||||
Get tax fraction for calculating tax exclusive amount
|
||||
from tax inclusive amount
|
||||
"""
|
||||
current_tax_fraction = 0
|
||||
|
||||
if cint(tax.included_in_print_rate):
|
||||
tax_rate = self._get_tax_rate(tax, item_tax_map)
|
||||
|
||||
if tax.charge_type == "On Net Total":
|
||||
current_tax_fraction = tax_rate / 100.0
|
||||
|
||||
elif tax.charge_type == "On Previous Row Amount":
|
||||
current_tax_fraction = (tax_rate / 100.0) * \
|
||||
self.get("taxes")[cint(tax.row_id) - 1].tax_fraction_for_current_item
|
||||
|
||||
elif tax.charge_type == "On Previous Row Total":
|
||||
current_tax_fraction = (tax_rate / 100.0) * \
|
||||
self.get("taxes")[cint(tax.row_id) - 1].grand_total_fraction_for_current_item
|
||||
|
||||
return current_tax_fraction
|
||||
|
||||
def calculate_item_values(self):
|
||||
if not self.discount_amount_applied:
|
||||
for item in self.get("items"):
|
||||
self.round_floats_in(item)
|
||||
|
||||
if item.discount_percentage == 100:
|
||||
item.rate = 0
|
||||
elif not item.rate:
|
||||
item.rate = flt(item.price_list_rate * (1.0 - (item.discount_percentage / 100.0)),
|
||||
self.precision("rate", item))
|
||||
|
||||
item.amount = flt(item.rate * item.qty,
|
||||
self.precision("amount", item))
|
||||
|
||||
self._set_in_company_currency(item, "price_list_rate", "base_price_list_rate")
|
||||
self._set_in_company_currency(item, "rate", "base_rate")
|
||||
self._set_in_company_currency(item, "amount", "base_amount")
|
||||
|
||||
def calculate_net_total(self):
|
||||
self.base_net_total = self.net_total = 0.0
|
||||
|
||||
for item in self.get("items"):
|
||||
self.base_net_total += item.base_amount
|
||||
self.net_total += item.amount
|
||||
|
||||
self.round_floats_in(self, ["base_net_total", "net_total"])
|
||||
|
||||
def calculate_totals(self):
|
||||
self.base_grand_total = flt(self.get("taxes")[-1].total if self.get("taxes") else self.base_net_total)
|
||||
|
||||
self.base_total_taxes_and_charges = flt(self.base_grand_total - self.base_net_total, self.precision("base_total_taxes_and_charges"))
|
||||
|
||||
self.grand_total = flt(self.base_grand_total / self.conversion_rate) \
|
||||
if (self.base_total_taxes_and_charges or self.discount_amount) else self.net_total
|
||||
|
||||
self.total_taxes_and_charges = flt(self.grand_total - self.net_total +
|
||||
flt(self.discount_amount), self.precision("total_taxes_and_charges"))
|
||||
|
||||
self.base_grand_total = flt(self.base_grand_total, self.precision("base_grand_total"))
|
||||
self.grand_total = flt(self.grand_total, self.precision("grand_total"))
|
||||
|
||||
self.base_rounded_total = rounded(self.base_grand_total)
|
||||
self.rounded_total = rounded(self.grand_total)
|
||||
|
||||
def apply_discount_amount(self):
|
||||
if self.discount_amount:
|
||||
self.base_discount_amount = flt(self.discount_amount * self.conversion_rate, self.precision("base_discount_amount"))
|
||||
|
||||
grand_total_for_discount_amount = self.get_grand_total_for_discount_amount()
|
||||
|
||||
if grand_total_for_discount_amount:
|
||||
# calculate item amount after Discount Amount
|
||||
for item in self.get("items"):
|
||||
distributed_amount = flt(self.base_discount_amount) * item.base_amount / grand_total_for_discount_amount
|
||||
item.base_amount = flt(item.base_amount - distributed_amount, self.precision("base_amount", item))
|
||||
|
||||
self.discount_amount_applied = True
|
||||
self._calculate_taxes_and_totals()
|
||||
else:
|
||||
self.base_discount_amount = 0
|
||||
|
||||
def get_grand_total_for_discount_amount(self):
|
||||
actual_taxes_dict = {}
|
||||
|
||||
for tax in self.get("taxes"):
|
||||
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)
|
||||
|
||||
grand_total_for_discount_amount = flt(self.base_grand_total - sum(actual_taxes_dict.values()),
|
||||
self.precision("base_grand_total"))
|
||||
return grand_total_for_discount_amount
|
||||
|
||||
def calculate_outstanding_amount(self):
|
||||
# NOTE:
|
||||
# write_off_amount is only for POS Invoice
|
||||
# total_advance is only for non POS Invoice
|
||||
if self.doctype == "Sales Invoice" and self.docstatus == 0:
|
||||
self.round_floats_in(self, ["base_grand_total", "total_advance", "write_off_amount",
|
||||
"paid_amount"])
|
||||
total_amount_to_pay = self.base_grand_total - self.write_off_amount
|
||||
self.outstanding_amount = flt(total_amount_to_pay - self.total_advance \
|
||||
- self.paid_amount, self.precision("outstanding_amount"))
|
||||
|
||||
def calculate_commission(self):
|
||||
if self.meta.get_field("commission_rate"):
|
||||
self.round_floats_in(self, ["base_net_total", "commission_rate"])
|
||||
|
||||
Reference in New Issue
Block a user