blob: cbcccce5f71958583e83ccd653c0330783978b3a [file] [log] [blame]
Anand Doshi885e0742015-03-03 14:55:30 +05301# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
Nabin Hait3237c752015-02-17 11:11:11 +05302# License: GNU General Public License v3. See license.txt
3
Chillar Anand915b3432021-09-02 16:44:59 +05304
Nabin Hait3237c752015-02-17 11:11:11 +05305import json
Chillar Anand915b3432021-09-02 16:44:59 +05306
7import frappe
Nabin Hait3769d872015-12-18 13:12:02 +05308from frappe import _, scrub
Nabin Haitb962fc12017-07-17 18:02:31 +05309from frappe.utils import cint, flt, round_based_on_smallest_currency_fraction
Chillar Anand915b3432021-09-02 16:44:59 +053010
11import erpnext
Deepesh Gargbfc17e42020-12-25 18:34:39 +053012from erpnext.accounts.doctype.journal_entry.journal_entry import get_exchange_rate
Chillar Anand915b3432021-09-02 16:44:59 +053013from erpnext.accounts.doctype.pricing_rule.utils import get_applied_pricing_rules
14from erpnext.controllers.accounts_controller import (
15 validate_conversion_rate,
16 validate_inclusive_tax,
17 validate_taxes_and_charges,
18)
19from erpnext.stock.get_item_details import _get_item_tax_template
20
Nabin Hait3237c752015-02-17 11:11:11 +053021
Nabin Haitfe81da22015-02-18 12:23:18 +053022class calculate_taxes_and_totals(object):
Nabin Hait3237c752015-02-17 11:11:11 +053023 def __init__(self, doc):
24 self.doc = doc
Deepesh Garg6a5ef262021-02-19 14:30:23 +053025 frappe.flags.round_off_applicable_accounts = []
26 get_round_off_applicable_accounts(self.doc.company, frappe.flags.round_off_applicable_accounts)
Nabin Haitfe81da22015-02-18 12:23:18 +053027 self.calculate()
28
Nabin Hait3237c752015-02-17 11:11:11 +053029 def calculate(self):
Nabin Haitb315acb2019-07-12 14:27:19 +053030 if not len(self.doc.get("items")):
31 return
32
Nabin Hait3237c752015-02-17 11:11:11 +053033 self.discount_amount_applied = False
34 self._calculate()
35
36 if self.doc.meta.get_field("discount_amount"):
Nabin Hait3769d872015-12-18 13:12:02 +053037 self.set_discount_amount()
Nabin Hait3237c752015-02-17 11:11:11 +053038 self.apply_discount_amount()
39
Deepesh Garg3b159662022-08-21 17:51:05 +053040 # Update grand total as per cash and non trade discount
41 if self.doc.apply_discount_on == "Grand Total" and self.doc.get("is_cash_or_non_trade_discount"):
42 self.doc.grand_total -= self.doc.discount_amount
43 self.doc.base_grand_total -= self.doc.base_discount_amount
Deepesh Garg318da162022-08-29 14:18:39 +053044 self.set_rounded_total()
Deepesh Garg3b159662022-08-21 17:51:05 +053045
Deepesh Gargd596e0e2022-03-10 20:56:36 +053046 self.calculate_shipping_charges()
47
Nabin Haitbd00e812015-02-17 12:50:51 +053048 if self.doc.doctype in ["Sales Invoice", "Purchase Invoice"]:
Nabin Hait3237c752015-02-17 11:11:11 +053049 self.calculate_total_advance()
Vishal Dhayaguded42242d2017-11-29 16:09:59 +053050
Nabin Hait852cb642017-07-05 12:58:19 +053051 if self.doc.meta.get_field("other_charges_calculation"):
52 self.set_item_wise_tax_breakup()
Nabin Hait3237c752015-02-17 11:11:11 +053053
54 def _calculate(self):
Faris Ansarieae2dda2018-05-02 12:19:30 +053055 self.validate_conversion_rate()
Nabin Haite7679702015-02-20 14:40:35 +053056 self.calculate_item_values()
Deepesh Gargef0d26c2020-01-06 15:34:15 +053057 self.validate_item_tax_template()
Nabin Haite7679702015-02-20 14:40:35 +053058 self.initialize_taxes()
59 self.determine_exclusive_rate()
60 self.calculate_net_total()
61 self.calculate_taxes()
Nabin Haita1bf43b2015-03-17 10:50:47 +053062 self.manipulate_grand_total_for_inclusive_tax()
Nabin Haite7679702015-02-20 14:40:35 +053063 self.calculate_totals()
64 self._cleanup()
rohitwaghchaurea8fb2db2018-05-26 09:23:02 +053065 self.calculate_total_net_weight()
Nabin Haite7679702015-02-20 14:40:35 +053066
Deepesh Gargef0d26c2020-01-06 15:34:15 +053067 def validate_item_tax_template(self):
Ankush Menat494bd9e2022-03-28 18:52:46 +053068 for item in self.doc.get("items"):
69 if item.item_code and item.get("item_tax_template"):
Deepesh Gargef0d26c2020-01-06 15:34:15 +053070 item_doc = frappe.get_cached_doc("Item", item.item_code)
71 args = {
Ankush Menat494bd9e2022-03-28 18:52:46 +053072 "net_rate": item.net_rate or item.rate,
73 "tax_category": self.doc.get("tax_category"),
74 "posting_date": self.doc.get("posting_date"),
75 "bill_date": self.doc.get("bill_date"),
76 "transaction_date": self.doc.get("transaction_date"),
77 "company": self.doc.get("company"),
Deepesh Gargef0d26c2020-01-06 15:34:15 +053078 }
79
80 item_group = item_doc.item_group
81 item_group_taxes = []
82
83 while item_group:
Ankush Menat494bd9e2022-03-28 18:52:46 +053084 item_group_doc = frappe.get_cached_doc("Item Group", item_group)
Deepesh Gargef0d26c2020-01-06 15:34:15 +053085 item_group_taxes += item_group_doc.taxes or []
86 item_group = item_group_doc.parent_item_group
87
88 item_taxes = item_doc.taxes or []
89
90 if not item_group_taxes and (not item_taxes):
91 # No validation if no taxes in item or item group
92 continue
93
94 taxes = _get_item_tax_template(args, item_taxes + item_group_taxes, for_validate=True)
95
Deepesh Garg18be7672021-06-06 13:25:34 +053096 if taxes:
97 if item.item_tax_template not in taxes:
98 item.item_tax_template = taxes[0]
Ankush Menat494bd9e2022-03-28 18:52:46 +053099 frappe.msgprint(
100 _("Row {0}: Item Tax template updated as per validity and rate applied").format(
101 item.idx, frappe.bold(item.item_code)
102 )
103 )
Deepesh Gargef0d26c2020-01-06 15:34:15 +0530104
Nabin Haite7679702015-02-20 14:40:35 +0530105 def validate_conversion_rate(self):
Nabin Hait3237c752015-02-17 11:11:11 +0530106 # validate conversion rate
Rushabh Mehtacc8b2b22017-03-31 12:44:29 +0530107 company_currency = erpnext.get_company_currency(self.doc.company)
Nabin Hait3237c752015-02-17 11:11:11 +0530108 if not self.doc.currency or self.doc.currency == company_currency:
109 self.doc.currency = company_currency
110 self.doc.conversion_rate = 1.0
111 else:
Ankush Menat494bd9e2022-03-28 18:52:46 +0530112 validate_conversion_rate(
113 self.doc.currency,
114 self.doc.conversion_rate,
115 self.doc.meta.get_label("conversion_rate"),
116 self.doc.company,
117 )
Nabin Hait3237c752015-02-17 11:11:11 +0530118
119 self.doc.conversion_rate = flt(self.doc.conversion_rate)
120
Nabin Hait3237c752015-02-17 11:11:11 +0530121 def calculate_item_values(self):
Ankush Menat494bd9e2022-03-28 18:52:46 +0530122 if self.doc.get("is_consolidated"):
Saqib Ansari0452d7d2022-02-08 11:26:23 +0530123 return
124
Nabin Hait3237c752015-02-17 11:11:11 +0530125 if not self.discount_amount_applied:
126 for item in self.doc.get("items"):
127 self.doc.round_floats_in(item)
128
129 if item.discount_percentage == 100:
130 item.rate = 0.0
Nabin Hait593242f2019-04-05 19:35:02 +0530131 elif item.price_list_rate:
Deepesh Garga83a0a02022-03-25 12:28:55 +0530132 if not item.rate or (item.pricing_rules and item.discount_percentage > 0):
Ankush Menat494bd9e2022-03-28 18:52:46 +0530133 item.rate = flt(
134 item.price_list_rate * (1.0 - (item.discount_percentage / 100.0)), item.precision("rate")
135 )
Deepesh Gargd95f8932022-03-01 23:09:59 +0530136
Deepesh Garga83a0a02022-03-25 12:28:55 +0530137 item.discount_amount = item.price_list_rate * (item.discount_percentage / 100.0)
Deepesh Gargd95f8932022-03-01 23:09:59 +0530138
Deepesh Garg97e102c2022-03-25 12:39:59 +0530139 elif item.discount_amount and item.pricing_rules:
Ankush Menat494bd9e2022-03-28 18:52:46 +0530140 item.rate = item.price_list_rate - item.discount_amount
Nabin Hait3237c752015-02-17 11:11:11 +0530141
Ankush Menat494bd9e2022-03-28 18:52:46 +0530142 if item.doctype in [
143 "Quotation Item",
144 "Sales Order Item",
145 "Delivery Note Item",
146 "Sales Invoice Item",
147 "POS Invoice Item",
148 "Purchase Invoice Item",
149 "Purchase Order Item",
150 "Purchase Receipt Item",
151 ]:
Shreya Shahbe690ef2017-11-14 17:22:41 +0530152 item.rate_with_margin, item.base_rate_with_margin = self.calculate_margin(item)
Nabin Hait64bfdd92019-04-23 13:37:19 +0530153 if flt(item.rate_with_margin) > 0:
Ankush Menat494bd9e2022-03-28 18:52:46 +0530154 item.rate = flt(
155 item.rate_with_margin * (1.0 - (item.discount_percentage / 100.0)), item.precision("rate")
156 )
Nabin Hait10c61372021-04-13 15:46:01 +0530157
Walstan Baptista37b826b2021-04-03 19:48:46 +0530158 if item.discount_amount and not item.discount_percentage:
Nabin Hait10c61372021-04-13 15:46:01 +0530159 item.rate = item.rate_with_margin - item.discount_amount
Walstan Baptista37b826b2021-04-03 19:48:46 +0530160 else:
161 item.discount_amount = item.rate_with_margin - item.rate
Nabin Hait10c61372021-04-13 15:46:01 +0530162
Nabin Hait64bfdd92019-04-23 13:37:19 +0530163 elif flt(item.price_list_rate) > 0:
164 item.discount_amount = item.price_list_rate - item.rate
Rohit Waghchaure8bfe3302019-03-18 14:34:19 +0530165 elif flt(item.price_list_rate) > 0 and not item.discount_amount:
166 item.discount_amount = item.price_list_rate - item.rate
mbauskara52472c2016-03-05 15:10:25 +0530167
Nabin Haite7679702015-02-20 14:40:35 +0530168 item.net_rate = item.rate
Deepesh Gargb65c7612019-07-31 15:58:01 +0530169
deepeshgarg0078bf19ce2019-08-03 13:40:37 +0530170 if not item.qty and self.doc.get("is_return"):
Deepesh Gargb65c7612019-07-31 15:58:01 +0530171 item.amount = flt(-1 * item.rate, item.precision("amount"))
Saqib Ansari04ea42c2021-12-22 13:23:42 +0530172 elif not item.qty and self.doc.get("is_debit_note"):
173 item.amount = flt(item.rate, item.precision("amount"))
Deepesh Gargb65c7612019-07-31 15:58:01 +0530174 else:
Ankush Menat494bd9e2022-03-28 18:52:46 +0530175 item.amount = flt(item.rate * item.qty, item.precision("amount"))
Deepesh Gargb65c7612019-07-31 15:58:01 +0530176
Nabin Haite7679702015-02-20 14:40:35 +0530177 item.net_amount = item.amount
Nabin Hait3237c752015-02-17 11:11:11 +0530178
Ankush Menat494bd9e2022-03-28 18:52:46 +0530179 self._set_in_company_currency(
180 item, ["price_list_rate", "rate", "net_rate", "amount", "net_amount"]
181 )
Nabin Hait3237c752015-02-17 11:11:11 +0530182
Nabin Haite7679702015-02-20 14:40:35 +0530183 item.item_tax_amount = 0.0
184
185 def _set_in_company_currency(self, doc, fields):
Nabin Hait3237c752015-02-17 11:11:11 +0530186 """set values in base currency"""
Nabin Haite7679702015-02-20 14:40:35 +0530187 for f in fields:
Ankush Menat494bd9e2022-03-28 18:52:46 +0530188 val = flt(
189 flt(doc.get(f), doc.precision(f)) * self.doc.conversion_rate, doc.precision("base_" + f)
190 )
Nabin Haite7679702015-02-20 14:40:35 +0530191 doc.set("base_" + f, val)
Nabin Hait3237c752015-02-17 11:11:11 +0530192
193 def initialize_taxes(self):
194 for tax in self.doc.get("taxes"):
Nabin Hait86cd4cc2015-02-28 19:11:51 +0530195 if not self.discount_amount_applied:
196 validate_taxes_and_charges(tax)
197 validate_inclusive_tax(tax, self.doc)
Nabin Hait613d0812015-02-23 11:58:15 +0530198
Ankush Menat494bd9e2022-03-28 18:52:46 +0530199 if not (self.doc.get("is_consolidated") or tax.get("dont_recompute_tax")):
Deepesh Garg5f3d7f52021-04-12 10:56:47 +0530200 tax.item_wise_tax_detail = {}
201
Ankush Menat494bd9e2022-03-28 18:52:46 +0530202 tax_fields = [
203 "total",
204 "tax_amount_after_discount_amount",
205 "tax_amount_for_current_item",
206 "grand_total_for_current_item",
207 "tax_fraction_for_current_item",
208 "grand_total_fraction_for_current_item",
209 ]
Nabin Hait3237c752015-02-17 11:11:11 +0530210
Ankush Menat494bd9e2022-03-28 18:52:46 +0530211 if tax.charge_type != "Actual" and not (
212 self.discount_amount_applied and self.doc.apply_discount_on == "Grand Total"
213 ):
214 tax_fields.append("tax_amount")
Nabin Hait3237c752015-02-17 11:11:11 +0530215
216 for fieldname in tax_fields:
217 tax.set(fieldname, 0.0)
218
Nabin Hait3237c752015-02-17 11:11:11 +0530219 self.doc.round_floats_in(tax)
220
Nabin Hait3237c752015-02-17 11:11:11 +0530221 def determine_exclusive_rate(self):
Ankush Menat8fe5feb2021-11-04 19:48:32 +0530222 if not any(cint(tax.included_in_print_rate) for tax in self.doc.get("taxes")):
Nabin Hait37b047d2015-02-23 16:01:33 +0530223 return
Nabin Hait3237c752015-02-17 11:11:11 +0530224
225 for item in self.doc.get("items"):
226 item_tax_map = self._load_item_tax_rate(item.item_tax_rate)
227 cumulated_tax_fraction = 0
Nabin Hait19ea7212020-08-11 20:34:57 +0530228 total_inclusive_tax_amount_per_qty = 0
Nabin Hait3237c752015-02-17 11:11:11 +0530229 for i, tax in enumerate(self.doc.get("taxes")):
Ankush Menat494bd9e2022-03-28 18:52:46 +0530230 (
231 tax.tax_fraction_for_current_item,
232 inclusive_tax_amount_per_qty,
233 ) = self.get_current_tax_fraction(tax, item_tax_map)
Nabin Hait3237c752015-02-17 11:11:11 +0530234
Ankush Menat494bd9e2022-03-28 18:52:46 +0530235 if i == 0:
Nabin Hait3237c752015-02-17 11:11:11 +0530236 tax.grand_total_fraction_for_current_item = 1 + tax.tax_fraction_for_current_item
237 else:
Ankush Menat494bd9e2022-03-28 18:52:46 +0530238 tax.grand_total_fraction_for_current_item = (
239 self.doc.get("taxes")[i - 1].grand_total_fraction_for_current_item
Nabin Hait3237c752015-02-17 11:11:11 +0530240 + tax.tax_fraction_for_current_item
Ankush Menat494bd9e2022-03-28 18:52:46 +0530241 )
Nabin Hait3237c752015-02-17 11:11:11 +0530242
243 cumulated_tax_fraction += tax.tax_fraction_for_current_item
Nabin Haite2ee4552020-08-12 20:58:03 +0530244 total_inclusive_tax_amount_per_qty += inclusive_tax_amount_per_qty * flt(item.qty)
Nabin Hait3237c752015-02-17 11:11:11 +0530245
Ankush Menat494bd9e2022-03-28 18:52:46 +0530246 if (
247 not self.discount_amount_applied
248 and item.qty
249 and (cumulated_tax_fraction or total_inclusive_tax_amount_per_qty)
250 ):
Nabin Hait19ea7212020-08-11 20:34:57 +0530251 amount = flt(item.amount) - total_inclusive_tax_amount_per_qty
252
253 item.net_amount = flt(amount / (1 + cumulated_tax_fraction))
Nabin Haite7679702015-02-20 14:40:35 +0530254 item.net_rate = flt(item.net_amount / item.qty, item.precision("net_rate"))
Ankush Menat494bd9e2022-03-28 18:52:46 +0530255 item.discount_percentage = flt(item.discount_percentage, item.precision("discount_percentage"))
Nabin Hait3237c752015-02-17 11:11:11 +0530256
Nabin Haite7679702015-02-20 14:40:35 +0530257 self._set_in_company_currency(item, ["net_rate", "net_amount"])
258
Nabin Hait3237c752015-02-17 11:11:11 +0530259 def _load_item_tax_rate(self, item_tax_rate):
260 return json.loads(item_tax_rate) if item_tax_rate else {}
261
262 def get_current_tax_fraction(self, tax, item_tax_map):
263 """
Ankush Menat494bd9e2022-03-28 18:52:46 +0530264 Get tax fraction for calculating tax exclusive amount
265 from tax inclusive amount
Nabin Hait3237c752015-02-17 11:11:11 +0530266 """
267 current_tax_fraction = 0
Nabin Hait19ea7212020-08-11 20:34:57 +0530268 inclusive_tax_amount_per_qty = 0
Nabin Hait3237c752015-02-17 11:11:11 +0530269
270 if cint(tax.included_in_print_rate):
271 tax_rate = self._get_tax_rate(tax, item_tax_map)
272
273 if tax.charge_type == "On Net Total":
274 current_tax_fraction = tax_rate / 100.0
275
276 elif tax.charge_type == "On Previous Row Amount":
Ankush Menat494bd9e2022-03-28 18:52:46 +0530277 current_tax_fraction = (tax_rate / 100.0) * self.doc.get("taxes")[
278 cint(tax.row_id) - 1
279 ].tax_fraction_for_current_item
Nabin Hait3237c752015-02-17 11:11:11 +0530280
281 elif tax.charge_type == "On Previous Row Total":
Ankush Menat494bd9e2022-03-28 18:52:46 +0530282 current_tax_fraction = (tax_rate / 100.0) * self.doc.get("taxes")[
283 cint(tax.row_id) - 1
284 ].grand_total_fraction_for_current_item
marination733fd5f2020-08-26 18:23:12 +0530285
Nabin Hait19ea7212020-08-11 20:34:57 +0530286 elif tax.charge_type == "On Item Quantity":
287 inclusive_tax_amount_per_qty = flt(tax_rate)
Nabin Hait3237c752015-02-17 11:11:11 +0530288
Nabin Hait19ea7212020-08-11 20:34:57 +0530289 if getattr(tax, "add_deduct_tax", None) and tax.add_deduct_tax == "Deduct":
290 current_tax_fraction *= -1.0
291 inclusive_tax_amount_per_qty *= -1.0
292
293 return current_tax_fraction, inclusive_tax_amount_per_qty
Nabin Hait3237c752015-02-17 11:11:11 +0530294
295 def _get_tax_rate(self, tax, item_tax_map):
Achilles Rasquinha87dab142018-03-08 14:21:48 +0530296 if tax.account_head in item_tax_map:
Nabin Hait3237c752015-02-17 11:11:11 +0530297 return flt(item_tax_map.get(tax.account_head), self.doc.precision("rate", tax))
298 else:
299 return tax.rate
300
301 def calculate_net_total(self):
Ankush Menat494bd9e2022-03-28 18:52:46 +0530302 self.doc.total_qty = (
303 self.doc.total
304 ) = self.doc.base_total = self.doc.net_total = self.doc.base_net_total = 0.0
rohitwaghchaure3a595d02018-06-25 10:10:29 +0530305
Nabin Hait3237c752015-02-17 11:11:11 +0530306 for item in self.doc.get("items"):
Nabin Haitf0bc9b62015-02-23 01:40:01 +0530307 self.doc.total += item.amount
Shreya Shahe3290382018-05-28 11:49:08 +0530308 self.doc.total_qty += item.qty
Nabin Haitf0bc9b62015-02-23 01:40:01 +0530309 self.doc.base_total += item.base_amount
Nabin Haite7679702015-02-20 14:40:35 +0530310 self.doc.net_total += item.net_amount
311 self.doc.base_net_total += item.base_net_amount
Nabin Hait3237c752015-02-17 11:11:11 +0530312
Nabin Haitf0bc9b62015-02-23 01:40:01 +0530313 self.doc.round_floats_in(self.doc, ["total", "base_total", "net_total", "base_net_total"])
Nabin Hait3237c752015-02-17 11:11:11 +0530314
Subin Toma8e2c022021-11-16 19:06:49 +0530315 def calculate_shipping_charges(self):
Deepesh Garg714fc082022-04-04 20:05:10 +0530316
317 # Do not apply shipping rule for POS
Deepesh Garg631545a2022-04-06 09:27:40 +0530318 if self.doc.get("is_pos"):
Deepesh Garg714fc082022-04-04 20:05:10 +0530319 return
320
Subin Tomaf1fce02021-11-10 16:49:12 +0530321 if hasattr(self.doc, "shipping_rule") and self.doc.shipping_rule:
Subin Tom18ae03d2021-11-10 15:57:41 +0530322 shipping_rule = frappe.get_doc("Shipping Rule", self.doc.shipping_rule)
323 shipping_rule.apply(self.doc)
324
Deepesh Gargd596e0e2022-03-10 20:56:36 +0530325 self._calculate()
326
Nabin Hait3237c752015-02-17 11:11:11 +0530327 def calculate_taxes(self):
Ankush Menat494bd9e2022-03-28 18:52:46 +0530328 rounding_adjustment_computed = self.doc.get("is_consolidated") and self.doc.get(
329 "rounding_adjustment"
330 )
Saqib Ansari17445c72022-03-07 18:01:07 +0530331 if not rounding_adjustment_computed:
Subin Tom75a76e62021-10-29 16:45:04 +0530332 self.doc.rounding_adjustment = 0
333
Nabin Hait3237c752015-02-17 11:11:11 +0530334 # maintain actual tax rate based on idx
Ankush Menat494bd9e2022-03-28 18:52:46 +0530335 actual_tax_dict = dict(
336 [
337 [tax.idx, flt(tax.tax_amount, tax.precision("tax_amount"))]
338 for tax in self.doc.get("taxes")
339 if tax.charge_type == "Actual"
340 ]
341 )
Nabin Hait3237c752015-02-17 11:11:11 +0530342
343 for n, item in enumerate(self.doc.get("items")):
344 item_tax_map = self._load_item_tax_rate(item.item_tax_rate)
Nabin Hait3237c752015-02-17 11:11:11 +0530345 for i, tax in enumerate(self.doc.get("taxes")):
346 # tax_amount represents the amount of tax for the current step
347 current_tax_amount = self.get_current_tax_amount(item, tax, item_tax_map)
348
349 # Adjust divisional loss to the last item
350 if tax.charge_type == "Actual":
351 actual_tax_dict[tax.idx] -= current_tax_amount
352 if n == len(self.doc.get("items")) - 1:
353 current_tax_amount += actual_tax_dict[tax.idx]
354
Nabin Hait2b019ed2015-02-22 23:03:07 +0530355 # accumulate tax amount into tax.tax_amount
Ankush Menat494bd9e2022-03-28 18:52:46 +0530356 if tax.charge_type != "Actual" and not (
357 self.discount_amount_applied and self.doc.apply_discount_on == "Grand Total"
358 ):
359 tax.tax_amount += current_tax_amount
Nabin Hait2b019ed2015-02-22 23:03:07 +0530360
Nabin Hait3237c752015-02-17 11:11:11 +0530361 # store tax_amount for current item as it will be used for
362 # charge type = 'On Previous Row Amount'
363 tax.tax_amount_for_current_item = current_tax_amount
364
Nabin Hait2b019ed2015-02-22 23:03:07 +0530365 # set tax after discount
Nabin Hait3237c752015-02-17 11:11:11 +0530366 tax.tax_amount_after_discount_amount += current_tax_amount
367
Nabin Haitcd951342017-07-31 18:07:45 +0530368 current_tax_amount = self.get_tax_amount_if_for_valuation_or_deduction(current_tax_amount, tax)
Nabin Hait3237c752015-02-17 11:11:11 +0530369
Nabin Hait3237c752015-02-17 11:11:11 +0530370 # note: grand_total_for_current_item contains the contribution of
371 # item's amount, previously applied tax and the current tax on that item
Ankush Menat494bd9e2022-03-28 18:52:46 +0530372 if i == 0:
Nabin Haitcd951342017-07-31 18:07:45 +0530373 tax.grand_total_for_current_item = flt(item.net_amount + current_tax_amount)
Nabin Hait3237c752015-02-17 11:11:11 +0530374 else:
Ankush Menat494bd9e2022-03-28 18:52:46 +0530375 tax.grand_total_for_current_item = flt(
376 self.doc.get("taxes")[i - 1].grand_total_for_current_item + current_tax_amount
377 )
Nabin Hait3237c752015-02-17 11:11:11 +0530378
379 # set precision in the last item iteration
380 if n == len(self.doc.get("items")) - 1:
381 self.round_off_totals(tax)
Ankush Menat494bd9e2022-03-28 18:52:46 +0530382 self._set_in_company_currency(tax, ["tax_amount", "tax_amount_after_discount_amount"])
Deepesh Gargb6705882021-04-14 11:20:27 +0530383
384 self.round_off_base_values(tax)
Nabin Haitcd951342017-07-31 18:07:45 +0530385 self.set_cumulative_total(i, tax)
386
Deepesh Gargb6705882021-04-14 11:20:27 +0530387 self._set_in_company_currency(tax, ["total"])
Anand Doshiec5ec602015-03-05 19:31:23 +0530388
Nabin Hait3237c752015-02-17 11:11:11 +0530389 # adjust Discount Amount loss in last tax iteration
Ankush Menat494bd9e2022-03-28 18:52:46 +0530390 if (
391 i == (len(self.doc.get("taxes")) - 1)
392 and self.discount_amount_applied
393 and self.doc.discount_amount
394 and self.doc.apply_discount_on == "Grand Total"
395 and not rounding_adjustment_computed
396 ):
397 self.doc.rounding_adjustment = flt(
398 self.doc.grand_total - flt(self.doc.discount_amount) - tax.total,
399 self.doc.precision("rounding_adjustment"),
400 )
Anand Doshiec5ec602015-03-05 19:31:23 +0530401
Nabin Haitcd951342017-07-31 18:07:45 +0530402 def get_tax_amount_if_for_valuation_or_deduction(self, tax_amount, tax):
403 # if just for valuation, do not add the tax amount in total
404 # if tax/charges is for deduction, multiply by -1
405 if getattr(tax, "category", None):
406 tax_amount = 0.0 if (tax.category == "Valuation") else tax_amount
Ankush Menat494bd9e2022-03-28 18:52:46 +0530407 if self.doc.doctype in [
408 "Purchase Order",
409 "Purchase Invoice",
410 "Purchase Receipt",
411 "Supplier Quotation",
412 ]:
Rushabh Mehta30dc9a12017-11-17 14:31:09 +0530413 tax_amount *= -1.0 if (tax.add_deduct_tax == "Deduct") else 1.0
Nabin Haitcd951342017-07-31 18:07:45 +0530414 return tax_amount
Anand Doshiec5ec602015-03-05 19:31:23 +0530415
Nabin Haitcd951342017-07-31 18:07:45 +0530416 def set_cumulative_total(self, row_idx, tax):
417 tax_amount = tax.tax_amount_after_discount_amount
418 tax_amount = self.get_tax_amount_if_for_valuation_or_deduction(tax_amount, tax)
419
420 if row_idx == 0:
421 tax.total = flt(self.doc.net_total + tax_amount, tax.precision("total"))
422 else:
Ankush Menat494bd9e2022-03-28 18:52:46 +0530423 tax.total = flt(self.doc.get("taxes")[row_idx - 1].total + tax_amount, tax.precision("total"))
Nabin Hait3237c752015-02-17 11:11:11 +0530424
425 def get_current_tax_amount(self, item, tax, item_tax_map):
426 tax_rate = self._get_tax_rate(tax, item_tax_map)
427 current_tax_amount = 0.0
428
429 if tax.charge_type == "Actual":
430 # distribute the tax amount proportionally to each item row
Nabin Haite7679702015-02-20 14:40:35 +0530431 actual = flt(tax.tax_amount, tax.precision("tax_amount"))
Ankush Menat494bd9e2022-03-28 18:52:46 +0530432 current_tax_amount = (
433 item.net_amount * actual / self.doc.net_total if self.doc.net_total else 0.0
434 )
Nabin Haite7679702015-02-20 14:40:35 +0530435
Nabin Hait3237c752015-02-17 11:11:11 +0530436 elif tax.charge_type == "On Net Total":
Nabin Haite7679702015-02-20 14:40:35 +0530437 current_tax_amount = (tax_rate / 100.0) * item.net_amount
Nabin Hait3237c752015-02-17 11:11:11 +0530438 elif tax.charge_type == "On Previous Row Amount":
Ankush Menat494bd9e2022-03-28 18:52:46 +0530439 current_tax_amount = (tax_rate / 100.0) * self.doc.get("taxes")[
440 cint(tax.row_id) - 1
441 ].tax_amount_for_current_item
Nabin Hait3237c752015-02-17 11:11:11 +0530442 elif tax.charge_type == "On Previous Row Total":
Ankush Menat494bd9e2022-03-28 18:52:46 +0530443 current_tax_amount = (tax_rate / 100.0) * self.doc.get("taxes")[
444 cint(tax.row_id) - 1
445 ].grand_total_for_current_item
Himanshu Mishra35b26272018-11-13 11:13:04 +0530446 elif tax.charge_type == "On Item Quantity":
Nabin Hait19ea7212020-08-11 20:34:57 +0530447 current_tax_amount = tax_rate * item.qty
Nabin Hait3237c752015-02-17 11:11:11 +0530448
Ankush Menatdfdd1c62021-07-23 15:50:37 +0530449 if not (self.doc.get("is_consolidated") or tax.get("dont_recompute_tax")):
Deepesh Garg5f3d7f52021-04-12 10:56:47 +0530450 self.set_item_wise_tax(item, tax, tax_rate, current_tax_amount)
Nabin Hait3237c752015-02-17 11:11:11 +0530451
452 return current_tax_amount
453
Nabin Haite7679702015-02-20 14:40:35 +0530454 def set_item_wise_tax(self, item, tax, tax_rate, current_tax_amount):
455 # store tax breakup for each item
456 key = item.item_code or item.item_name
Ankush Menat494bd9e2022-03-28 18:52:46 +0530457 item_wise_tax_amount = current_tax_amount * self.doc.conversion_rate
Nabin Haite7679702015-02-20 14:40:35 +0530458 if tax.item_wise_tax_detail.get(key):
459 item_wise_tax_amount += tax.item_wise_tax_detail[key][1]
460
Ankush Menat494bd9e2022-03-28 18:52:46 +0530461 tax.item_wise_tax_detail[key] = [tax_rate, flt(item_wise_tax_amount)]
Nabin Haite7679702015-02-20 14:40:35 +0530462
Nabin Hait3237c752015-02-17 11:11:11 +0530463 def round_off_totals(self, tax):
Deepesh Gargb6705882021-04-14 11:20:27 +0530464 if tax.account_head in frappe.flags.round_off_applicable_accounts:
465 tax.tax_amount = round(tax.tax_amount, 0)
466 tax.tax_amount_after_discount_amount = round(tax.tax_amount_after_discount_amount, 0)
467
Nabin Haite7679702015-02-20 14:40:35 +0530468 tax.tax_amount = flt(tax.tax_amount, tax.precision("tax_amount"))
Ankush Menat494bd9e2022-03-28 18:52:46 +0530469 tax.tax_amount_after_discount_amount = flt(
470 tax.tax_amount_after_discount_amount, tax.precision("tax_amount")
471 )
Nabin Haitce245122015-02-22 20:14:49 +0530472
Deepesh Gargb6705882021-04-14 11:20:27 +0530473 def round_off_base_values(self, tax):
474 # Round off to nearest integer based on regional settings
475 if tax.account_head in frappe.flags.round_off_applicable_accounts:
476 tax.base_tax_amount = round(tax.base_tax_amount, 0)
477 tax.base_tax_amount_after_discount_amount = round(tax.base_tax_amount_after_discount_amount, 0)
478
Nabin Haita1bf43b2015-03-17 10:50:47 +0530479 def manipulate_grand_total_for_inclusive_tax(self):
480 # if fully inclusive taxes and diff
Ankush Menat98917802021-06-11 18:40:22 +0530481 if self.doc.get("taxes") and any(cint(t.included_in_print_rate) for t in self.doc.get("taxes")):
Nabin Haita1bf43b2015-03-17 10:50:47 +0530482 last_tax = self.doc.get("taxes")[-1]
Ankush Menat494bd9e2022-03-28 18:52:46 +0530483 non_inclusive_tax_amount = sum(
484 flt(d.tax_amount_after_discount_amount)
485 for d in self.doc.get("taxes")
486 if not d.included_in_print_rate
487 )
Nabin Haitf32fc232019-12-25 13:59:24 +0530488
Ankush Menat494bd9e2022-03-28 18:52:46 +0530489 diff = (
490 self.doc.total + non_inclusive_tax_amount - flt(last_tax.total, last_tax.precision("total"))
491 )
Nabin Haitf32fc232019-12-25 13:59:24 +0530492
493 # If discount amount applied, deduct the discount amount
494 # because self.doc.total is always without discount, but last_tax.total is after discount
495 if self.discount_amount_applied and self.doc.discount_amount:
496 diff -= flt(self.doc.discount_amount)
497
498 diff = flt(diff, self.doc.precision("rounding_adjustment"))
499
Ankush Menat494bd9e2022-03-28 18:52:46 +0530500 if diff and abs(diff) <= (5.0 / 10 ** last_tax.precision("tax_amount")):
Nabin Haitf32fc232019-12-25 13:59:24 +0530501 self.doc.rounding_adjustment = diff
Nabin Hait3237c752015-02-17 11:11:11 +0530502
503 def calculate_totals(self):
Subin Tom75a76e62021-10-29 16:45:04 +0530504 if self.doc.get("taxes"):
505 self.doc.grand_total = flt(self.doc.get("taxes")[-1].total) + flt(self.doc.rounding_adjustment)
506 else:
507 self.doc.grand_total = flt(self.doc.net_total)
Nabin Hait3237c752015-02-17 11:11:11 +0530508
Subin Tom75a76e62021-10-29 16:45:04 +0530509 if self.doc.get("taxes"):
Ankush Menat494bd9e2022-03-28 18:52:46 +0530510 self.doc.total_taxes_and_charges = flt(
511 self.doc.grand_total - self.doc.net_total - flt(self.doc.rounding_adjustment),
512 self.doc.precision("total_taxes_and_charges"),
513 )
Subin Tom75a76e62021-10-29 16:45:04 +0530514 else:
515 self.doc.total_taxes_and_charges = 0.0
Anand Doshiec5ec602015-03-05 19:31:23 +0530516
Nabin Hait2e4de832017-09-19 14:53:16 +0530517 self._set_in_company_currency(self.doc, ["total_taxes_and_charges", "rounding_adjustment"])
Anand Doshiec5ec602015-03-05 19:31:23 +0530518
Ankush Menat494bd9e2022-03-28 18:52:46 +0530519 if self.doc.doctype in [
520 "Quotation",
521 "Sales Order",
522 "Delivery Note",
523 "Sales Invoice",
524 "POS Invoice",
525 ]:
526 self.doc.base_grand_total = (
527 flt(self.doc.grand_total * self.doc.conversion_rate, self.doc.precision("base_grand_total"))
528 if self.doc.total_taxes_and_charges
529 else self.doc.base_net_total
530 )
Nabin Hait3237c752015-02-17 11:11:11 +0530531 else:
Anand Doshiec5ec602015-03-05 19:31:23 +0530532 self.doc.taxes_and_charges_added = self.doc.taxes_and_charges_deducted = 0.0
Nabin Hait3237c752015-02-17 11:11:11 +0530533 for tax in self.doc.get("taxes"):
534 if tax.category in ["Valuation and Total", "Total"]:
535 if tax.add_deduct_tax == "Add":
Nabin Haitdb53a782015-07-31 16:53:13 +0530536 self.doc.taxes_and_charges_added += flt(tax.tax_amount_after_discount_amount)
Nabin Hait3237c752015-02-17 11:11:11 +0530537 else:
Nabin Haitdb53a782015-07-31 16:53:13 +0530538 self.doc.taxes_and_charges_deducted += flt(tax.tax_amount_after_discount_amount)
Nabin Hait3237c752015-02-17 11:11:11 +0530539
Nabin Haite7679702015-02-20 14:40:35 +0530540 self.doc.round_floats_in(self.doc, ["taxes_and_charges_added", "taxes_and_charges_deducted"])
Nabin Hait3237c752015-02-17 11:11:11 +0530541
Ankush Menat494bd9e2022-03-28 18:52:46 +0530542 self.doc.base_grand_total = (
543 flt(self.doc.grand_total * self.doc.conversion_rate)
544 if (self.doc.taxes_and_charges_added or self.doc.taxes_and_charges_deducted)
Nabin Haite7679702015-02-20 14:40:35 +0530545 else self.doc.base_net_total
Ankush Menat494bd9e2022-03-28 18:52:46 +0530546 )
Nabin Hait3237c752015-02-17 11:11:11 +0530547
Ankush Menat494bd9e2022-03-28 18:52:46 +0530548 self._set_in_company_currency(
549 self.doc, ["taxes_and_charges_added", "taxes_and_charges_deducted"]
550 )
Nabin Hait3237c752015-02-17 11:11:11 +0530551
Nabin Haite7679702015-02-20 14:40:35 +0530552 self.doc.round_floats_in(self.doc, ["grand_total", "base_grand_total"])
Nabin Hait3237c752015-02-17 11:11:11 +0530553
Nabin Hait2e4de832017-09-19 14:53:16 +0530554 self.set_rounded_total()
555
rohitwaghchaurea8fb2db2018-05-26 09:23:02 +0530556 def calculate_total_net_weight(self):
Ankush Menat494bd9e2022-03-28 18:52:46 +0530557 if self.doc.meta.get_field("total_net_weight"):
rohitwaghchaurea8fb2db2018-05-26 09:23:02 +0530558 self.doc.total_net_weight = 0.0
559 for d in self.doc.items:
560 if d.total_weight:
561 self.doc.total_net_weight += d.total_weight
562
Nabin Hait2e4de832017-09-19 14:53:16 +0530563 def set_rounded_total(self):
Ankush Menat494bd9e2022-03-28 18:52:46 +0530564 if self.doc.get("is_consolidated") and self.doc.get("rounding_adjustment"):
Saqib Ansari17445c72022-03-07 18:01:07 +0530565 return
Nabin Hait877e1bb2017-11-17 12:27:43 +0530566
Saqib Ansari17445c72022-03-07 18:01:07 +0530567 if self.doc.meta.get_field("rounded_total"):
568 if self.doc.is_rounded_total_disabled():
569 self.doc.rounded_total = self.doc.base_rounded_total = 0
570 return
Nabin Hait2e4de832017-09-19 14:53:16 +0530571
Ankush Menat494bd9e2022-03-28 18:52:46 +0530572 self.doc.rounded_total = round_based_on_smallest_currency_fraction(
573 self.doc.grand_total, self.doc.currency, self.doc.precision("rounded_total")
574 )
Nabin Hait877e1bb2017-11-17 12:27:43 +0530575
Ankush Menat494bd9e2022-03-28 18:52:46 +0530576 # if print_in_rate is set, we would have already calculated rounding adjustment
577 self.doc.rounding_adjustment += flt(
578 self.doc.rounded_total - self.doc.grand_total, self.doc.precision("rounding_adjustment")
579 )
Saqib Ansari17445c72022-03-07 18:01:07 +0530580
581 self._set_in_company_currency(self.doc, ["rounding_adjustment", "rounded_total"])
Nabin Hait877e1bb2017-11-17 12:27:43 +0530582
Nabin Hait3237c752015-02-17 11:11:11 +0530583 def _cleanup(self):
Ankush Menat494bd9e2022-03-28 18:52:46 +0530584 if not self.doc.get("is_consolidated"):
Deepesh Garg5f3d7f52021-04-12 10:56:47 +0530585 for tax in self.doc.get("taxes"):
Ankush Menatdfdd1c62021-07-23 15:50:37 +0530586 if not tax.get("dont_recompute_tax"):
Ankush Menat494bd9e2022-03-28 18:52:46 +0530587 tax.item_wise_tax_detail = json.dumps(tax.item_wise_tax_detail, separators=(",", ":"))
Anand Doshi15f7b1e2016-04-04 15:03:28 +0530588
Nabin Hait3769d872015-12-18 13:12:02 +0530589 def set_discount_amount(self):
Nabin Haite0405102016-10-13 12:14:32 +0530590 if self.doc.additional_discount_percentage:
Ankush Menat494bd9e2022-03-28 18:52:46 +0530591 self.doc.discount_amount = flt(
592 flt(self.doc.get(scrub(self.doc.apply_discount_on)))
593 * self.doc.additional_discount_percentage
594 / 100,
595 self.doc.precision("discount_amount"),
596 )
Nabin Hait3237c752015-02-17 11:11:11 +0530597
598 def apply_discount_amount(self):
599 if self.doc.discount_amount:
Nabin Hait37b047d2015-02-23 16:01:33 +0530600 if not self.doc.apply_discount_on:
601 frappe.throw(_("Please select Apply Discount On"))
602
Deepesh Garg3b159662022-08-21 17:51:05 +0530603 self.doc.base_discount_amount = flt(
604 self.doc.discount_amount * self.doc.conversion_rate, self.doc.precision("base_discount_amount")
605 )
606
Deepesh Garge54ec4b2022-07-03 11:02:21 +0530607 if self.doc.apply_discount_on == "Grand Total" and self.doc.get(
608 "is_cash_or_non_trade_discount"
609 ):
Deepesh Garg169ff5a2022-06-19 21:18:12 +0530610 self.discount_amount_applied = True
611 return
612
Nabin Haite7679702015-02-20 14:40:35 +0530613 total_for_discount_amount = self.get_total_for_discount_amount()
Nabin Hait25bd84d2015-03-04 15:06:56 +0530614 taxes = self.doc.get("taxes")
615 net_total = 0
Nabin Hait3237c752015-02-17 11:11:11 +0530616
Nabin Haite7679702015-02-20 14:40:35 +0530617 if total_for_discount_amount:
Nabin Hait3237c752015-02-17 11:11:11 +0530618 # calculate item amount after Discount Amount
Nabin Hait25bd84d2015-03-04 15:06:56 +0530619 for i, item in enumerate(self.doc.get("items")):
Ankush Menat494bd9e2022-03-28 18:52:46 +0530620 distributed_amount = (
621 flt(self.doc.discount_amount) * item.net_amount / total_for_discount_amount
622 )
Anand Doshiec5ec602015-03-05 19:31:23 +0530623
Nabin Haite7679702015-02-20 14:40:35 +0530624 item.net_amount = flt(item.net_amount - distributed_amount, item.precision("net_amount"))
Nabin Hait25bd84d2015-03-04 15:06:56 +0530625 net_total += item.net_amount
Anand Doshiec5ec602015-03-05 19:31:23 +0530626
Nabin Hait25bd84d2015-03-04 15:06:56 +0530627 # discount amount rounding loss adjustment if no taxes
Ankush Menat494bd9e2022-03-28 18:52:46 +0530628 if (
629 self.doc.apply_discount_on == "Net Total"
630 or not taxes
631 or total_for_discount_amount == self.doc.net_total
632 ) and i == len(self.doc.get("items")) - 1:
633 discount_amount_loss = flt(
634 self.doc.net_total - net_total - self.doc.discount_amount, self.doc.precision("net_total")
635 )
Rushabh Mehtac6bd7ad2016-12-21 17:30:29 +0530636
Ankush Menat494bd9e2022-03-28 18:52:46 +0530637 item.net_amount = flt(item.net_amount + discount_amount_loss, item.precision("net_amount"))
Anand Doshiec5ec602015-03-05 19:31:23 +0530638
Nabin Hait51e980d2015-10-10 18:10:05 +0530639 item.net_rate = flt(item.net_amount / item.qty, item.precision("net_rate")) if item.qty else 0
Anand Doshiec5ec602015-03-05 19:31:23 +0530640
Nabin Haite7679702015-02-20 14:40:35 +0530641 self._set_in_company_currency(item, ["net_rate", "net_amount"])
Nabin Hait3237c752015-02-17 11:11:11 +0530642
643 self.discount_amount_applied = True
644 self._calculate()
645 else:
646 self.doc.base_discount_amount = 0
647
Nabin Haite7679702015-02-20 14:40:35 +0530648 def get_total_for_discount_amount(self):
Nabin Haitde9c8a92015-02-23 01:06:00 +0530649 if self.doc.apply_discount_on == "Net Total":
650 return self.doc.net_total
Nabin Haite7679702015-02-20 14:40:35 +0530651 else:
652 actual_taxes_dict = {}
Nabin Hait3237c752015-02-17 11:11:11 +0530653
Nabin Haite7679702015-02-20 14:40:35 +0530654 for tax in self.doc.get("taxes"):
Nabin Hait19ea7212020-08-11 20:34:57 +0530655 if tax.charge_type in ["Actual", "On Item Quantity"]:
Nabin Haitaf9bdfe2017-12-12 18:50:05 +0530656 tax_amount = self.get_tax_amount_if_for_valuation_or_deduction(tax.tax_amount, tax)
657 actual_taxes_dict.setdefault(tax.idx, tax_amount)
Nabin Haite7679702015-02-20 14:40:35 +0530658 elif tax.row_id in actual_taxes_dict:
659 actual_tax_amount = flt(actual_taxes_dict.get(tax.row_id, 0)) * flt(tax.rate) / 100
660 actual_taxes_dict.setdefault(tax.idx, actual_tax_amount)
Nabin Hait3237c752015-02-17 11:11:11 +0530661
Ankush Menat494bd9e2022-03-28 18:52:46 +0530662 return flt(
663 self.doc.grand_total - sum(actual_taxes_dict.values()), self.doc.precision("grand_total")
664 )
Nabin Hait3237c752015-02-17 11:11:11 +0530665
Nabin Hait7b19b9e2015-02-24 09:42:24 +0530666 def calculate_total_advance(self):
667 if self.doc.docstatus < 2:
Ankush Menat494bd9e2022-03-28 18:52:46 +0530668 total_allocated_amount = sum(
669 flt(adv.allocated_amount, adv.precision("allocated_amount"))
670 for adv in self.doc.get("advances")
671 )
Nabin Hait3237c752015-02-17 11:11:11 +0530672
Nabin Haite7679702015-02-20 14:40:35 +0530673 self.doc.total_advance = flt(total_allocated_amount, self.doc.precision("total_advance"))
Anand Doshi15f7b1e2016-04-04 15:03:28 +0530674
Faris Ansari6041f5c2018-02-08 13:33:52 +0530675 grand_total = self.doc.rounded_total or self.doc.grand_total
676
Nabin Hait289ffb72016-02-08 11:06:55 +0530677 if self.doc.party_account_currency == self.doc.currency:
Ankush Menat494bd9e2022-03-28 18:52:46 +0530678 invoice_total = flt(
679 grand_total - flt(self.doc.write_off_amount), self.doc.precision("grand_total")
680 )
Nabin Hait8d8cba72017-04-03 17:26:22 +0530681 else:
Ankush Menat494bd9e2022-03-28 18:52:46 +0530682 base_write_off_amount = flt(
683 flt(self.doc.write_off_amount) * self.doc.conversion_rate,
684 self.doc.precision("base_write_off_amount"),
685 )
686 invoice_total = (
687 flt(grand_total * self.doc.conversion_rate, self.doc.precision("grand_total"))
688 - base_write_off_amount
689 )
Vishal Dhayaguded42242d2017-11-29 16:09:59 +0530690
Nabin Haitadc09232016-02-09 10:31:11 +0530691 if invoice_total > 0 and self.doc.total_advance > invoice_total:
Ankush Menat494bd9e2022-03-28 18:52:46 +0530692 frappe.throw(
693 _("Advance amount cannot be greater than {0} {1}").format(
694 self.doc.party_account_currency, invoice_total
695 )
696 )
Nabin Hait3237c752015-02-17 11:11:11 +0530697
Rushabh Mehta8bb6e532015-02-18 20:22:59 +0530698 if self.doc.docstatus == 0:
Ankush Menat3821a972022-03-28 20:14:19 +0530699 if self.doc.get("write_off_outstanding_amount_automatically"):
Deepesh Garg19b1b1f2022-03-25 18:02:14 +0530700 self.doc.write_off_amount = 0
701
Nabin Hait3237c752015-02-17 11:11:11 +0530702 self.calculate_outstanding_amount()
Deepesh Gargf57f4af2022-03-24 12:31:37 +0530703 self.calculate_write_off_amount()
Nabin Hait3237c752015-02-17 11:11:11 +0530704
Deepesh Gargf17ea2c2020-12-11 21:30:39 +0530705 def is_internal_invoice(self):
706 """
Ankush Menat494bd9e2022-03-28 18:52:46 +0530707 Checks if its an internal transfer invoice
708 and decides if to calculate any out standing amount or not
Deepesh Gargf17ea2c2020-12-11 21:30:39 +0530709 """
710
Ankush Menat494bd9e2022-03-28 18:52:46 +0530711 if self.doc.doctype in ("Sales Invoice", "Purchase Invoice") and self.doc.is_internal_transfer():
Deepesh Gargf17ea2c2020-12-11 21:30:39 +0530712 return True
713
714 return False
715
Nabin Hait3237c752015-02-17 11:11:11 +0530716 def calculate_outstanding_amount(self):
717 # NOTE:
718 # write_off_amount is only for POS Invoice
719 # total_advance is only for non POS Invoice
Rohit Waghchaureefb5bf22016-08-25 02:09:53 +0530720 if self.doc.doctype == "Sales Invoice":
721 self.calculate_paid_amount()
722
Ankush Menat494bd9e2022-03-28 18:52:46 +0530723 if (
724 self.doc.is_return
725 and self.doc.return_against
726 and not self.doc.get("is_pos")
727 or self.is_internal_invoice()
728 ):
729 return
Anand Doshi15f7b1e2016-04-04 15:03:28 +0530730
Nabin Hait4ffd7f32015-08-27 12:28:36 +0530731 self.doc.round_floats_in(self.doc, ["grand_total", "total_advance", "write_off_amount"])
Ankush Menat494bd9e2022-03-28 18:52:46 +0530732 self._set_in_company_currency(self.doc, ["write_off_amount"])
Anand Doshi15f7b1e2016-04-04 15:03:28 +0530733
Nabin Hait877e1bb2017-11-17 12:27:43 +0530734 if self.doc.doctype in ["Sales Invoice", "Purchase Invoice"]:
735 grand_total = self.doc.rounded_total or self.doc.grand_total
Deepesh Garg9d3a5c32022-01-06 18:58:49 +0530736 base_grand_total = self.doc.base_rounded_total or self.doc.base_grand_total
737
Nabin Hait877e1bb2017-11-17 12:27:43 +0530738 if self.doc.party_account_currency == self.doc.currency:
Ankush Menat494bd9e2022-03-28 18:52:46 +0530739 total_amount_to_pay = flt(
740 grand_total - self.doc.total_advance - flt(self.doc.write_off_amount),
741 self.doc.precision("grand_total"),
742 )
Nabin Hait877e1bb2017-11-17 12:27:43 +0530743 else:
Ankush Menat494bd9e2022-03-28 18:52:46 +0530744 total_amount_to_pay = flt(
745 flt(base_grand_total, self.doc.precision("base_grand_total"))
746 - self.doc.total_advance
747 - flt(self.doc.base_write_off_amount),
748 self.doc.precision("base_grand_total"),
749 )
Anand Doshi15f7b1e2016-04-04 15:03:28 +0530750
Nabin Hait4ffd7f32015-08-27 12:28:36 +0530751 self.doc.round_floats_in(self.doc, ["paid_amount"])
Nabin Hait877e1bb2017-11-17 12:27:43 +0530752 change_amount = 0
753
Ankush Menat494bd9e2022-03-28 18:52:46 +0530754 if self.doc.doctype == "Sales Invoice" and not self.doc.get("is_return"):
Nabin Hait877e1bb2017-11-17 12:27:43 +0530755 self.calculate_change_amount()
Ankush Menat494bd9e2022-03-28 18:52:46 +0530756 change_amount = (
757 self.doc.change_amount
758 if self.doc.party_account_currency == self.doc.currency
759 else self.doc.base_change_amount
760 )
Nabin Hait877e1bb2017-11-17 12:27:43 +0530761
Ankush Menat494bd9e2022-03-28 18:52:46 +0530762 paid_amount = (
763 self.doc.paid_amount
764 if self.doc.party_account_currency == self.doc.currency
765 else self.doc.base_paid_amount
766 )
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530767
Ankush Menat494bd9e2022-03-28 18:52:46 +0530768 self.doc.outstanding_amount = flt(
769 total_amount_to_pay - flt(paid_amount) + flt(change_amount),
770 self.doc.precision("outstanding_amount"),
771 )
Rushabh Mehtac6bd7ad2016-12-21 17:30:29 +0530772
Saqib Ansarie8a7a542022-03-12 19:20:48 +0530773 if (
Ankush Menat494bd9e2022-03-28 18:52:46 +0530774 self.doc.doctype == "Sales Invoice"
775 and self.doc.get("is_pos")
Saqib Ansari33762db2022-08-10 14:17:28 +0530776 and self.doc.get("pos_profile")
777 and self.doc.get("is_consolidated")
778 ):
779 write_off_limit = flt(
780 frappe.db.get_value("POS Profile", self.doc.pos_profile, "write_off_limit")
781 )
782 if write_off_limit and abs(self.doc.outstanding_amount) <= write_off_limit:
783 self.doc.write_off_outstanding_amount_automatically = 1
784
785 if (
786 self.doc.doctype == "Sales Invoice"
787 and self.doc.get("is_pos")
Ankush Menat494bd9e2022-03-28 18:52:46 +0530788 and self.doc.get("is_return")
789 and not self.doc.get("is_consolidated")
Saqib Ansarie8a7a542022-03-12 19:20:48 +0530790 ):
Subin Tom7d627df2021-08-23 11:05:07 +0530791 self.set_total_amount_to_default_mop(total_amount_to_pay)
792 self.calculate_paid_amount()
Deepesh Garg0ebace52020-02-25 13:21:16 +0530793
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530794 def calculate_paid_amount(self):
Manas Solankida486ee2018-07-06 12:36:57 +0530795
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530796 paid_amount = base_paid_amount = 0.0
Rohit Waghchauref58cad62017-01-17 12:11:57 +0530797
798 if self.doc.is_pos:
Ankush Menat494bd9e2022-03-28 18:52:46 +0530799 for payment in self.doc.get("payments"):
Ayush Shuklae9cf1ab2017-05-25 14:14:55 +0530800 payment.amount = flt(payment.amount)
801 payment.base_amount = payment.amount * flt(self.doc.conversion_rate)
Rohit Waghchauref58cad62017-01-17 12:11:57 +0530802 paid_amount += payment.amount
803 base_paid_amount += payment.base_amount
rohitwaghchaure73456ac2017-05-16 11:29:57 +0530804 elif not self.doc.is_return:
Ankush Menat494bd9e2022-03-28 18:52:46 +0530805 self.doc.set("payments", [])
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530806
Manas Solankida486ee2018-07-06 12:36:57 +0530807 if self.doc.redeem_loyalty_points and self.doc.loyalty_amount:
808 base_paid_amount += self.doc.loyalty_amount
Ankush Menat494bd9e2022-03-28 18:52:46 +0530809 paid_amount += self.doc.loyalty_amount / flt(self.doc.conversion_rate)
Manas Solankida486ee2018-07-06 12:36:57 +0530810
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530811 self.doc.paid_amount = flt(paid_amount, self.doc.precision("paid_amount"))
812 self.doc.base_paid_amount = flt(base_paid_amount, self.doc.precision("base_paid_amount"))
813
Nabin Hait3bb1a422016-08-02 16:41:10 +0530814 def calculate_change_amount(self):
815 self.doc.change_amount = 0.0
Rohit Waghchaure609e2b42016-08-31 02:04:37 +0530816 self.doc.base_change_amount = 0.0
Saqib Ansaric2b83a02022-02-08 17:07:51 +0530817 grand_total = self.doc.rounded_total or self.doc.grand_total
818 base_grand_total = self.doc.base_rounded_total or self.doc.base_grand_total
Nabin Hait877e1bb2017-11-17 12:27:43 +0530819
Ankush Menat494bd9e2022-03-28 18:52:46 +0530820 if (
821 self.doc.doctype == "Sales Invoice"
822 and self.doc.paid_amount > grand_total
823 and not self.doc.is_return
824 and any(d.type == "Cash" for d in self.doc.payments)
825 ):
Ankush Menat494bd9e2022-03-28 18:52:46 +0530826 self.doc.change_amount = flt(
Ankush Menat3821a972022-03-28 20:14:19 +0530827 self.doc.paid_amount - grand_total, self.doc.precision("change_amount")
Ankush Menat494bd9e2022-03-28 18:52:46 +0530828 )
Nabin Haitac3b2aa2017-05-30 15:35:01 +0530829
Ankush Menat494bd9e2022-03-28 18:52:46 +0530830 self.doc.base_change_amount = flt(
Ankush Menat3821a972022-03-28 20:14:19 +0530831 self.doc.base_paid_amount - base_grand_total, self.doc.precision("base_change_amount")
Ankush Menat494bd9e2022-03-28 18:52:46 +0530832 )
mbauskar36b51892016-01-18 16:31:10 +0530833
Rohit Waghchaure7127a8f2016-08-04 14:56:15 +0530834 def calculate_write_off_amount(self):
Ankush Menat3821a972022-03-28 20:14:19 +0530835 if self.doc.get("write_off_outstanding_amount_automatically"):
Ankush Menat494bd9e2022-03-28 18:52:46 +0530836 self.doc.write_off_amount = flt(
Ankush Menat3821a972022-03-28 20:14:19 +0530837 self.doc.outstanding_amount, self.doc.precision("write_off_amount")
Ankush Menat494bd9e2022-03-28 18:52:46 +0530838 )
839 self.doc.base_write_off_amount = flt(
840 self.doc.write_off_amount * self.doc.conversion_rate,
841 self.doc.precision("base_write_off_amount"),
842 )
Rohit Waghchaure7127a8f2016-08-04 14:56:15 +0530843
Deepesh Gargf57f4af2022-03-24 12:31:37 +0530844 self.calculate_outstanding_amount()
845
mbauskar36b51892016-01-18 16:31:10 +0530846 def calculate_margin(self, item):
Makarand Bauskar0e4c5c92017-05-11 11:40:02 +0530847 rate_with_margin = 0.0
Shreya Shahbe690ef2017-11-14 17:22:41 +0530848 base_rate_with_margin = 0.0
mbauskar36b51892016-01-18 16:31:10 +0530849 if item.price_list_rate:
Rohit Waghchaure8bfe3302019-03-18 14:34:19 +0530850 if item.pricing_rules and not self.doc.ignore_pricing_rule:
Rohit Waghchaurea248dfb2020-07-16 17:27:26 +0530851 has_margin = False
marination733fd5f2020-08-26 18:23:12 +0530852 for d in get_applied_pricing_rules(item.pricing_rules):
Ankush Menat494bd9e2022-03-28 18:52:46 +0530853 pricing_rule = frappe.get_cached_doc("Pricing Rule", d)
Shreya Shahf718b0c2018-02-20 11:26:46 +0530854
Ankush Menat494bd9e2022-03-28 18:52:46 +0530855 if pricing_rule.margin_rate_or_amount and (
856 (
857 pricing_rule.currency == self.doc.currency
858 and pricing_rule.margin_type in ["Amount", "Percentage"]
859 )
860 or pricing_rule.margin_type == "Percentage"
861 ):
Rohit Waghchaure8bfe3302019-03-18 14:34:19 +0530862 item.margin_type = pricing_rule.margin_type
863 item.margin_rate_or_amount = pricing_rule.margin_rate_or_amount
Rohit Waghchaurea248dfb2020-07-16 17:27:26 +0530864 has_margin = True
865
866 if not has_margin:
867 item.margin_type = None
868 item.margin_rate_or_amount = 0.0
mbauskar36b51892016-01-18 16:31:10 +0530869
Rohit Waghchaure01faa9c2021-06-21 00:59:02 +0530870 if not item.pricing_rules and flt(item.rate) > flt(item.price_list_rate):
871 item.margin_type = "Amount"
Ankush Menat494bd9e2022-03-28 18:52:46 +0530872 item.margin_rate_or_amount = flt(
873 item.rate - item.price_list_rate, item.precision("margin_rate_or_amount")
874 )
Rohit Waghchaure01faa9c2021-06-21 00:59:02 +0530875 item.rate_with_margin = item.rate
876
877 elif item.margin_type and item.margin_rate_or_amount:
Ankush Menat494bd9e2022-03-28 18:52:46 +0530878 margin_value = (
879 item.margin_rate_or_amount
880 if item.margin_type == "Amount"
881 else flt(item.price_list_rate) * flt(item.margin_rate_or_amount) / 100
882 )
Makarand Bauskar0e4c5c92017-05-11 11:40:02 +0530883 rate_with_margin = flt(item.price_list_rate) + flt(margin_value)
Shreya Shahbe690ef2017-11-14 17:22:41 +0530884 base_rate_with_margin = flt(rate_with_margin) * flt(self.doc.conversion_rate)
mbauskar36b51892016-01-18 16:31:10 +0530885
Shreya Shahbe690ef2017-11-14 17:22:41 +0530886 return rate_with_margin, base_rate_with_margin
Nabin Hait852cb642017-07-05 12:58:19 +0530887
888 def set_item_wise_tax_breakup(self):
Nabin Hait9c421612017-07-20 13:32:01 +0530889 self.doc.other_charges_calculation = get_itemised_tax_breakup_html(self.doc)
Vishal Dhayaguded42242d2017-11-29 16:09:59 +0530890
Subin Tom7d627df2021-08-23 11:05:07 +0530891 def set_total_amount_to_default_mop(self, total_amount_to_pay):
Ankush Menat494bd9e2022-03-28 18:52:46 +0530892 default_mode_of_payment = frappe.db.get_value(
893 "POS Payment Method",
894 {"parent": self.doc.pos_profile, "default": 1},
895 ["mode_of_payment"],
896 as_dict=1,
897 )
Deepesh Garg0ebace52020-02-25 13:21:16 +0530898
Deepesh Garg0ebace52020-02-25 13:21:16 +0530899 if default_mode_of_payment:
Afshanb6148342021-08-10 21:33:58 +0530900 self.doc.payments = []
Ankush Menat494bd9e2022-03-28 18:52:46 +0530901 self.doc.append(
902 "payments",
903 {
904 "mode_of_payment": default_mode_of_payment.mode_of_payment,
905 "amount": total_amount_to_pay,
906 "default": 1,
907 },
908 )
909
Deepesh Garg0ebace52020-02-25 13:21:16 +0530910
Nabin Hait9c421612017-07-20 13:32:01 +0530911def get_itemised_tax_breakup_html(doc):
912 if not doc.taxes:
913 return
914 frappe.flags.company = doc.company
Vishal Dhayaguded42242d2017-11-29 16:09:59 +0530915
Nabin Hait9c421612017-07-20 13:32:01 +0530916 # get headers
Nabin Haitcaab5822017-08-24 16:22:28 +0530917 tax_accounts = []
918 for tax in doc.taxes:
Ankush Menat494bd9e2022-03-28 18:52:46 +0530919 if getattr(tax, "category", None) and tax.category == "Valuation":
Nabin Haitcaab5822017-08-24 16:22:28 +0530920 continue
rohitwaghchaure4e17fae2017-12-12 14:40:52 +0530921 if tax.description not in tax_accounts:
Nabin Haitcaab5822017-08-24 16:22:28 +0530922 tax_accounts.append(tax.description)
923
Nabin Hait9c421612017-07-20 13:32:01 +0530924 headers = get_itemised_tax_breakup_header(doc.doctype + " Item", tax_accounts)
Vishal Dhayaguded42242d2017-11-29 16:09:59 +0530925
Nabin Hait9c421612017-07-20 13:32:01 +0530926 # get tax breakup data
927 itemised_tax, itemised_taxable_amount = get_itemised_tax_breakup_data(doc)
Nabin Haitcaab5822017-08-24 16:22:28 +0530928
929 get_rounded_tax_amount(itemised_tax, doc.precision("tax_amount", "taxes"))
930
rohitwaghchaured4526682017-12-28 14:20:13 +0530931 update_itemised_tax_data(doc)
Nabin Hait9c421612017-07-20 13:32:01 +0530932 frappe.flags.company = None
Vishal Dhayaguded42242d2017-11-29 16:09:59 +0530933
Nabin Hait9c421612017-07-20 13:32:01 +0530934 return frappe.render_template(
Ankush Menat494bd9e2022-03-28 18:52:46 +0530935 "templates/includes/itemised_tax_breakup.html",
936 dict(
Nabin Hait9c421612017-07-20 13:32:01 +0530937 headers=headers,
938 itemised_tax=itemised_tax,
939 itemised_taxable_amount=itemised_taxable_amount,
940 tax_accounts=tax_accounts,
Ankush Menat494bd9e2022-03-28 18:52:46 +0530941 doc=doc,
942 ),
Nabin Hait9c421612017-07-20 13:32:01 +0530943 )
Nabin Hait852cb642017-07-05 12:58:19 +0530944
Ankush Menat494bd9e2022-03-28 18:52:46 +0530945
Deepesh Garg6a5ef262021-02-19 14:30:23 +0530946@frappe.whitelist()
947def get_round_off_applicable_accounts(company, account_list):
948 account_list = get_regional_round_off_accounts(company, account_list)
949
950 return account_list
951
Ankush Menat494bd9e2022-03-28 18:52:46 +0530952
Deepesh Garg6a5ef262021-02-19 14:30:23 +0530953@erpnext.allow_regional
954def get_regional_round_off_accounts(company, account_list):
955 pass
rohitwaghchaured4526682017-12-28 14:20:13 +0530956
Ankush Menat494bd9e2022-03-28 18:52:46 +0530957
rohitwaghchaured4526682017-12-28 14:20:13 +0530958@erpnext.allow_regional
959def update_itemised_tax_data(doc):
Ankush Menat494bd9e2022-03-28 18:52:46 +0530960 # Don't delete this method, used for localization
rohitwaghchaured4526682017-12-28 14:20:13 +0530961 pass
962
Ankush Menat494bd9e2022-03-28 18:52:46 +0530963
Nabin Haitb962fc12017-07-17 18:02:31 +0530964@erpnext.allow_regional
965def get_itemised_tax_breakup_header(item_doctype, tax_accounts):
966 return [_("Item"), _("Taxable Amount")] + tax_accounts
967
Ankush Menat494bd9e2022-03-28 18:52:46 +0530968
Nabin Haitb962fc12017-07-17 18:02:31 +0530969@erpnext.allow_regional
970def get_itemised_tax_breakup_data(doc):
971 itemised_tax = get_itemised_tax(doc.taxes)
972
973 itemised_taxable_amount = get_itemised_taxable_amount(doc.items)
974
975 return itemised_tax, itemised_taxable_amount
976
Ankush Menat494bd9e2022-03-28 18:52:46 +0530977
Nabin Hait34c551d2019-07-03 10:34:31 +0530978def get_itemised_tax(taxes, with_tax_account=False):
Nabin Haitb962fc12017-07-17 18:02:31 +0530979 itemised_tax = {}
980 for tax in taxes:
Ankush Menat494bd9e2022-03-28 18:52:46 +0530981 if getattr(tax, "category", None) and tax.category == "Valuation":
Nabin Haitcaab5822017-08-24 16:22:28 +0530982 continue
983
Nabin Haitb962fc12017-07-17 18:02:31 +0530984 item_tax_map = json.loads(tax.item_wise_tax_detail) if tax.item_wise_tax_detail else {}
Nabin Hait2e4de832017-09-19 14:53:16 +0530985 if item_tax_map:
986 for item_code, tax_data in item_tax_map.items():
987 itemised_tax.setdefault(item_code, frappe._dict())
Vishal Dhayaguded42242d2017-11-29 16:09:59 +0530988
Prateeksha Singhea7533f2018-06-11 13:31:33 +0530989 tax_rate = 0.0
990 tax_amount = 0.0
991
Nabin Hait2e4de832017-09-19 14:53:16 +0530992 if isinstance(tax_data, list):
Prateeksha Singhea7533f2018-06-11 13:31:33 +0530993 tax_rate = flt(tax_data[0])
994 tax_amount = flt(tax_data[1])
Nabin Hait2e4de832017-09-19 14:53:16 +0530995 else:
Prateeksha Singhea7533f2018-06-11 13:31:33 +0530996 tax_rate = flt(tax_data)
997
Ankush Menat494bd9e2022-03-28 18:52:46 +0530998 itemised_tax[item_code][tax.description] = frappe._dict(
999 dict(tax_rate=tax_rate, tax_amount=tax_amount)
1000 )
Rohit Waghchaure296fbfe2017-07-10 13:03:29 +05301001
Nabin Hait34c551d2019-07-03 10:34:31 +05301002 if with_tax_account:
1003 itemised_tax[item_code][tax.description].tax_account = tax.account_head
1004
Nabin Haitb962fc12017-07-17 18:02:31 +05301005 return itemised_tax
1006
Ankush Menat494bd9e2022-03-28 18:52:46 +05301007
Nabin Haitb962fc12017-07-17 18:02:31 +05301008def get_itemised_taxable_amount(items):
1009 itemised_taxable_amount = frappe._dict()
1010 for item in items:
Rohit Waghchaure296fbfe2017-07-10 13:03:29 +05301011 item_code = item.item_code or item.item_name
Nabin Haitb962fc12017-07-17 18:02:31 +05301012 itemised_taxable_amount.setdefault(item_code, 0)
1013 itemised_taxable_amount[item_code] += item.net_amount
1014
Nabin Haitcaab5822017-08-24 16:22:28 +05301015 return itemised_taxable_amount
1016
Ankush Menat494bd9e2022-03-28 18:52:46 +05301017
Nabin Haitcaab5822017-08-24 16:22:28 +05301018def get_rounded_tax_amount(itemised_tax, precision):
1019 # Rounding based on tax_amount precision
1020 for taxes in itemised_tax.values():
1021 for tax_account in taxes:
Himanshu Mishra35b26272018-11-13 11:13:04 +05301022 taxes[tax_account]["tax_amount"] = flt(taxes[tax_account]["tax_amount"], precision)
Deepesh Gargbfc17e42020-12-25 18:34:39 +05301023
Ankush Menat494bd9e2022-03-28 18:52:46 +05301024
Deepesh Gargbfc17e42020-12-25 18:34:39 +05301025class init_landed_taxes_and_totals(object):
1026 def __init__(self, doc):
1027 self.doc = doc
Ankush Menat494bd9e2022-03-28 18:52:46 +05301028 self.tax_field = "taxes" if self.doc.doctype == "Landed Cost Voucher" else "additional_costs"
Deepesh Gargbfc17e42020-12-25 18:34:39 +05301029 self.set_account_currency()
1030 self.set_exchange_rate()
1031 self.set_amounts_in_company_currency()
1032
1033 def set_account_currency(self):
1034 company_currency = erpnext.get_company_currency(self.doc.company)
1035 for d in self.doc.get(self.tax_field):
1036 if not d.account_currency:
Ankush Menat494bd9e2022-03-28 18:52:46 +05301037 account_currency = frappe.db.get_value("Account", d.expense_account, "account_currency")
Deepesh Gargbfc17e42020-12-25 18:34:39 +05301038 d.account_currency = account_currency or company_currency
1039
1040 def set_exchange_rate(self):
1041 company_currency = erpnext.get_company_currency(self.doc.company)
1042 for d in self.doc.get(self.tax_field):
1043 if d.account_currency == company_currency:
1044 d.exchange_rate = 1
Deepesh Garg22f5ff82021-03-17 10:56:52 +05301045 elif not d.exchange_rate:
Ankush Menat494bd9e2022-03-28 18:52:46 +05301046 d.exchange_rate = get_exchange_rate(
1047 self.doc.posting_date,
1048 account=d.expense_account,
1049 account_currency=d.account_currency,
1050 company=self.doc.company,
1051 )
Deepesh Gargbfc17e42020-12-25 18:34:39 +05301052
1053 if not d.exchange_rate:
1054 frappe.throw(_("Row {0}: Exchange Rate is mandatory").format(d.idx))
1055
1056 def set_amounts_in_company_currency(self):
1057 for d in self.doc.get(self.tax_field):
1058 d.amount = flt(d.amount, d.precision("amount"))
Walstan Baptista37b826b2021-04-03 19:48:46 +05301059 d.base_amount = flt(d.amount * flt(d.exchange_rate), d.precision("base_amount"))