mirror of
https://github.com/bringout/oca-financial.git
synced 2026-04-27 15:22:00 +02:00
131 lines
4.7 KiB
Python
131 lines
4.7 KiB
Python
from math import copysign
|
|
|
|
from odoo import _, api, exceptions, fields, models
|
|
from odoo.tools.float_utils import float_compare
|
|
|
|
|
|
class AccountTax(models.Model):
|
|
"""Inherit to implement the tax using avatax API"""
|
|
|
|
_inherit = "account.tax"
|
|
|
|
is_avatax = fields.Boolean()
|
|
|
|
@api.model
|
|
def _get_avalara_tax_domain(self, tax_rate, doc_type):
|
|
return [
|
|
("amount", "=", tax_rate),
|
|
("is_avatax", "=", True),
|
|
(
|
|
"company_id",
|
|
"=",
|
|
self.env.company.id,
|
|
),
|
|
]
|
|
|
|
@api.model
|
|
def _get_avalara_tax_name(self, tax_rate, doc_type=None):
|
|
return _("{}%*").format(str(tax_rate))
|
|
|
|
@api.model
|
|
def get_avalara_tax(self, tax_rate, doc_type):
|
|
domain = self._get_avalara_tax_domain(tax_rate, doc_type)
|
|
tax = self.with_context(active_test=False).search(domain, limit=1)
|
|
if tax and not tax.active:
|
|
tax.active = True
|
|
if not tax:
|
|
domain = self._get_avalara_tax_domain(0, doc_type)
|
|
tax_template = self.search(domain, limit=1)
|
|
if not tax_template:
|
|
raise exceptions.UserError(
|
|
_("Please configure Avatax Tax for Company %s:")
|
|
% self.env.company.name
|
|
)
|
|
# If you get a unique constraint error here,
|
|
# check the data for your existing Avatax taxes.
|
|
vals = {
|
|
"amount": tax_rate,
|
|
"name": self._get_avalara_tax_name(tax_rate, doc_type),
|
|
}
|
|
tax = tax_template.sudo().copy(default=vals)
|
|
# Odoo core does not use the name set in default dict
|
|
tax.name = vals.get("name")
|
|
return tax
|
|
|
|
def compute_all(
|
|
self,
|
|
price_unit,
|
|
currency=None,
|
|
quantity=1.0,
|
|
product=None,
|
|
partner=None,
|
|
is_refund=False,
|
|
handle_price_include=True,
|
|
include_caba_tags=False,
|
|
fixed_multiplicator=1,
|
|
):
|
|
"""
|
|
Adopted as the central point to inject custom tax computations.
|
|
Avatax logic is triggered if the "avatax_invoice" is set in the context.
|
|
To find the Avatax amount, we search an Invoice line with the same
|
|
quantity, price and product.
|
|
"""
|
|
res = super().compute_all(
|
|
price_unit,
|
|
currency,
|
|
quantity,
|
|
product,
|
|
partner,
|
|
is_refund,
|
|
handle_price_include,
|
|
include_caba_tags,
|
|
fixed_multiplicator,
|
|
)
|
|
avatax_invoice = self.env.context.get("avatax_invoice")
|
|
current_aml = False
|
|
if "current_aml" in self.env.context:
|
|
current_aml = self.env["account.move.line"].browse(
|
|
self.env.context.get("current_aml")
|
|
)
|
|
if not (
|
|
current_aml.display_type == "product"
|
|
and current_aml.account_type != "asset_receivable"
|
|
):
|
|
avatax_invoice = False
|
|
if avatax_invoice:
|
|
# Find the Avatax amount in the invoice Lines
|
|
# Looks up the line for the current product, price_unit, and quantity
|
|
# Note that the price_unit used must consider discount
|
|
base = res["total_excluded"]
|
|
digits = 6
|
|
avatax_amount = None
|
|
if current_aml:
|
|
avatax_amount = copysign(current_aml.avatax_amt_line, base)
|
|
else:
|
|
for line in avatax_invoice.invoice_line_ids:
|
|
price_unit = line.currency_id._convert(
|
|
price_unit,
|
|
avatax_invoice.company_id.currency_id,
|
|
avatax_invoice.company_id,
|
|
avatax_invoice.date,
|
|
)
|
|
if (
|
|
line.product_id == product
|
|
and float_compare(line.quantity, quantity, digits) == 0
|
|
):
|
|
avatax_amount = copysign(line.avatax_amt_line, base)
|
|
break
|
|
if avatax_amount is None:
|
|
avatax_amount = 0.0
|
|
raise exceptions.UserError(
|
|
_(
|
|
"Incorrect retrieval of Avatax amount for Invoice %(avatax_invoice)s:"
|
|
" product %(product.display_name)s, price_unit %(-price_unit)f"
|
|
" , quantity %(quantity)f"
|
|
)
|
|
)
|
|
for tax_item in res["taxes"]:
|
|
if tax_item["amount"] != 0:
|
|
tax_item["amount"] = avatax_amount
|
|
res["total_included"] = base + avatax_amount
|
|
return res
|