style: format code with black

This commit is contained in:
Ankush Menat
2022-03-28 18:52:46 +05:30
parent 21e00da3d6
commit 494bd9ef78
1395 changed files with 91704 additions and 62532 deletions

View File

@@ -59,23 +59,23 @@ class calculate_taxes_and_totals(object):
self.calculate_total_net_weight()
def validate_item_tax_template(self):
for item in self.doc.get('items'):
if item.item_code and item.get('item_tax_template'):
for item in self.doc.get("items"):
if item.item_code and item.get("item_tax_template"):
item_doc = frappe.get_cached_doc("Item", item.item_code)
args = {
'net_rate': item.net_rate or item.rate,
'tax_category': self.doc.get('tax_category'),
'posting_date': self.doc.get('posting_date'),
'bill_date': self.doc.get('bill_date'),
'transaction_date': self.doc.get('transaction_date'),
'company': self.doc.get('company')
"net_rate": item.net_rate or item.rate,
"tax_category": self.doc.get("tax_category"),
"posting_date": self.doc.get("posting_date"),
"bill_date": self.doc.get("bill_date"),
"transaction_date": self.doc.get("transaction_date"),
"company": self.doc.get("company"),
}
item_group = item_doc.item_group
item_group_taxes = []
while item_group:
item_group_doc = frappe.get_cached_doc('Item Group', item_group)
item_group_doc = frappe.get_cached_doc("Item Group", item_group)
item_group_taxes += item_group_doc.taxes or []
item_group = item_group_doc.parent_item_group
@@ -90,9 +90,11 @@ class calculate_taxes_and_totals(object):
if taxes:
if item.item_tax_template not in taxes:
item.item_tax_template = taxes[0]
frappe.msgprint(_("Row {0}: Item Tax template updated as per validity and rate applied").format(
item.idx, frappe.bold(item.item_code)
))
frappe.msgprint(
_("Row {0}: Item Tax template updated as per validity and rate applied").format(
item.idx, frappe.bold(item.item_code)
)
)
def validate_conversion_rate(self):
# validate conversion rate
@@ -101,13 +103,17 @@ class calculate_taxes_and_totals(object):
self.doc.currency = company_currency
self.doc.conversion_rate = 1.0
else:
validate_conversion_rate(self.doc.currency, self.doc.conversion_rate,
self.doc.meta.get_label("conversion_rate"), self.doc.company)
validate_conversion_rate(
self.doc.currency,
self.doc.conversion_rate,
self.doc.meta.get_label("conversion_rate"),
self.doc.company,
)
self.doc.conversion_rate = flt(self.doc.conversion_rate)
def calculate_item_values(self):
if self.doc.get('is_consolidated'):
if self.doc.get("is_consolidated"):
return
if not self.discount_amount_applied:
@@ -118,19 +124,30 @@ class calculate_taxes_and_totals(object):
item.rate = 0.0
elif item.price_list_rate:
if not item.rate or (item.pricing_rules and item.discount_percentage > 0):
item.rate = flt(item.price_list_rate *
(1.0 - (item.discount_percentage / 100.0)), item.precision("rate"))
item.rate = flt(
item.price_list_rate * (1.0 - (item.discount_percentage / 100.0)), item.precision("rate")
)
item.discount_amount = item.price_list_rate * (item.discount_percentage / 100.0)
elif item.discount_amount and item.pricing_rules:
item.rate = item.price_list_rate - item.discount_amount
item.rate = item.price_list_rate - item.discount_amount
if item.doctype in ['Quotation Item', 'Sales Order Item', 'Delivery Note Item', 'Sales Invoice Item',
'POS Invoice Item', 'Purchase Invoice Item', 'Purchase Order Item', 'Purchase Receipt Item']:
if item.doctype in [
"Quotation Item",
"Sales Order Item",
"Delivery Note Item",
"Sales Invoice Item",
"POS Invoice Item",
"Purchase Invoice Item",
"Purchase Order Item",
"Purchase Receipt Item",
]:
item.rate_with_margin, item.base_rate_with_margin = self.calculate_margin(item)
if flt(item.rate_with_margin) > 0:
item.rate = flt(item.rate_with_margin * (1.0 - (item.discount_percentage / 100.0)), item.precision("rate"))
item.rate = flt(
item.rate_with_margin * (1.0 - (item.discount_percentage / 100.0)), item.precision("rate")
)
if item.discount_amount and not item.discount_percentage:
item.rate = item.rate_with_margin - item.discount_amount
@@ -149,18 +166,22 @@ class calculate_taxes_and_totals(object):
elif not item.qty and self.doc.get("is_debit_note"):
item.amount = flt(item.rate, item.precision("amount"))
else:
item.amount = flt(item.rate * item.qty, item.precision("amount"))
item.amount = flt(item.rate * item.qty, item.precision("amount"))
item.net_amount = item.amount
self._set_in_company_currency(item, ["price_list_rate", "rate", "net_rate", "amount", "net_amount"])
self._set_in_company_currency(
item, ["price_list_rate", "rate", "net_rate", "amount", "net_amount"]
)
item.item_tax_amount = 0.0
def _set_in_company_currency(self, doc, fields):
"""set values in base currency"""
for f in fields:
val = flt(flt(doc.get(f), doc.precision(f)) * self.doc.conversion_rate, doc.precision("base_" + f))
val = flt(
flt(doc.get(f), doc.precision(f)) * self.doc.conversion_rate, doc.precision("base_" + f)
)
doc.set("base_" + f, val)
def initialize_taxes(self):
@@ -169,16 +190,22 @@ class calculate_taxes_and_totals(object):
validate_taxes_and_charges(tax)
validate_inclusive_tax(tax, self.doc)
if not (self.doc.get('is_consolidated') or tax.get("dont_recompute_tax")):
if not (self.doc.get("is_consolidated") or tax.get("dont_recompute_tax")):
tax.item_wise_tax_detail = {}
tax_fields = ["total", "tax_amount_after_discount_amount",
"tax_amount_for_current_item", "grand_total_for_current_item",
"tax_fraction_for_current_item", "grand_total_fraction_for_current_item"]
tax_fields = [
"total",
"tax_amount_after_discount_amount",
"tax_amount_for_current_item",
"grand_total_for_current_item",
"tax_fraction_for_current_item",
"grand_total_fraction_for_current_item",
]
if tax.charge_type != "Actual" and \
not (self.discount_amount_applied and self.doc.apply_discount_on=="Grand Total"):
tax_fields.append("tax_amount")
if tax.charge_type != "Actual" and not (
self.discount_amount_applied and self.doc.apply_discount_on == "Grand Total"
):
tax_fields.append("tax_amount")
for fieldname in tax_fields:
tax.set(fieldname, 0.0)
@@ -194,25 +221,32 @@ class calculate_taxes_and_totals(object):
cumulated_tax_fraction = 0
total_inclusive_tax_amount_per_qty = 0
for i, tax in enumerate(self.doc.get("taxes")):
tax.tax_fraction_for_current_item, inclusive_tax_amount_per_qty = self.get_current_tax_fraction(tax, item_tax_map)
(
tax.tax_fraction_for_current_item,
inclusive_tax_amount_per_qty,
) = self.get_current_tax_fraction(tax, item_tax_map)
if i==0:
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.doc.get("taxes")[i-1].grand_total_fraction_for_current_item \
tax.grand_total_fraction_for_current_item = (
self.doc.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
total_inclusive_tax_amount_per_qty += inclusive_tax_amount_per_qty * flt(item.qty)
if not self.discount_amount_applied and item.qty and (cumulated_tax_fraction or total_inclusive_tax_amount_per_qty):
if (
not self.discount_amount_applied
and item.qty
and (cumulated_tax_fraction or total_inclusive_tax_amount_per_qty)
):
amount = flt(item.amount) - total_inclusive_tax_amount_per_qty
item.net_amount = flt(amount / (1 + cumulated_tax_fraction))
item.net_rate = flt(item.net_amount / item.qty, item.precision("net_rate"))
item.discount_percentage = flt(item.discount_percentage,
item.precision("discount_percentage"))
item.discount_percentage = flt(item.discount_percentage, item.precision("discount_percentage"))
self._set_in_company_currency(item, ["net_rate", "net_amount"])
@@ -221,8 +255,8 @@ class calculate_taxes_and_totals(object):
def get_current_tax_fraction(self, tax, item_tax_map):
"""
Get tax fraction for calculating tax exclusive amount
from tax inclusive amount
Get tax fraction for calculating tax exclusive amount
from tax inclusive amount
"""
current_tax_fraction = 0
inclusive_tax_amount_per_qty = 0
@@ -234,12 +268,14 @@ class calculate_taxes_and_totals(object):
current_tax_fraction = tax_rate / 100.0
elif tax.charge_type == "On Previous Row Amount":
current_tax_fraction = (tax_rate / 100.0) * \
self.doc.get("taxes")[cint(tax.row_id) - 1].tax_fraction_for_current_item
current_tax_fraction = (tax_rate / 100.0) * self.doc.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.doc.get("taxes")[cint(tax.row_id) - 1].grand_total_fraction_for_current_item
current_tax_fraction = (tax_rate / 100.0) * self.doc.get("taxes")[
cint(tax.row_id) - 1
].grand_total_fraction_for_current_item
elif tax.charge_type == "On Item Quantity":
inclusive_tax_amount_per_qty = flt(tax_rate)
@@ -257,7 +293,9 @@ class calculate_taxes_and_totals(object):
return tax.rate
def calculate_net_total(self):
self.doc.total_qty = self.doc.total = self.doc.base_total = self.doc.net_total = self.doc.base_net_total = 0.0
self.doc.total_qty = (
self.doc.total
) = self.doc.base_total = self.doc.net_total = self.doc.base_net_total = 0.0
for item in self.doc.get("items"):
self.doc.total += item.amount
@@ -276,13 +314,20 @@ class calculate_taxes_and_totals(object):
self._calculate()
def calculate_taxes(self):
rounding_adjustment_computed = self.doc.get('is_consolidated') and self.doc.get('rounding_adjustment')
rounding_adjustment_computed = self.doc.get("is_consolidated") and self.doc.get(
"rounding_adjustment"
)
if not rounding_adjustment_computed:
self.doc.rounding_adjustment = 0
# maintain actual tax rate based on idx
actual_tax_dict = dict([[tax.idx, flt(tax.tax_amount, tax.precision("tax_amount"))]
for tax in self.doc.get("taxes") if tax.charge_type == "Actual"])
actual_tax_dict = dict(
[
[tax.idx, flt(tax.tax_amount, tax.precision("tax_amount"))]
for tax in self.doc.get("taxes")
if tax.charge_type == "Actual"
]
)
for n, item in enumerate(self.doc.get("items")):
item_tax_map = self._load_item_tax_rate(item.item_tax_rate)
@@ -297,9 +342,10 @@ class calculate_taxes_and_totals(object):
current_tax_amount += actual_tax_dict[tax.idx]
# accumulate tax amount into tax.tax_amount
if tax.charge_type != "Actual" and \
not (self.discount_amount_applied and self.doc.apply_discount_on=="Grand Total"):
tax.tax_amount += current_tax_amount
if tax.charge_type != "Actual" and not (
self.discount_amount_applied and self.doc.apply_discount_on == "Grand Total"
):
tax.tax_amount += current_tax_amount
# store tax_amount for current item as it will be used for
# charge type = 'On Previous Row Amount'
@@ -312,17 +358,17 @@ class calculate_taxes_and_totals(object):
# note: grand_total_for_current_item contains the contribution of
# 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.net_amount + current_tax_amount)
else:
tax.grand_total_for_current_item = \
flt(self.doc.get("taxes")[i-1].grand_total_for_current_item + current_tax_amount)
tax.grand_total_for_current_item = flt(
self.doc.get("taxes")[i - 1].grand_total_for_current_item + current_tax_amount
)
# set precision in the last item iteration
if n == len(self.doc.get("items")) - 1:
self.round_off_totals(tax)
self._set_in_company_currency(tax,
["tax_amount", "tax_amount_after_discount_amount"])
self._set_in_company_currency(tax, ["tax_amount", "tax_amount_after_discount_amount"])
self.round_off_base_values(tax)
self.set_cumulative_total(i, tax)
@@ -330,20 +376,29 @@ class calculate_taxes_and_totals(object):
self._set_in_company_currency(tax, ["total"])
# adjust Discount Amount loss in last tax iteration
if i == (len(self.doc.get("taxes")) - 1) and self.discount_amount_applied \
and self.doc.discount_amount \
and self.doc.apply_discount_on == "Grand Total" \
and not rounding_adjustment_computed:
self.doc.rounding_adjustment = flt(self.doc.grand_total
- flt(self.doc.discount_amount) - tax.total,
self.doc.precision("rounding_adjustment"))
if (
i == (len(self.doc.get("taxes")) - 1)
and self.discount_amount_applied
and self.doc.discount_amount
and self.doc.apply_discount_on == "Grand Total"
and not rounding_adjustment_computed
):
self.doc.rounding_adjustment = flt(
self.doc.grand_total - flt(self.doc.discount_amount) - tax.total,
self.doc.precision("rounding_adjustment"),
)
def get_tax_amount_if_for_valuation_or_deduction(self, tax_amount, tax):
# if just for valuation, do not add the tax amount in total
# if tax/charges is for deduction, multiply by -1
if getattr(tax, "category", None):
tax_amount = 0.0 if (tax.category == "Valuation") else tax_amount
if self.doc.doctype in ["Purchase Order", "Purchase Invoice", "Purchase Receipt", "Supplier Quotation"]:
if self.doc.doctype in [
"Purchase Order",
"Purchase Invoice",
"Purchase Receipt",
"Supplier Quotation",
]:
tax_amount *= -1.0 if (tax.add_deduct_tax == "Deduct") else 1.0
return tax_amount
@@ -354,7 +409,7 @@ class calculate_taxes_and_totals(object):
if row_idx == 0:
tax.total = flt(self.doc.net_total + tax_amount, tax.precision("total"))
else:
tax.total = flt(self.doc.get("taxes")[row_idx-1].total + tax_amount, tax.precision("total"))
tax.total = flt(self.doc.get("taxes")[row_idx - 1].total + tax_amount, tax.precision("total"))
def get_current_tax_amount(self, item, tax, item_tax_map):
tax_rate = self._get_tax_rate(tax, item_tax_map)
@@ -363,16 +418,20 @@ class calculate_taxes_and_totals(object):
if tax.charge_type == "Actual":
# distribute the tax amount proportionally to each item row
actual = flt(tax.tax_amount, tax.precision("tax_amount"))
current_tax_amount = item.net_amount*actual / self.doc.net_total if self.doc.net_total else 0.0
current_tax_amount = (
item.net_amount * actual / self.doc.net_total if self.doc.net_total else 0.0
)
elif tax.charge_type == "On Net Total":
current_tax_amount = (tax_rate / 100.0) * item.net_amount
elif tax.charge_type == "On Previous Row Amount":
current_tax_amount = (tax_rate / 100.0) * \
self.doc.get("taxes")[cint(tax.row_id) - 1].tax_amount_for_current_item
current_tax_amount = (tax_rate / 100.0) * self.doc.get("taxes")[
cint(tax.row_id) - 1
].tax_amount_for_current_item
elif tax.charge_type == "On Previous Row Total":
current_tax_amount = (tax_rate / 100.0) * \
self.doc.get("taxes")[cint(tax.row_id) - 1].grand_total_for_current_item
current_tax_amount = (tax_rate / 100.0) * self.doc.get("taxes")[
cint(tax.row_id) - 1
].grand_total_for_current_item
elif tax.charge_type == "On Item Quantity":
current_tax_amount = tax_rate * item.qty
@@ -384,11 +443,11 @@ class calculate_taxes_and_totals(object):
def set_item_wise_tax(self, item, tax, tax_rate, current_tax_amount):
# store tax breakup for each item
key = item.item_code or item.item_name
item_wise_tax_amount = current_tax_amount*self.doc.conversion_rate
item_wise_tax_amount = current_tax_amount * self.doc.conversion_rate
if tax.item_wise_tax_detail.get(key):
item_wise_tax_amount += tax.item_wise_tax_detail[key][1]
tax.item_wise_tax_detail[key] = [tax_rate,flt(item_wise_tax_amount)]
tax.item_wise_tax_detail[key] = [tax_rate, flt(item_wise_tax_amount)]
def round_off_totals(self, tax):
if tax.account_head in frappe.flags.round_off_applicable_accounts:
@@ -396,8 +455,9 @@ class calculate_taxes_and_totals(object):
tax.tax_amount_after_discount_amount = round(tax.tax_amount_after_discount_amount, 0)
tax.tax_amount = flt(tax.tax_amount, tax.precision("tax_amount"))
tax.tax_amount_after_discount_amount = flt(tax.tax_amount_after_discount_amount,
tax.precision("tax_amount"))
tax.tax_amount_after_discount_amount = flt(
tax.tax_amount_after_discount_amount, tax.precision("tax_amount")
)
def round_off_base_values(self, tax):
# Round off to nearest integer based on regional settings
@@ -409,11 +469,15 @@ class calculate_taxes_and_totals(object):
# if fully inclusive taxes and diff
if self.doc.get("taxes") and any(cint(t.included_in_print_rate) for t in self.doc.get("taxes")):
last_tax = self.doc.get("taxes")[-1]
non_inclusive_tax_amount = sum(flt(d.tax_amount_after_discount_amount)
for d in self.doc.get("taxes") if not d.included_in_print_rate)
non_inclusive_tax_amount = sum(
flt(d.tax_amount_after_discount_amount)
for d in self.doc.get("taxes")
if not d.included_in_print_rate
)
diff = self.doc.total + non_inclusive_tax_amount \
- flt(last_tax.total, last_tax.precision("total"))
diff = (
self.doc.total + non_inclusive_tax_amount - flt(last_tax.total, last_tax.precision("total"))
)
# If discount amount applied, deduct the discount amount
# because self.doc.total is always without discount, but last_tax.total is after discount
@@ -422,7 +486,7 @@ class calculate_taxes_and_totals(object):
diff = flt(diff, self.doc.precision("rounding_adjustment"))
if diff and abs(diff) <= (5.0 / 10**last_tax.precision("tax_amount")):
if diff and abs(diff) <= (5.0 / 10 ** last_tax.precision("tax_amount")):
self.doc.rounding_adjustment = diff
def calculate_totals(self):
@@ -432,16 +496,27 @@ class calculate_taxes_and_totals(object):
self.doc.grand_total = flt(self.doc.net_total)
if self.doc.get("taxes"):
self.doc.total_taxes_and_charges = flt(self.doc.grand_total - self.doc.net_total
- flt(self.doc.rounding_adjustment), self.doc.precision("total_taxes_and_charges"))
self.doc.total_taxes_and_charges = flt(
self.doc.grand_total - self.doc.net_total - flt(self.doc.rounding_adjustment),
self.doc.precision("total_taxes_and_charges"),
)
else:
self.doc.total_taxes_and_charges = 0.0
self._set_in_company_currency(self.doc, ["total_taxes_and_charges", "rounding_adjustment"])
if self.doc.doctype in ["Quotation", "Sales Order", "Delivery Note", "Sales Invoice", "POS Invoice"]:
self.doc.base_grand_total = flt(self.doc.grand_total * self.doc.conversion_rate, self.doc.precision("base_grand_total")) \
if self.doc.total_taxes_and_charges else self.doc.base_net_total
if self.doc.doctype in [
"Quotation",
"Sales Order",
"Delivery Note",
"Sales Invoice",
"POS Invoice",
]:
self.doc.base_grand_total = (
flt(self.doc.grand_total * self.doc.conversion_rate, self.doc.precision("base_grand_total"))
if self.doc.total_taxes_and_charges
else self.doc.base_net_total
)
else:
self.doc.taxes_and_charges_added = self.doc.taxes_and_charges_deducted = 0.0
for tax in self.doc.get("taxes"):
@@ -453,26 +528,29 @@ class calculate_taxes_and_totals(object):
self.doc.round_floats_in(self.doc, ["taxes_and_charges_added", "taxes_and_charges_deducted"])
self.doc.base_grand_total = flt(self.doc.grand_total * self.doc.conversion_rate) \
if (self.doc.taxes_and_charges_added or self.doc.taxes_and_charges_deducted) \
self.doc.base_grand_total = (
flt(self.doc.grand_total * self.doc.conversion_rate)
if (self.doc.taxes_and_charges_added or self.doc.taxes_and_charges_deducted)
else self.doc.base_net_total
)
self._set_in_company_currency(self.doc,
["taxes_and_charges_added", "taxes_and_charges_deducted"])
self._set_in_company_currency(
self.doc, ["taxes_and_charges_added", "taxes_and_charges_deducted"]
)
self.doc.round_floats_in(self.doc, ["grand_total", "base_grand_total"])
self.set_rounded_total()
def calculate_total_net_weight(self):
if self.doc.meta.get_field('total_net_weight'):
if self.doc.meta.get_field("total_net_weight"):
self.doc.total_net_weight = 0.0
for d in self.doc.items:
if d.total_weight:
self.doc.total_net_weight += d.total_weight
def set_rounded_total(self):
if self.doc.get('is_consolidated') and self.doc.get('rounding_adjustment'):
if self.doc.get("is_consolidated") and self.doc.get("rounding_adjustment"):
return
if self.doc.meta.get_field("rounded_total"):
@@ -480,33 +558,40 @@ class calculate_taxes_and_totals(object):
self.doc.rounded_total = self.doc.base_rounded_total = 0
return
self.doc.rounded_total = round_based_on_smallest_currency_fraction(self.doc.grand_total,
self.doc.currency, self.doc.precision("rounded_total"))
self.doc.rounded_total = round_based_on_smallest_currency_fraction(
self.doc.grand_total, self.doc.currency, self.doc.precision("rounded_total")
)
#if print_in_rate is set, we would have already calculated rounding adjustment
self.doc.rounding_adjustment += flt(self.doc.rounded_total - self.doc.grand_total,
self.doc.precision("rounding_adjustment"))
# if print_in_rate is set, we would have already calculated rounding adjustment
self.doc.rounding_adjustment += flt(
self.doc.rounded_total - self.doc.grand_total, self.doc.precision("rounding_adjustment")
)
self._set_in_company_currency(self.doc, ["rounding_adjustment", "rounded_total"])
def _cleanup(self):
if not self.doc.get('is_consolidated'):
if not self.doc.get("is_consolidated"):
for tax in self.doc.get("taxes"):
if not tax.get("dont_recompute_tax"):
tax.item_wise_tax_detail = json.dumps(tax.item_wise_tax_detail, separators=(',', ':'))
tax.item_wise_tax_detail = json.dumps(tax.item_wise_tax_detail, separators=(",", ":"))
def set_discount_amount(self):
if self.doc.additional_discount_percentage:
self.doc.discount_amount = flt(flt(self.doc.get(scrub(self.doc.apply_discount_on)))
* self.doc.additional_discount_percentage / 100, self.doc.precision("discount_amount"))
self.doc.discount_amount = flt(
flt(self.doc.get(scrub(self.doc.apply_discount_on)))
* self.doc.additional_discount_percentage
/ 100,
self.doc.precision("discount_amount"),
)
def apply_discount_amount(self):
if self.doc.discount_amount:
if not self.doc.apply_discount_on:
frappe.throw(_("Please select Apply Discount On"))
self.doc.base_discount_amount = flt(self.doc.discount_amount * self.doc.conversion_rate,
self.doc.precision("base_discount_amount"))
self.doc.base_discount_amount = flt(
self.doc.discount_amount * self.doc.conversion_rate, self.doc.precision("base_discount_amount")
)
total_for_discount_amount = self.get_total_for_discount_amount()
taxes = self.doc.get("taxes")
@@ -515,20 +600,24 @@ class calculate_taxes_and_totals(object):
if total_for_discount_amount:
# calculate item amount after Discount Amount
for i, item in enumerate(self.doc.get("items")):
distributed_amount = flt(self.doc.discount_amount) * \
item.net_amount / total_for_discount_amount
distributed_amount = (
flt(self.doc.discount_amount) * item.net_amount / total_for_discount_amount
)
item.net_amount = flt(item.net_amount - distributed_amount, item.precision("net_amount"))
net_total += item.net_amount
# discount amount rounding loss adjustment if no taxes
if (self.doc.apply_discount_on == "Net Total" or not taxes or total_for_discount_amount==self.doc.net_total) \
and i == len(self.doc.get("items")) - 1:
discount_amount_loss = flt(self.doc.net_total - net_total - self.doc.discount_amount,
self.doc.precision("net_total"))
if (
self.doc.apply_discount_on == "Net Total"
or not taxes
or total_for_discount_amount == self.doc.net_total
) and i == len(self.doc.get("items")) - 1:
discount_amount_loss = flt(
self.doc.net_total - net_total - self.doc.discount_amount, self.doc.precision("net_total")
)
item.net_amount = flt(item.net_amount + discount_amount_loss,
item.precision("net_amount"))
item.net_amount = flt(item.net_amount + discount_amount_loss, item.precision("net_amount"))
item.net_rate = flt(item.net_amount / item.qty, item.precision("net_rate")) if item.qty else 0
@@ -553,42 +642,52 @@ class calculate_taxes_and_totals(object):
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)
return flt(self.doc.grand_total - sum(actual_taxes_dict.values()),
self.doc.precision("grand_total"))
return flt(
self.doc.grand_total - sum(actual_taxes_dict.values()), self.doc.precision("grand_total")
)
def calculate_total_advance(self):
if self.doc.docstatus < 2:
total_allocated_amount = sum(flt(adv.allocated_amount, adv.precision("allocated_amount"))
for adv in self.doc.get("advances"))
total_allocated_amount = sum(
flt(adv.allocated_amount, adv.precision("allocated_amount"))
for adv in self.doc.get("advances")
)
self.doc.total_advance = flt(total_allocated_amount, self.doc.precision("total_advance"))
grand_total = self.doc.rounded_total or self.doc.grand_total
if self.doc.party_account_currency == self.doc.currency:
invoice_total = flt(grand_total - flt(self.doc.write_off_amount),
self.doc.precision("grand_total"))
invoice_total = flt(
grand_total - flt(self.doc.write_off_amount), self.doc.precision("grand_total")
)
else:
base_write_off_amount = flt(flt(self.doc.write_off_amount) * self.doc.conversion_rate,
self.doc.precision("base_write_off_amount"))
invoice_total = flt(grand_total * self.doc.conversion_rate,
self.doc.precision("grand_total")) - base_write_off_amount
base_write_off_amount = flt(
flt(self.doc.write_off_amount) * self.doc.conversion_rate,
self.doc.precision("base_write_off_amount"),
)
invoice_total = (
flt(grand_total * self.doc.conversion_rate, self.doc.precision("grand_total"))
- base_write_off_amount
)
if invoice_total > 0 and self.doc.total_advance > invoice_total:
frappe.throw(_("Advance amount cannot be greater than {0} {1}")
.format(self.doc.party_account_currency, invoice_total))
frappe.throw(
_("Advance amount cannot be greater than {0} {1}").format(
self.doc.party_account_currency, invoice_total
)
)
if self.doc.docstatus == 0:
self.calculate_outstanding_amount()
def is_internal_invoice(self):
"""
Checks if its an internal transfer invoice
and decides if to calculate any out standing amount or not
Checks if its an internal transfer invoice
and decides if to calculate any out standing amount or not
"""
if self.doc.doctype in ('Sales Invoice', 'Purchase Invoice') and self.doc.is_internal_transfer():
if self.doc.doctype in ("Sales Invoice", "Purchase Invoice") and self.doc.is_internal_transfer():
return True
return False
@@ -600,43 +699,62 @@ class calculate_taxes_and_totals(object):
if self.doc.doctype == "Sales Invoice":
self.calculate_paid_amount()
if self.doc.is_return and self.doc.return_against and not self.doc.get('is_pos') or \
self.is_internal_invoice(): return
if (
self.doc.is_return
and self.doc.return_against
and not self.doc.get("is_pos")
or self.is_internal_invoice()
):
return
self.doc.round_floats_in(self.doc, ["grand_total", "total_advance", "write_off_amount"])
self._set_in_company_currency(self.doc, ['write_off_amount'])
self._set_in_company_currency(self.doc, ["write_off_amount"])
if self.doc.doctype in ["Sales Invoice", "Purchase Invoice"]:
grand_total = self.doc.rounded_total or self.doc.grand_total
base_grand_total = self.doc.base_rounded_total or self.doc.base_grand_total
if self.doc.party_account_currency == self.doc.currency:
total_amount_to_pay = flt(grand_total - self.doc.total_advance
- flt(self.doc.write_off_amount), self.doc.precision("grand_total"))
total_amount_to_pay = flt(
grand_total - self.doc.total_advance - flt(self.doc.write_off_amount),
self.doc.precision("grand_total"),
)
else:
total_amount_to_pay = flt(flt(base_grand_total, self.doc.precision("base_grand_total")) - self.doc.total_advance
- flt(self.doc.base_write_off_amount), self.doc.precision("base_grand_total"))
total_amount_to_pay = flt(
flt(base_grand_total, self.doc.precision("base_grand_total"))
- self.doc.total_advance
- flt(self.doc.base_write_off_amount),
self.doc.precision("base_grand_total"),
)
self.doc.round_floats_in(self.doc, ["paid_amount"])
change_amount = 0
if self.doc.doctype == "Sales Invoice" and not self.doc.get('is_return'):
if self.doc.doctype == "Sales Invoice" and not self.doc.get("is_return"):
self.calculate_write_off_amount()
self.calculate_change_amount()
change_amount = self.doc.change_amount \
if self.doc.party_account_currency == self.doc.currency else self.doc.base_change_amount
change_amount = (
self.doc.change_amount
if self.doc.party_account_currency == self.doc.currency
else self.doc.base_change_amount
)
paid_amount = self.doc.paid_amount \
if self.doc.party_account_currency == self.doc.currency else self.doc.base_paid_amount
paid_amount = (
self.doc.paid_amount
if self.doc.party_account_currency == self.doc.currency
else self.doc.base_paid_amount
)
self.doc.outstanding_amount = flt(total_amount_to_pay - flt(paid_amount) + flt(change_amount),
self.doc.precision("outstanding_amount"))
self.doc.outstanding_amount = flt(
total_amount_to_pay - flt(paid_amount) + flt(change_amount),
self.doc.precision("outstanding_amount"),
)
if (
self.doc.doctype == 'Sales Invoice'
and self.doc.get('is_pos')
and self.doc.get('is_return')
and not self.doc.get('is_consolidated')
self.doc.doctype == "Sales Invoice"
and self.doc.get("is_pos")
and self.doc.get("is_return")
and not self.doc.get("is_consolidated")
):
self.set_total_amount_to_default_mop(total_amount_to_pay)
self.calculate_paid_amount()
@@ -646,17 +764,17 @@ class calculate_taxes_and_totals(object):
paid_amount = base_paid_amount = 0.0
if self.doc.is_pos:
for payment in self.doc.get('payments'):
for payment in self.doc.get("payments"):
payment.amount = flt(payment.amount)
payment.base_amount = payment.amount * flt(self.doc.conversion_rate)
paid_amount += payment.amount
base_paid_amount += payment.base_amount
elif not self.doc.is_return:
self.doc.set('payments', [])
self.doc.set("payments", [])
if self.doc.redeem_loyalty_points and self.doc.loyalty_amount:
base_paid_amount += self.doc.loyalty_amount
paid_amount += (self.doc.loyalty_amount / flt(self.doc.conversion_rate))
paid_amount += self.doc.loyalty_amount / flt(self.doc.conversion_rate)
self.doc.paid_amount = flt(paid_amount, self.doc.precision("paid_amount"))
self.doc.base_paid_amount = flt(base_paid_amount, self.doc.precision("base_paid_amount"))
@@ -667,22 +785,33 @@ class calculate_taxes_and_totals(object):
grand_total = self.doc.rounded_total or self.doc.grand_total
base_grand_total = self.doc.base_rounded_total or self.doc.base_grand_total
if self.doc.doctype == "Sales Invoice" \
and self.doc.paid_amount > grand_total and not self.doc.is_return \
and any(d.type == "Cash" for d in self.doc.payments):
if (
self.doc.doctype == "Sales Invoice"
and self.doc.paid_amount > grand_total
and not self.doc.is_return
and any(d.type == "Cash" for d in self.doc.payments)
):
self.doc.change_amount = flt(self.doc.paid_amount - grand_total +
self.doc.write_off_amount, self.doc.precision("change_amount"))
self.doc.change_amount = flt(
self.doc.paid_amount - grand_total + self.doc.write_off_amount,
self.doc.precision("change_amount"),
)
self.doc.base_change_amount = flt(self.doc.base_paid_amount - base_grand_total +
self.doc.base_write_off_amount, self.doc.precision("base_change_amount"))
self.doc.base_change_amount = flt(
self.doc.base_paid_amount - base_grand_total + self.doc.base_write_off_amount,
self.doc.precision("base_change_amount"),
)
def calculate_write_off_amount(self):
if flt(self.doc.change_amount) > 0:
self.doc.write_off_amount = flt(self.doc.grand_total - self.doc.paid_amount
+ self.doc.change_amount, self.doc.precision("write_off_amount"))
self.doc.base_write_off_amount = flt(self.doc.write_off_amount * self.doc.conversion_rate,
self.doc.precision("base_write_off_amount"))
self.doc.write_off_amount = flt(
self.doc.grand_total - self.doc.paid_amount + self.doc.change_amount,
self.doc.precision("write_off_amount"),
)
self.doc.base_write_off_amount = flt(
self.doc.write_off_amount * self.doc.conversion_rate,
self.doc.precision("base_write_off_amount"),
)
def calculate_margin(self, item):
rate_with_margin = 0.0
@@ -691,10 +820,15 @@ class calculate_taxes_and_totals(object):
if item.pricing_rules and not self.doc.ignore_pricing_rule:
has_margin = False
for d in get_applied_pricing_rules(item.pricing_rules):
pricing_rule = frappe.get_cached_doc('Pricing Rule', d)
pricing_rule = frappe.get_cached_doc("Pricing Rule", d)
if pricing_rule.margin_rate_or_amount and ((pricing_rule.currency == self.doc.currency and
pricing_rule.margin_type in ['Amount', 'Percentage']) or pricing_rule.margin_type == 'Percentage'):
if pricing_rule.margin_rate_or_amount and (
(
pricing_rule.currency == self.doc.currency
and pricing_rule.margin_type in ["Amount", "Percentage"]
)
or pricing_rule.margin_type == "Percentage"
):
item.margin_type = pricing_rule.margin_type
item.margin_rate_or_amount = pricing_rule.margin_rate_or_amount
has_margin = True
@@ -705,12 +839,17 @@ class calculate_taxes_and_totals(object):
if not item.pricing_rules and flt(item.rate) > flt(item.price_list_rate):
item.margin_type = "Amount"
item.margin_rate_or_amount = flt(item.rate - item.price_list_rate,
item.precision("margin_rate_or_amount"))
item.margin_rate_or_amount = flt(
item.rate - item.price_list_rate, item.precision("margin_rate_or_amount")
)
item.rate_with_margin = item.rate
elif item.margin_type and item.margin_rate_or_amount:
margin_value = item.margin_rate_or_amount if item.margin_type == 'Amount' else flt(item.price_list_rate) * flt(item.margin_rate_or_amount) / 100
margin_value = (
item.margin_rate_or_amount
if item.margin_type == "Amount"
else flt(item.price_list_rate) * flt(item.margin_rate_or_amount) / 100
)
rate_with_margin = flt(item.price_list_rate) + flt(margin_value)
base_rate_with_margin = flt(rate_with_margin) * flt(self.doc.conversion_rate)
@@ -720,16 +859,24 @@ class calculate_taxes_and_totals(object):
self.doc.other_charges_calculation = get_itemised_tax_breakup_html(self.doc)
def set_total_amount_to_default_mop(self, total_amount_to_pay):
default_mode_of_payment = frappe.db.get_value('POS Payment Method',
{'parent': self.doc.pos_profile, 'default': 1}, ['mode_of_payment'], as_dict=1)
default_mode_of_payment = frappe.db.get_value(
"POS Payment Method",
{"parent": self.doc.pos_profile, "default": 1},
["mode_of_payment"],
as_dict=1,
)
if default_mode_of_payment:
self.doc.payments = []
self.doc.append('payments', {
'mode_of_payment': default_mode_of_payment.mode_of_payment,
'amount': total_amount_to_pay,
'default': 1
})
self.doc.append(
"payments",
{
"mode_of_payment": default_mode_of_payment.mode_of_payment,
"amount": total_amount_to_pay,
"default": 1,
},
)
def get_itemised_tax_breakup_html(doc):
if not doc.taxes:
@@ -739,7 +886,7 @@ def get_itemised_tax_breakup_html(doc):
# get headers
tax_accounts = []
for tax in doc.taxes:
if getattr(tax, "category", None) and tax.category=="Valuation":
if getattr(tax, "category", None) and tax.category == "Valuation":
continue
if tax.description not in tax_accounts:
tax_accounts.append(tax.description)
@@ -755,34 +902,40 @@ def get_itemised_tax_breakup_html(doc):
frappe.flags.company = None
return frappe.render_template(
"templates/includes/itemised_tax_breakup.html", dict(
"templates/includes/itemised_tax_breakup.html",
dict(
headers=headers,
itemised_tax=itemised_tax,
itemised_taxable_amount=itemised_taxable_amount,
tax_accounts=tax_accounts,
doc=doc
)
doc=doc,
),
)
@frappe.whitelist()
def get_round_off_applicable_accounts(company, account_list):
account_list = get_regional_round_off_accounts(company, account_list)
return account_list
@erpnext.allow_regional
def get_regional_round_off_accounts(company, account_list):
pass
@erpnext.allow_regional
def update_itemised_tax_data(doc):
#Don't delete this method, used for localization
# Don't delete this method, used for localization
pass
@erpnext.allow_regional
def get_itemised_tax_breakup_header(item_doctype, tax_accounts):
return [_("Item"), _("Taxable Amount")] + tax_accounts
@erpnext.allow_regional
def get_itemised_tax_breakup_data(doc):
itemised_tax = get_itemised_tax(doc.taxes)
@@ -791,10 +944,11 @@ def get_itemised_tax_breakup_data(doc):
return itemised_tax, itemised_taxable_amount
def get_itemised_tax(taxes, with_tax_account=False):
itemised_tax = {}
for tax in taxes:
if getattr(tax, "category", None) and tax.category=="Valuation":
if getattr(tax, "category", None) and tax.category == "Valuation":
continue
item_tax_map = json.loads(tax.item_wise_tax_detail) if tax.item_wise_tax_detail else {}
@@ -811,16 +965,16 @@ def get_itemised_tax(taxes, with_tax_account=False):
else:
tax_rate = flt(tax_data)
itemised_tax[item_code][tax.description] = frappe._dict(dict(
tax_rate = tax_rate,
tax_amount = tax_amount
))
itemised_tax[item_code][tax.description] = frappe._dict(
dict(tax_rate=tax_rate, tax_amount=tax_amount)
)
if with_tax_account:
itemised_tax[item_code][tax.description].tax_account = tax.account_head
return itemised_tax
def get_itemised_taxable_amount(items):
itemised_taxable_amount = frappe._dict()
for item in items:
@@ -830,16 +984,18 @@ def get_itemised_taxable_amount(items):
return itemised_taxable_amount
def get_rounded_tax_amount(itemised_tax, precision):
# Rounding based on tax_amount precision
for taxes in itemised_tax.values():
for tax_account in taxes:
taxes[tax_account]["tax_amount"] = flt(taxes[tax_account]["tax_amount"], precision)
class init_landed_taxes_and_totals(object):
def __init__(self, doc):
self.doc = doc
self.tax_field = 'taxes' if self.doc.doctype == 'Landed Cost Voucher' else 'additional_costs'
self.tax_field = "taxes" if self.doc.doctype == "Landed Cost Voucher" else "additional_costs"
self.set_account_currency()
self.set_exchange_rate()
self.set_amounts_in_company_currency()
@@ -848,7 +1004,7 @@ class init_landed_taxes_and_totals(object):
company_currency = erpnext.get_company_currency(self.doc.company)
for d in self.doc.get(self.tax_field):
if not d.account_currency:
account_currency = frappe.db.get_value('Account', d.expense_account, 'account_currency')
account_currency = frappe.db.get_value("Account", d.expense_account, "account_currency")
d.account_currency = account_currency or company_currency
def set_exchange_rate(self):
@@ -857,8 +1013,12 @@ class init_landed_taxes_and_totals(object):
if d.account_currency == company_currency:
d.exchange_rate = 1
elif not d.exchange_rate:
d.exchange_rate = get_exchange_rate(self.doc.posting_date, account=d.expense_account,
account_currency=d.account_currency, company=self.doc.company)
d.exchange_rate = get_exchange_rate(
self.doc.posting_date,
account=d.expense_account,
account_currency=d.account_currency,
company=self.doc.company,
)
if not d.exchange_rate:
frappe.throw(_("Row {0}: Exchange Rate is mandatory").format(d.idx))