From 2bef3c4bc8dd4c2dc88c8cb003c0a46773c7c911 Mon Sep 17 00:00:00 2001
From: Daniel Reis
Date: Tue, 2 Aug 2022 21:02:42 +0100
Subject: [PATCH 01/27] account_avatax_sale_oca: renamed from
account_sale_avatax
---
account_avatax_sale_oca/README.rst | 162 ++++++
account_avatax_sale_oca/__init__.py | 1 +
account_avatax_sale_oca/__manifest__.py | 19 +
.../i18n/account_avatax_sale.pot | 202 +++++++
account_avatax_sale_oca/models/__init__.py | 5 +
.../models/account_move.py | 17 +
account_avatax_sale_oca/models/account_tax.py | 44 ++
.../models/avalara_salestax.py | 21 +
account_avatax_sale_oca/models/partner.py | 27 +
account_avatax_sale_oca/models/sale_order.py | 373 +++++++++++++
.../readme/CONTRIBUTORS.rst | 17 +
.../readme/DESCRIPTION.rst | 2 +
account_avatax_sale_oca/readme/USAGE.rst | 58 +++
.../static/description/icon.png | Bin 0 -> 9455 bytes
.../static/description/index.html | 493 ++++++++++++++++++
.../views/avalara_salestax_view.xml | 38 ++
.../views/partner_view.xml | 18 +
.../views/sale_order_view.xml | 93 ++++
18 files changed, 1590 insertions(+)
create mode 100644 account_avatax_sale_oca/README.rst
create mode 100644 account_avatax_sale_oca/__init__.py
create mode 100644 account_avatax_sale_oca/__manifest__.py
create mode 100644 account_avatax_sale_oca/i18n/account_avatax_sale.pot
create mode 100644 account_avatax_sale_oca/models/__init__.py
create mode 100644 account_avatax_sale_oca/models/account_move.py
create mode 100644 account_avatax_sale_oca/models/account_tax.py
create mode 100644 account_avatax_sale_oca/models/avalara_salestax.py
create mode 100644 account_avatax_sale_oca/models/partner.py
create mode 100644 account_avatax_sale_oca/models/sale_order.py
create mode 100644 account_avatax_sale_oca/readme/CONTRIBUTORS.rst
create mode 100644 account_avatax_sale_oca/readme/DESCRIPTION.rst
create mode 100644 account_avatax_sale_oca/readme/USAGE.rst
create mode 100644 account_avatax_sale_oca/static/description/icon.png
create mode 100644 account_avatax_sale_oca/static/description/index.html
create mode 100644 account_avatax_sale_oca/views/avalara_salestax_view.xml
create mode 100644 account_avatax_sale_oca/views/partner_view.xml
create mode 100644 account_avatax_sale_oca/views/sale_order_view.xml
diff --git a/account_avatax_sale_oca/README.rst b/account_avatax_sale_oca/README.rst
new file mode 100644
index 000000000..72f83f9fa
--- /dev/null
+++ b/account_avatax_sale_oca/README.rst
@@ -0,0 +1,162 @@
+=========================================
+Avalara Avatax Connector for Sales Orders
+=========================================
+
+.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ !! This file is generated by oca-gen-addon-readme !!
+ !! changes will be overwritten. !!
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+.. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png
+ :target: https://odoo-community.org/page/development-status
+ :alt: Production/Stable
+.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
+ :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
+ :alt: License: AGPL-3
+.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Faccount--fiscal--rule-lightgray.png?logo=github
+ :target: https://github.com/OCA/account-fiscal-rule/tree/15.0/account_avatax_sale
+ :alt: OCA/account-fiscal-rule
+.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
+ :target: https://translation.odoo-community.org/projects/account-fiscal-rule-15-0/account-fiscal-rule-15-0-account_avatax_sale
+ :alt: Translate me on Weblate
+.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
+ :target: https://runbot.odoo-community.org/runbot/93/15.0
+ :alt: Try me on Runbot
+
+|badge1| |badge2| |badge3| |badge4| |badge5|
+
+This module is a component of the Avatax Integration with odoo app.
+Please refer to the corresponding documentation.
+
+**Table of contents**
+
+.. contents::
+ :local:
+
+Usage
+=====
+
+The AvaTax module is integrated into Sales Orders and allows computation of taxes.
+Sales order transactions do not appear in the in the AvaTax interface.
+
+The information placed in the sales order will automatically pass to the invoice
+on the Avalara server and can be viewed in the AvaTax control panel.
+
+Discounts are handled when they are enabled in Odoo's settings.
+They will be reported as a net deduction on the line item cost.
+
+Create New Sales Order
+
+- Navigate to: Sales >> Orders >> Orders
+
+- Click Create button
+
+Compute Taxes with AvaTax
+
+- The module will calculate tax when the sales order is confirmed,
+ or by navigating to Action >> Update taxes with Avatax.
+ At this step, the sales order will retrieve the tax amount from Avalara
+ but will not report the transaction to the AvaTax dashboard.
+ Only invoice, refund, and payment activity are reported to the dashboard.
+
+- The module will check if there is a selected warehouse
+ and will automatically determine the address of the warehouse
+ and the origin location. If no address is assigned to the warehouse
+ the module will automatically use the address of the company as its origin.
+ Location code will automatically populate with the warehouse code
+ but can be modified if needed.
+
+- Hide Exemption & Tax Based on shipping address -- this will provide this
+ feature support at sale order level.
+
+
+Tax Exemption Status
+
+- Tax exemption status can be defined on Contacts.
+
+- In a multi-company environment, the exemption status is defined per
+ Company, since each individual company is required to secure the
+ exemption certificates to claim for exemption application,
+ and this may not be the case for all Companies.
+
+- If the customer is tax exempt, in the "Avatax" tab, check the "Is Tax Exempt" checkbox.
+ When checked, the exemption details can be provided.
+ The Exemption Code is the type of exemption,
+ and the Exemption Number is an identification number to use on the customer's State.
+
+- This exemption status will only be applied for delivery addresses
+ in the State matching the State of the exemption address.
+ The same customer can have exemptiions on several states.
+ For this use additional Contact/Addresses for those states,
+ and enter the exempention details there.
+
+- To make this data management simpler, is it possible to set the customer as exempt
+ country wide, using the corresponding checkbox. In this case the exemption status will
+ be used for delivery addresses in any state. Using this option has compliance risks, so
+ plase use it with care.
+
+Bug Tracker
+===========
+
+Bugs are tracked on `GitHub Issues `_.
+In case of trouble, please check there if your issue has already been reported.
+If you spotted it first, help us smashing it by providing a detailed and welcomed
+`feedback `_.
+
+Do not contact contributors directly about support or help with technical issues.
+
+Credits
+=======
+
+Authors
+~~~~~~~
+
+* Open Source Integrators
+* Fabrice Henrion
+* Sodexis
+
+Contributors
+~~~~~~~~~~~~
+
+* Odoo SA
+
+ * Fabrice Henrion
+
+* Open Source Integrators (https://opensourceintegrators.com)
+
+ * Daniel Reis
+ * Bhavesh Odedra
+ * Sandip Mangukiya
+
+* Serpent CS
+
+ * Murtuza Saleh
+
+* Sodexis
+
+ * Atchuthan Ubendran
+
+Maintainers
+~~~~~~~~~~~
+
+This module is maintained by the OCA.
+
+.. image:: https://odoo-community.org/logo.png
+ :alt: Odoo Community Association
+ :target: https://odoo-community.org
+
+OCA, or the Odoo Community Association, is a nonprofit organization whose
+mission is to support the collaborative development of Odoo features and
+promote its widespread use.
+
+.. |maintainer-dreispt| image:: https://github.com/dreispt.png?size=40px
+ :target: https://github.com/dreispt
+ :alt: dreispt
+
+Current `maintainer `__:
+
+|maintainer-dreispt|
+
+This module is part of the `OCA/account-fiscal-rule `_ project on GitHub.
+
+You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
diff --git a/account_avatax_sale_oca/__init__.py b/account_avatax_sale_oca/__init__.py
new file mode 100644
index 000000000..0650744f6
--- /dev/null
+++ b/account_avatax_sale_oca/__init__.py
@@ -0,0 +1 @@
+from . import models
diff --git a/account_avatax_sale_oca/__manifest__.py b/account_avatax_sale_oca/__manifest__.py
new file mode 100644
index 000000000..2ad6c0043
--- /dev/null
+++ b/account_avatax_sale_oca/__manifest__.py
@@ -0,0 +1,19 @@
+{
+ "name": "Avalara Avatax Certified Connector for Sales Orders",
+ "version": "15.0.1.1.0",
+ "author": "Open Source Integrators, Fabrice Henrion,"
+ "Sodexis, Odoo Community Association (OCA)",
+ "summary": "Sales Orders with automatic Tax application using Avatax",
+ "license": "AGPL-3",
+ "category": "Accounting",
+ "website": "https://github.com/OCA/account-fiscal-rule",
+ "depends": ["account_avatax_oca", "sale_stock"],
+ "data": [
+ "views/sale_order_view.xml",
+ "views/partner_view.xml",
+ "views/avalara_salestax_view.xml",
+ ],
+ "auto_install": True,
+ "development_status": "Production/Stable",
+ "maintainers": ["dreispt"],
+}
diff --git a/account_avatax_sale_oca/i18n/account_avatax_sale.pot b/account_avatax_sale_oca/i18n/account_avatax_sale.pot
new file mode 100644
index 000000000..7cf0ef086
--- /dev/null
+++ b/account_avatax_sale_oca/i18n/account_avatax_sale.pot
@@ -0,0 +1,202 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * account_avatax_sale
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 15.0\n"
+"Report-Msgid-Bugs-To: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: account_avatax_sale
+#: model:ir.model.fields,field_description:account_avatax_sale.field_avalara_salestax__sale_calculate_tax
+msgid "Auto Calculate Tax on SO Save"
+msgstr ""
+
+#. module: account_avatax_sale
+#: model:ir.model.fields,help:account_avatax_sale.field_avalara_salestax__sale_calculate_tax
+msgid ""
+"Automatically triggers API to calculate tax If changes made onSO's "
+"warehouse_id, tax_on_shipping_address, SO line's price_unit, discount, "
+"product_uom_qty"
+msgstr ""
+
+#. module: account_avatax_sale
+#: model:ir.model.fields,field_description:account_avatax_sale.field_sale_order__tax_amount
+#: model:ir.model.fields,field_description:account_avatax_sale.field_sale_order_line__tax_amt
+msgid "AvaTax"
+msgstr ""
+
+#. module: account_avatax_sale
+#: model:ir.model,name:account_avatax_sale.model_avalara_salestax
+msgid "AvaTax Configuration"
+msgstr ""
+
+#. module: account_avatax_sale
+#: model:ir.model.fields,field_description:account_avatax_sale.field_sale_order__avatax_request_log
+msgid "Avatax API Request Log"
+msgstr ""
+
+#. module: account_avatax_sale
+#: model:ir.model.fields,field_description:account_avatax_sale.field_sale_order__avatax_response_log
+msgid "Avatax API Response Log"
+msgstr ""
+
+#. module: account_avatax_sale
+#: model_terms:ir.ui.view,arch_db:account_avatax_sale.sale_order_update_form_view
+msgid "Avatax Log"
+msgstr ""
+
+#. module: account_avatax_sale
+#: model:ir.model.fields,field_description:account_avatax_sale.field_sale_order__calculate_tax_on_save
+msgid "Calculate Tax On Save"
+msgstr ""
+
+#. module: account_avatax_sale
+#: model_terms:ir.ui.view,arch_db:account_avatax_sale.sale_order_update_form_view
+msgid "Compute Taxes"
+msgstr ""
+
+#. module: account_avatax_sale
+#: model:ir.model,name:account_avatax_sale.model_res_partner
+msgid "Contact"
+msgstr ""
+
+#. module: account_avatax_sale
+#: code:addons/account_avatax_sale/models/partner.py:0
+#, python-format
+msgid ""
+"Enabling the exemption status for all states may have tax compliance risks, and should be carefully considered.\n"
+"\n"
+" Please ensure that your tax advisor was consulted and the necessary tax exemption documentation was obtained for every state this Partner may have transactions."
+msgstr ""
+
+#. module: account_avatax_sale
+#: model:ir.model.fields,field_description:account_avatax_sale.field_res_partner__property_exemption_country_wide
+#: model:ir.model.fields,field_description:account_avatax_sale.field_res_users__property_exemption_country_wide
+msgid "Exemption Applies Country Wide"
+msgstr ""
+
+#. module: account_avatax_sale
+#: model:ir.model.fields,field_description:account_avatax_sale.field_sale_order__exemption_code_id
+msgid "Exemption Code"
+msgstr ""
+
+#. module: account_avatax_sale
+#: model:ir.model.fields,field_description:account_avatax_sale.field_sale_order__exemption_code
+msgid "Exemption Number"
+msgstr ""
+
+#. module: account_avatax_sale
+#: model:ir.model.fields,field_description:account_avatax_sale.field_sale_order__hide_exemption
+msgid "Hide Exemption & Tax Based on shipping address"
+msgstr ""
+
+#. module: account_avatax_sale
+#: model:ir.model.fields,help:account_avatax_sale.field_sale_order__exemption_code_id
+msgid "It show the customer exemption code"
+msgstr ""
+
+#. module: account_avatax_sale
+#: model:ir.model.fields,help:account_avatax_sale.field_sale_order__exemption_code
+msgid "It show the customer exemption number"
+msgstr ""
+
+#. module: account_avatax_sale
+#: model:ir.model,name:account_avatax_sale.model_account_move
+msgid "Journal Entry"
+msgstr ""
+
+#. module: account_avatax_sale
+#: model:ir.model.fields,field_description:account_avatax_sale.field_sale_order__location_code
+msgid "Location Code"
+msgstr ""
+
+#. module: account_avatax_sale
+#: model:ir.model.fields,help:account_avatax_sale.field_sale_order__location_code
+msgid "Origin address location code"
+msgstr ""
+
+#. module: account_avatax_sale
+#: model:ir.model.fields,field_description:account_avatax_sale.field_avalara_salestax__override_line_taxes
+msgid "Override Line Taxes"
+msgstr ""
+
+#. module: account_avatax_sale
+#: model:ir.model,name:account_avatax_sale.model_sale_order
+msgid "Sales Order"
+msgstr ""
+
+#. module: account_avatax_sale
+#: model:ir.model,name:account_avatax_sale.model_sale_order_line
+msgid "Sales Order Line"
+msgstr ""
+
+#. module: account_avatax_sale
+#: model:ir.model,name:account_avatax_sale.model_account_tax
+msgid "Tax"
+msgstr ""
+
+#. module: account_avatax_sale
+#: model:ir.model.fields,field_description:account_avatax_sale.field_sale_order__tax_address_id
+msgid "Tax Address"
+msgstr ""
+
+#. module: account_avatax_sale
+#: code:addons/account_avatax_sale/models/partner.py:0
+#, python-format
+msgid "Tax Compliance Risk"
+msgstr ""
+
+#. module: account_avatax_sale
+#: model:ir.model.fields,field_description:account_avatax_sale.field_sale_order__tax_on_shipping_address
+msgid "Tax based on shipping address"
+msgstr ""
+
+#. module: account_avatax_sale
+#: model:ir.model.fields,help:account_avatax_sale.field_sale_order__hide_exemption
+msgid ""
+"Uncheck the this field to show exemption fields on SO/Invoice form view. "
+"Also, it will show Tax based on shipping address button"
+msgstr ""
+
+#. module: account_avatax_sale
+#: model:ir.actions.server,name:account_avatax_sale.action_sale_order_compute_taxes
+msgid "Update taxes with AvaTax"
+msgstr ""
+
+#. module: account_avatax_sale
+#: model:ir.model.fields,field_description:account_avatax_sale.field_sale_order__is_avatax
+msgid "Use Avatax API"
+msgstr ""
+
+#. module: account_avatax_sale
+#: model:ir.model.fields,field_description:account_avatax_sale.field_avalara_salestax__use_partner_invoice_id
+msgid "Use Invoice partner's customer code in SO"
+msgstr ""
+
+#. module: account_avatax_sale
+#: model:ir.model.fields,help:account_avatax_sale.field_avalara_salestax__use_partner_invoice_id
+msgid "Use Sales Order's Invoice Address field to determine TaxableStatus"
+msgstr ""
+
+#. module: account_avatax_sale
+#: model:ir.model.fields,help:account_avatax_sale.field_avalara_salestax__override_line_taxes
+msgid ""
+"When checked, the Avatax computed tax will replace any other taxes that may "
+"exist in the document line."
+msgstr ""
+
+#. module: account_avatax_sale
+#: model:ir.model.fields,help:account_avatax_sale.field_res_partner__property_exemption_country_wide
+#: model:ir.model.fields,help:account_avatax_sale.field_res_users__property_exemption_country_wide
+msgid ""
+"When enabled, the delivery address State is irrelevant when looking up the "
+"exemption status, meaning that the exemption is considered applicable for "
+"all states"
+msgstr ""
diff --git a/account_avatax_sale_oca/models/__init__.py b/account_avatax_sale_oca/models/__init__.py
new file mode 100644
index 000000000..65f793277
--- /dev/null
+++ b/account_avatax_sale_oca/models/__init__.py
@@ -0,0 +1,5 @@
+from . import account_move
+from . import account_tax
+from . import partner
+from . import sale_order
+from . import avalara_salestax
diff --git a/account_avatax_sale_oca/models/account_move.py b/account_avatax_sale_oca/models/account_move.py
new file mode 100644
index 000000000..d8319eebc
--- /dev/null
+++ b/account_avatax_sale_oca/models/account_move.py
@@ -0,0 +1,17 @@
+from odoo import api, models
+
+
+class AccountMove(models.Model):
+ _inherit = "account.move"
+
+ @api.onchange("partner_id")
+ def _onchange_partner_id(self):
+ res = super(AccountMove, self)._onchange_partner_id()
+ self._onchange_partner_shipping_id()
+ return res
+
+ @api.onchange("partner_shipping_id")
+ def _onchange_partner_shipping_id(self):
+ res = super(AccountMove, self)._onchange_partner_shipping_id()
+ self.tax_on_shipping_address = bool(self.partner_shipping_id)
+ return res
diff --git a/account_avatax_sale_oca/models/account_tax.py b/account_avatax_sale_oca/models/account_tax.py
new file mode 100644
index 000000000..4962f3dac
--- /dev/null
+++ b/account_avatax_sale_oca/models/account_tax.py
@@ -0,0 +1,44 @@
+from odoo import models
+
+
+class AccountTax(models.Model):
+ _inherit = "account.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,
+ ):
+ res = super().compute_all(
+ price_unit,
+ currency,
+ quantity,
+ product,
+ partner,
+ is_refund,
+ handle_price_include,
+ include_caba_tags=False,
+ )
+ for_avatax_object = self.env.context.get("for_avatax_object")
+ if for_avatax_object:
+ # Find the Avatax amount in the document Lines
+ # Looks up the line for the current product, price_unit, and quantity
+ # Note that the price_unit used must consider discount
+ avatax_ids = self.env["account.tax"].search([("is_avatax", "=", True)]).ids
+ for tax_data in [x for x in res["taxes"] if x["id"] in avatax_ids]:
+ line = for_avatax_object.order_line.filtered(
+ lambda x: tax_data["id"] in x.tax_id.ids
+ and x.product_id == product
+ and x.product_uom_qty == quantity
+ and x.price_unit == price_unit
+ )[:1]
+ if line.tax_amt: # Avatax Amount
+ tax_data["amount"] = line.tax_amt
+ res["total_included"] = res["total_excluded"] + line.tax_amt
+ return res
diff --git a/account_avatax_sale_oca/models/avalara_salestax.py b/account_avatax_sale_oca/models/avalara_salestax.py
new file mode 100644
index 000000000..86ff1434e
--- /dev/null
+++ b/account_avatax_sale_oca/models/avalara_salestax.py
@@ -0,0 +1,21 @@
+from odoo import fields, models
+
+
+class AvalaraSalestax(models.Model):
+ _inherit = "avalara.salestax"
+
+ use_partner_invoice_id = fields.Boolean(
+ "Use Invoice partner's customer code in SO",
+ default=True,
+ help="Use Sales Order's Invoice Address field to determine Taxable" "Status",
+ )
+ sale_calculate_tax = fields.Boolean(
+ "Auto Calculate Tax on SO Save",
+ help="Automatically triggers API to calculate tax If changes made on"
+ "SO's warehouse_id, tax_on_shipping_address, "
+ "SO line's price_unit, discount, product_uom_qty",
+ )
+ override_line_taxes = fields.Boolean(
+ help="When checked, the Avatax computed tax will replace any other taxes"
+ " that may exist in the document line.",
+ )
diff --git a/account_avatax_sale_oca/models/partner.py b/account_avatax_sale_oca/models/partner.py
new file mode 100644
index 000000000..b698fbe93
--- /dev/null
+++ b/account_avatax_sale_oca/models/partner.py
@@ -0,0 +1,27 @@
+from odoo import _, api, fields, models
+
+
+class ResPartner(models.Model):
+ _inherit = "res.partner"
+
+ @api.onchange("property_exemption_country_wide")
+ def _onchange_property_exemption_contry_wide(self):
+ if self.property_exemption_country_wide:
+ message = (
+ _(
+ "Enabling the exemption status for all states"
+ " may have tax compliance risks,"
+ " and should be carefully considered.\n\n"
+ " Please ensure that your tax advisor was consulted and the"
+ " necessary tax exemption documentation was obtained"
+ " for every state this Partner may have transactions."
+ ),
+ )
+ return {"warning": {"title": _("Tax Compliance Risk"), "message": message}}
+
+ property_exemption_country_wide = fields.Boolean(
+ "Exemption Applies Country Wide",
+ help="When enabled, the delivery address State is irrelevant"
+ " when looking up the exemption status, meaning that the exemption"
+ " is considered applicable for all states",
+ )
diff --git a/account_avatax_sale_oca/models/sale_order.py b/account_avatax_sale_oca/models/sale_order.py
new file mode 100644
index 000000000..142f6bdca
--- /dev/null
+++ b/account_avatax_sale_oca/models/sale_order.py
@@ -0,0 +1,373 @@
+from odoo import api, fields, models
+
+
+class SaleOrder(models.Model):
+ _inherit = "sale.order"
+
+ @api.depends(
+ "order_line.tax_id", "order_line.price_unit", "amount_total", "amount_untaxed"
+ )
+ def _compute_tax_totals_json(self):
+ # Make the Sales Order data available to the AccountTax.compute_all() method
+ # This is needed to take in consideration the additional Avatax fields
+ enriched_self = self.with_context(for_avatax_object=self)
+ return super(SaleOrder, enriched_self)._compute_tax_totals_json()
+
+ @api.model
+ @api.depends("company_id", "partner_id", "partner_invoice_id", "state")
+ def _compute_hide_exemption(self):
+ avatax_config = self.env.company.get_avatax_config_company()
+ for order in self:
+ order.hide_exemption = avatax_config.hide_exemption
+
+ hide_exemption = fields.Boolean(
+ "Hide Exemption & Tax Based on shipping address",
+ compute=_compute_hide_exemption, # For past transactions visibility
+ default=lambda self: self.env.company.get_avatax_config_company,
+ help="Uncheck the this field to show exemption fields on SO/Invoice form view. "
+ "Also, it will show Tax based on shipping address button",
+ )
+ tax_amount = fields.Monetary(string="AvaTax")
+
+ @api.onchange("partner_shipping_id", "partner_id")
+ def onchange_partner_shipping_id(self):
+ """
+ Apply the exemption number and code from the Invoice Partner Data
+ We can only apply an exemption status that matches the delivery
+ address Country and State.
+
+ The setup for this is to add contact/addresses for the Invoicing Partner,
+ for each of the states we can claim exepmtion for.
+ """
+ res = super(SaleOrder, self).onchange_partner_shipping_id()
+ self.tax_on_shipping_address = bool(self.partner_shipping_id)
+ return res
+
+ @api.depends("partner_invoice_id", "tax_address_id", "company_id")
+ def _compute_onchange_exemption(self):
+ for order in self.filtered(lambda x: x.state not in ["done", "cancel"]):
+ invoice_partner = order.partner_invoice_id.commercial_partner_id
+ ship_to_address = order.tax_address_id
+ # Find an exemption address matching the Country + State
+ # of the Delivery address
+ exemption_addresses = (
+ invoice_partner | invoice_partner.child_ids
+ ).filtered("property_tax_exempt")
+ exemption_address_naive = exemption_addresses.filtered(
+ lambda a: a.country_id == ship_to_address.country_id
+ and (
+ a.state_id == ship_to_address.state_id
+ or invoice_partner.property_exemption_country_wide
+ )
+ )[:1]
+ # Force Company to get the correct values form the Property fields
+ exemption_address = exemption_address_naive.with_company(
+ order.company_id.id
+ )
+ order.exemption_code = exemption_address.property_exemption_number
+ order.exemption_code_id = exemption_address.property_exemption_code_id
+
+ def _prepare_invoice(self):
+ invoice_vals = super(SaleOrder, self)._prepare_invoice()
+ invoice_vals.update(
+ {
+ "exemption_code": self.exemption_code or "",
+ "exemption_code_id": self.exemption_code_id.id or False,
+ "exemption_locked": True,
+ "location_code": self.location_code or "",
+ "warehouse_id": self.warehouse_id.id or "",
+ "tax_on_shipping_address": self.tax_on_shipping_address,
+ "so_partner_id": self.partner_id.id,
+ }
+ )
+ return invoice_vals
+
+ @api.onchange("order_line", "fiscal_position_id")
+ def onchange_reset_avatax_amount(self):
+ """
+ When changing quantities or prices, reset the Avatax computed amount.
+ The Odoo computed tax amount will then be shown, as a reference.
+ The Avatax amount will be recomputed upon document validation.
+ """
+ for order in self:
+ order.tax_amount = 0
+ order.order_line.write({"tax_amt": 0})
+
+ @api.depends("order_line.price_total", "order_line.product_uom_qty", "tax_amount")
+ def _amount_all(self):
+ """
+ Compute fields amount_untaxed, amount_tax, amount_total
+ Their computation needs to be overriden,
+ to use the amounts returned by Avatax service, stored in specific fields.
+ """
+ res = super()._amount_all()
+ for order in self:
+ if order.tax_amount:
+ order.update(
+ {
+ "amount_tax": order.tax_amount,
+ "amount_total": order.amount_untaxed + order.tax_amount,
+ }
+ )
+ return res
+
+ @api.depends("tax_on_shipping_address", "partner_id", "partner_shipping_id")
+ def _compute_tax_address_id(self):
+ for invoice in self:
+ invoice.tax_address_id = (
+ invoice.partner_shipping_id
+ if invoice.tax_on_shipping_address
+ else invoice.partner_id
+ )
+
+ is_avatax = fields.Boolean(related="fiscal_position_id.is_avatax")
+ exemption_code = fields.Char(
+ "Exemption Number",
+ compute=_compute_onchange_exemption,
+ readonly=False, # New computed writeable fields
+ store=True,
+ help="It show the customer exemption number",
+ )
+ exemption_code_id = fields.Many2one(
+ "exemption.code",
+ "Exemption Code",
+ compute=_compute_onchange_exemption,
+ readonly=False, # New computed writeable fields
+ store=True,
+ help="It show the customer exemption code",
+ )
+ tax_on_shipping_address = fields.Boolean(
+ "Tax based on shipping address", default=True
+ )
+ tax_address_id = fields.Many2one(
+ "res.partner",
+ "Tax Address",
+ readonly=True,
+ states={"draft": [("readonly", False)]},
+ compute="_compute_tax_address_id",
+ store=True,
+ )
+ location_code = fields.Char(help="Origin address location code")
+ calculate_tax_on_save = fields.Boolean()
+ avatax_request_log = fields.Text(
+ "Avatax API Request Log", readonly=True, copy=False
+ )
+ avatax_response_log = fields.Text(
+ "Avatax API Response Log", readonly=True, copy=False
+ )
+
+ def _get_avatax_doc_type(self, commit=False):
+ return "SalesOrder"
+
+ def _avatax_prepare_lines(self, order_lines, doc_type=None):
+ """
+ Prepare the lines to use for Avatax computation.
+ Returns a list of dicts
+ """
+ lines = [
+ line._avatax_prepare_line(sign=1, doc_type=doc_type)
+ for line in order_lines.filtered(lambda line: not line.display_type)
+ ]
+ return [x for x in lines if x]
+
+ def _avatax_compute_tax(self):
+ """Contact REST API and recompute taxes for a Sale Order"""
+ self and self.ensure_one()
+ doc_type = self._get_avatax_doc_type()
+ Tax = self.env["account.tax"]
+ avatax_config = self.company_id.get_avatax_config_company()
+ if not avatax_config:
+ return False
+ partner = self.partner_id
+ if avatax_config.use_partner_invoice_id:
+ partner = self.partner_invoice_id
+ taxable_lines = self._avatax_prepare_lines(self.order_line)
+ tax_result = avatax_config.create_transaction(
+ self.date_order,
+ self.name,
+ doc_type,
+ partner,
+ self.warehouse_id.partner_id or self.company_id.partner_id,
+ self.tax_address_id or self.partner_id,
+ taxable_lines,
+ self.user_id,
+ self.exemption_code or None,
+ self.exemption_code_id.code or None,
+ currency_id=self.currency_id,
+ log_to_record=self,
+ )
+ tax_result_lines = {int(x["lineNumber"]): x for x in tax_result["lines"]}
+ for line in self.order_line:
+ tax_result_line = tax_result_lines.get(line.id)
+ if tax_result_line:
+ # Should we check the rate with the tax amount?
+ # tax_amount = tax_result_line["taxCalculated"]
+ # rate = round(tax_amount / line.price_subtotal * 100, 2)
+ rate = tax_result_line["rate"]
+ tax = Tax.get_avalara_tax(rate, doc_type)
+ if tax not in line.tax_id:
+ line_taxes = (
+ tax
+ if avatax_config.override_line_taxes
+ else tax | line.tax_id.filtered(lambda x: not x.is_avatax)
+ )
+ line.tax_id = line_taxes
+ line.tax_amt = tax_result_line["tax"]
+ self.tax_amount = tax_result.get("totalTax")
+ return True
+
+ def avalara_compute_taxes(self):
+ """
+ Use Avatax API to compute taxes.
+ Sets the Taxes on each line, and lets odoo perfomr teh calculations.
+ """
+ for order in self:
+ if order.fiscal_position_id.is_avatax:
+ order._avatax_compute_tax()
+ return True
+
+ def action_confirm(self):
+ avatax_config = self.company_id.get_avatax_config_company()
+ if avatax_config and avatax_config.force_address_validation:
+ for addr in [self.partner_id, self.partner_shipping_id]:
+ if not addr.date_validation:
+ # The Confirm action will be interrupted
+ # if the address is not validated
+ return addr.button_avatax_validate_address()
+ if avatax_config:
+ self.avalara_compute_taxes()
+ res = super(SaleOrder, self).action_confirm()
+ return res
+
+ @api.onchange(
+ "order_line",
+ "tax_on_shipping_address",
+ "tax_address_id",
+ "partner_id",
+ )
+ def onchange_avatax_calculation(self):
+ avatax_config = self.env.company.get_avatax_config_company()
+ self.calculate_tax_on_save = False
+ if avatax_config.sale_calculate_tax:
+ if (
+ self._origin.tax_address_id.street != self.tax_address_id.street
+ or self._origin.partner_id != self.partner_id
+ or self._origin.tax_on_shipping_address != self.tax_on_shipping_address
+ ):
+ self.calculate_tax_on_save = True
+ return
+ for line in self.order_line:
+ if (
+ line._origin.product_uom_qty != line.product_uom_qty
+ or line._origin.discount != line.discount
+ or line._origin.price_unit != line.price_unit
+ or line._origin.warehouse_id != line.warehouse_id
+ ):
+ self.calculate_tax_on_save = True
+ break
+
+ @api.model
+ def create(self, vals):
+ record = super(SaleOrder, self).create(vals)
+ avatax_config = self.env.company.get_avatax_config_company()
+ if (
+ avatax_config.sale_calculate_tax
+ and record.calculate_tax_on_save
+ and not self._context.get("skip_second_write", False)
+ ):
+ record.with_context(skip_second_write=True).write(
+ {
+ "calculate_tax_on_save": False,
+ }
+ )
+ record.avalara_compute_taxes()
+ return record
+
+ def write(self, vals):
+ result = super(SaleOrder, self).write(vals)
+ avatax_config = self.env.company.get_avatax_config_company()
+ for record in self:
+ if (
+ avatax_config.sale_calculate_tax
+ and record.calculate_tax_on_save
+ and record.state != "done"
+ and not self._context.get("skip_second_write", False)
+ ):
+ record.with_context(skip_second_write=True).write(
+ {
+ "calculate_tax_on_save": False,
+ }
+ )
+ record.avalara_compute_taxes()
+ return result
+
+
+class SaleOrderLine(models.Model):
+ _inherit = "sale.order.line"
+
+ tax_amt = fields.Monetary(string="AvaTax")
+
+ def _avatax_prepare_line(self, sign=1, doc_type=None):
+ """
+ Prepare a line to use for Avatax computation.
+ Returns a dict
+ """
+ line = self
+ res = {}
+ # Add UPC to product item code
+ avatax_config = line.company_id.get_avatax_config_company()
+ product = line.product_id
+ if product.barcode and avatax_config.upc_enable:
+ item_code = "UPC:%d" % product.barcode
+ else:
+ item_code = product.default_code or ("ID:%d" % product.id)
+ tax_code = line.product_id.applicable_tax_code_id.name
+ amount = (
+ sign * line.price_unit * line.product_uom_qty * (1 - line.discount / 100.0)
+ )
+ # Calculate discount amount
+ discount_amount = 0.0
+ is_discounted = False
+ if line.discount:
+ discount_amount = (
+ sign * line.price_unit * line.product_uom_qty * line.discount / 100.0
+ )
+ is_discounted = True
+ res = {
+ "qty": line.product_uom_qty,
+ "itemcode": item_code,
+ "description": line.name,
+ "discounted": is_discounted,
+ "discount": discount_amount,
+ "amount": amount,
+ "tax_code": tax_code,
+ "id": line,
+ "tax_id": line.tax_id,
+ }
+ return res
+
+ @api.onchange("product_uom_qty", "discount", "price_unit", "tax_id")
+ def onchange_reset_avatax_amount(self):
+ """
+ When changing quantities or prices, reset the Avatax computed amount.
+ The Odoo computed tax amount will then be shown, as a reference.
+ The Avatax amount will be recomputed upon document validation.
+ """
+ for line in self:
+ line.tax_amt = 0
+ line.order_id.tax_amount = 0
+
+ @api.depends("product_uom_qty", "discount", "price_unit", "tax_id", "tax_amt")
+ def _compute_amount(self):
+ """
+ If we have a Avatax computed amount, use it instead of the Odoo computed one
+ """
+ res = super()._compute_amount()
+ for line in self:
+ if line.tax_amt: # Has Avatax computed amount
+ vals = {
+ "price_tax": line.tax_amt,
+ "price_total": line.price_subtotal + line.tax_amt,
+ }
+ line.update(vals)
+ return res
diff --git a/account_avatax_sale_oca/readme/CONTRIBUTORS.rst b/account_avatax_sale_oca/readme/CONTRIBUTORS.rst
new file mode 100644
index 000000000..329425fba
--- /dev/null
+++ b/account_avatax_sale_oca/readme/CONTRIBUTORS.rst
@@ -0,0 +1,17 @@
+* Odoo SA
+
+ * Fabrice Henrion
+
+* Open Source Integrators (https://opensourceintegrators.com)
+
+ * Daniel Reis
+ * Bhavesh Odedra
+ * Sandip Mangukiya
+
+* Serpent CS
+
+ * Murtuza Saleh
+
+* Sodexis
+
+ * Atchuthan Ubendran
diff --git a/account_avatax_sale_oca/readme/DESCRIPTION.rst b/account_avatax_sale_oca/readme/DESCRIPTION.rst
new file mode 100644
index 000000000..b9f7adc12
--- /dev/null
+++ b/account_avatax_sale_oca/readme/DESCRIPTION.rst
@@ -0,0 +1,2 @@
+This module is a component of the Avatax Integration with odoo app.
+Please refer to the corresponding documentation.
diff --git a/account_avatax_sale_oca/readme/USAGE.rst b/account_avatax_sale_oca/readme/USAGE.rst
new file mode 100644
index 000000000..a59537c3a
--- /dev/null
+++ b/account_avatax_sale_oca/readme/USAGE.rst
@@ -0,0 +1,58 @@
+The AvaTax module is integrated into Sales Orders and allows computation of taxes.
+Sales order transactions do not appear in the in the AvaTax interface.
+
+The information placed in the sales order will automatically pass to the invoice
+on the Avalara server and can be viewed in the AvaTax control panel.
+
+Discounts are handled when they are enabled in Odoo's settings.
+They will be reported as a net deduction on the line item cost.
+
+Create New Sales Order
+
+- Navigate to: Sales >> Orders >> Orders
+
+- Click Create button
+
+Compute Taxes with AvaTax
+
+- The module will calculate tax when the sales order is confirmed,
+ or by navigating to Action >> Update taxes with Avatax.
+ At this step, the sales order will retrieve the tax amount from Avalara
+ but will not report the transaction to the AvaTax dashboard.
+ Only invoice, refund, and payment activity are reported to the dashboard.
+
+- The module will check if there is a selected warehouse
+ and will automatically determine the address of the warehouse
+ and the origin location. If no address is assigned to the warehouse
+ the module will automatically use the address of the company as its origin.
+ Location code will automatically populate with the warehouse code
+ but can be modified if needed.
+
+- Hide Exemption & Tax Based on shipping address -- this will provide this
+ feature support at sale order level.
+
+
+Tax Exemption Status
+
+- Tax exemption status can be defined on Contacts.
+
+- In a multi-company environment, the exemption status is defined per
+ Company, since each individual company is required to secure the
+ exemption certificates to claim for exemption application,
+ and this may not be the case for all Companies.
+
+- If the customer is tax exempt, in the "Avatax" tab, check the "Is Tax Exempt" checkbox.
+ When checked, the exemption details can be provided.
+ The Exemption Code is the type of exemption,
+ and the Exemption Number is an identification number to use on the customer's State.
+
+- This exemption status will only be applied for delivery addresses
+ in the State matching the State of the exemption address.
+ The same customer can have exemptiions on several states.
+ For this use additional Contact/Addresses for those states,
+ and enter the exempention details there.
+
+- To make this data management simpler, is it possible to set the customer as exempt
+ country wide, using the corresponding checkbox. In this case the exemption status will
+ be used for delivery addresses in any state. Using this option has compliance risks, so
+ plase use it with care.
diff --git a/account_avatax_sale_oca/static/description/icon.png b/account_avatax_sale_oca/static/description/icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d
GIT binary patch
literal 9455
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
z
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
Xviia!U7SGha1wx#SCgwmn*{w2TRX*I
literal 0
HcmV?d00001
diff --git a/account_avatax_sale_oca/static/description/index.html b/account_avatax_sale_oca/static/description/index.html
new file mode 100644
index 000000000..84576c500
--- /dev/null
+++ b/account_avatax_sale_oca/static/description/index.html
@@ -0,0 +1,493 @@
+
+
+
+
+
+
+Avalara Avatax Connector for Sales Orders
+
+
+
+
+
Avalara Avatax Connector for Sales Orders
+
+
+
+
This module is a component of the Avatax Integration with odoo app.
+Please refer to the corresponding documentation.
The AvaTax module is integrated into Sales Orders and allows computation of taxes.
+Sales order transactions do not appear in the in the AvaTax interface.
+
The information placed in the sales order will automatically pass to the invoice
+on the Avalara server and can be viewed in the AvaTax control panel.
+
Discounts are handled when they are enabled in Odoo’s settings.
+They will be reported as a net deduction on the line item cost.
+
Create New Sales Order
+
+
Navigate to: Sales >> Orders >> Orders
+
Click Create button
+
+
Compute Taxes with AvaTax
+
+
The module will calculate tax when the sales order is confirmed,
+or by navigating to Action >> Update taxes with Avatax.
+At this step, the sales order will retrieve the tax amount from Avalara
+but will not report the transaction to the AvaTax dashboard.
+Only invoice, refund, and payment activity are reported to the dashboard.
+
The module will check if there is a selected warehouse
+and will automatically determine the address of the warehouse
+and the origin location. If no address is assigned to the warehouse
+the module will automatically use the address of the company as its origin.
+Location code will automatically populate with the warehouse code
+but can be modified if needed.
+
Hide Exemption & Tax Based on shipping address – this will provide this
+feature support at sale order level.
+
+
Tax Exemption Status
+
+
Tax exemption status can be defined on Contacts.
+
In a multi-company environment, the exemption status is defined per
+Company, since each individual company is required to secure the
+exemption certificates to claim for exemption application,
+and this may not be the case for all Companies.
+
If the customer is tax exempt, in the “Avatax” tab, check the “Is Tax Exempt” checkbox.
+When checked, the exemption details can be provided.
+The Exemption Code is the type of exemption,
+and the Exemption Number is an identification number to use on the customer’s State.
+
This exemption status will only be applied for delivery addresses
+in the State matching the State of the exemption address.
+The same customer can have exemptiions on several states.
+For this use additional Contact/Addresses for those states,
+and enter the exempention details there.
+
To make this data management simpler, is it possible to set the customer as exempt
+country wide, using the corresponding checkbox. In this case the exemption status will
+be used for delivery addresses in any state. Using this option has compliance risks, so
+plase use it with care.
Bugs are tracked on GitHub Issues.
+In case of trouble, please check there if your issue has already been reported.
+If you spotted it first, help us smashing it by providing a detailed and welcomed
+feedback.
+
Do not contact contributors directly about support or help with technical issues.
OCA, or the Odoo Community Association, is a nonprofit organization whose
+mission is to support the collaborative development of Odoo features and
+promote its widespread use.
Bugs are tracked on GitHub Issues.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed
-feedback.
Bugs are tracked on GitHub Issues.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed
-feedback.
From 98ef61c825ff83dc035176fa64658391fbb46902 Mon Sep 17 00:00:00 2001
From: OCA-git-bot
Date: Sun, 3 Sep 2023 11:24:48 +0000
Subject: [PATCH 09/27] README.rst
---
account_avatax_sale_oca/README.rst | 15 ++++---
.../static/description/index.html | 40 ++++++++++---------
2 files changed, 30 insertions(+), 25 deletions(-)
diff --git a/account_avatax_sale_oca/README.rst b/account_avatax_sale_oca/README.rst
index 294c51455..fdd3411b1 100644
--- a/account_avatax_sale_oca/README.rst
+++ b/account_avatax_sale_oca/README.rst
@@ -2,10 +2,13 @@
Avalara Avatax Certified Connector for Sales Orders
===================================================
-.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+..
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ !! source digest: sha256:deb5a86c145b7ec5fb11b27a7368510d972eec33d9a2682e1330961cd2f52a0e
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png
:target: https://odoo-community.org/page/development-status
@@ -19,11 +22,11 @@ Avalara Avatax Certified Connector for Sales Orders
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/account-fiscal-rule-16-0/account-fiscal-rule-16-0-account_avatax_sale_oca
:alt: Translate me on Weblate
-.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
- :target: https://runbot.odoo-community.org/runbot/93/16.0
- :alt: Try me on Runbot
+.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
+ :target: https://runboat.odoo-community.org/builds?repo=OCA/account-fiscal-rule&target_branch=16.0
+ :alt: Try me on Runboat
-|badge1| |badge2| |badge3| |badge4| |badge5|
+|badge1| |badge2| |badge3| |badge4| |badge5|
This module is a component of the Avatax Integration with odoo app.
Please refer to the corresponding documentation.
@@ -100,7 +103,7 @@ Bug Tracker
Bugs are tracked on `GitHub Issues `_.
In case of trouble, please check there if your issue has already been reported.
-If you spotted it first, help us smashing it by providing a detailed and welcomed
+If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback `_.
Do not contact contributors directly about support or help with technical issues.
diff --git a/account_avatax_sale_oca/static/description/index.html b/account_avatax_sale_oca/static/description/index.html
index 8a54bf14a..491e7751e 100644
--- a/account_avatax_sale_oca/static/description/index.html
+++ b/account_avatax_sale_oca/static/description/index.html
@@ -1,20 +1,20 @@
-
+
-
+
Avalara Avatax Certified Connector for Sales Orders