Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 130 additions & 0 deletions account_avatax_exemption_sign_oca/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
=========================================
Avatax Exemptions with Sign OCA extension
=========================================

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:f3682879bd1520d85dbb7569fe61b8351e194999efd99778dabc747fe53fed7c
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |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/18.0/account_avatax_exemption_sign_oca
: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-18-0/account-fiscal-rule-18-0-account_avatax_exemption_sign_oca
:alt: Translate me on Weblate
.. |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=18.0
:alt: Try me on Runboat

|badge1| |badge2| |badge3| |badge4| |badge5|

This module connects between account avatax exemption and sign oca
modules.

**Table of contents**

.. contents::
:local:

Configuration
=============

1. Go to Invoicing > Configuration > Exemption Type:

- Create a new type and preferred to select a state
- If you don't see states to choose make sure to check
``Avatax Nexus`` field for some states.

2. Go to Sign > Templates:

- Create a new template and check the field ``Is Exemption`` and
choose the exemption type you created.
- Configure the template and make sure to add
``Tax Exemption Number`` item.

Usage
=====

Once you create a sign request for exemption template form, a new
exemption record will be created for the partner whose role in sign
template is ``Customer`` or any role who is ought to fill
``Tax Exemption Number`` item in sign request.

If exemption configurations are all set and specifically ``States`` or
``Group of States`` then a new exemption line will be ceated with the
new exemption itself.

If you fill the ``Tax Exemption Number`` item in sign request its value
will be populated to the new created records of exemption.

From sign request form you can open related exemptions through a smart
button on the top right corner.

Also, from the exemption view, may be through the partner's view you can
open the related sign request thourgh its relational field in the
exemption form view.

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/OCA/account-fiscal-rule/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/OCA/account-fiscal-rule/issues/new?body=module:%20account_avatax_exemption_sign_oca%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.

Do not contact contributors directly about support or help with technical issues.

Credits
=======

Authors
-------

* Kencove
* ForgeFlow

Contributors
------------

- ForgeFlow (https://www.forgeflow.com)

- ArnauCForgeFlow <[email protected]>
- BernatPForgeFlow <[email protected]>
- AlexPForgeFlow <[email protected]>

- Kencove (https://kencove.com)

- Don Kendall <[email protected]>
- Mohamed Alkobrosli <[email protected]>
- Wai-Lun Lin <[email protected]>

- Trobz (https://trobz.com)

- Do Anh Duy <[email protected]>

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.

This module is part of the `OCA/account-fiscal-rule <https://github.com/OCA/account-fiscal-rule/tree/18.0/account_avatax_exemption_sign_oca>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
1 change: 1 addition & 0 deletions account_avatax_exemption_sign_oca/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import models
30 changes: 30 additions & 0 deletions account_avatax_exemption_sign_oca/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Copyright 2023 ForgeFlow S.L. (http://www.forgeflow.com)
# Copyright 2025 Kencove (https://www.kencove.com).
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).

{
"name": "Avatax Exemptions with Sign OCA extension",
"version": "18.0.1.0.0",
"category": "Sales",
"summary": """
This application allows you to add Avatax exemptions with Sign OCA module
""",
"website": "https://github.com/OCA/account-fiscal-rule",
"author": "Kencove, ForgeFlow, Odoo Community Association (OCA)",
"license": "AGPL-3",
"depends": [
"account_avatax_oca",
"account_avatax_sale_oca",
"account_avatax_exemption_base",
"account_avatax_exemption",
"sign_oca",
],
"data": [
"data/data.xml",
"views/sign_oca_template.xml",
"views/sign_oca_request.xml",
"views/exemption_views.xml",
],
"installable": True,
"application": False,
}
8 changes: 8 additions & 0 deletions account_avatax_exemption_sign_oca/data/data.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="sign_field_text" model="sign.oca.field">
<field name="name">Tax Exemption Number</field>
<field name="field_type">text</field>
<field name="is_exemption_number">True</field>
</record>
</odoo>
5 changes: 5 additions & 0 deletions account_avatax_exemption_sign_oca/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from . import avalara_salestax
from . import exemption
from . import sign_oca_field
from . import sign_oca_request
from . import sign_oca_template
22 changes: 22 additions & 0 deletions account_avatax_exemption_sign_oca/models/avalara_salestax.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Copyright 2023 ForgeFlow S.L. (http://www.forgeflow.com)
# Copyright 2025 Kencove (https://www.kencove.com).
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).

from odoo import models


class AvalaraSalestax(models.Model):
_inherit = "avalara.salestax"

def link_certificates_to_customer(self, exemption_line):
res = super().link_certificates_to_customer(exemption_line=exemption_line)
if all(
exemption_line.exemption_id.exemption_line_ids.mapped("linked_to_customer")
):
if exemption_line.exemption_id.sign_oca_request_id:
exemption_line.exemption_id.sign_oca_request_id.write(
{
"is_exemption_synchronized": True,
}
)
return res
64 changes: 64 additions & 0 deletions account_avatax_exemption_sign_oca/models/exemption.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Copyright 2023 ForgeFlow S.L. (http://www.forgeflow.com)
# Copyright 2025 Kencove (https://www.kencove.com).
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).

from datetime import timedelta

from odoo import api, fields, models


class ResPartnerExemption(models.Model):
_inherit = "res.partner.exemption"

sign_oca_request_id = fields.Many2one("sign.oca.request")

def write(self, vals):
if vals.get("state") == "cancel":
for record in self:
record.sign_oca_request_id.cancel()
return super().write(vals)

def _rebuild_state_ids(self):
self.business_type = self.exemption_type.business_type.id
if self.exemption_type.group_of_state and not self.group_of_state:
self.group_of_state = self.exemption_type.group_of_state.id
if self.exemption_type or self.group_of_state:
state_ids = []
if self.exemption_type.group_of_state.state_ids:
state_ids += self.exemption_type.group_of_state.state_ids.ids
if self.exemption_type.state_ids:
state_ids += self.exemption_type.state_ids.ids
if self.group_of_state.state_ids:
state_ids += self.group_of_state.state_ids.ids
self.state_ids = [(6, 0, list(set(state_ids)))]

def _rebuild_expiry_date(self):
if self.exemption_type.exemption_validity_duration and self.effective_date:
self.expiry_date = self.effective_date + timedelta(
days=self.exemption_type.exemption_validity_duration
)

def _rebuild_exemption_lines(self):
self.ensure_one()
if not any(self.exemption_line_ids.mapped("avatax_id")) and not any(
self.exemption_line_ids.mapped("add_exemption_number")
):
self.exemption_line_ids.unlink()

existing_state_ids = self.exemption_line_ids.mapped("state_id").ids
for state_id in self.state_ids.ids:
if state_id not in existing_state_ids:
self.env["res.partner.exemption.line"].create(
{
"partner_id": self.partner_id.id,
"exemption_id": self.id,
"state_id": state_id,
"avatax_status": True,
}
)

@api.depends("state")
def _cancel_sign_request_id(self):
for rec in self:
if rec.state == "cancel":
rec.sign_oca_request_id.cancel()
11 changes: 11 additions & 0 deletions account_avatax_exemption_sign_oca/models/sign_oca_field.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Copyright 2023 ForgeFlow S.L. (http://www.forgeflow.com)
# Copyright 2025 Kencove (https://www.kencove.com).
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).

from odoo import fields, models


class SignOcaField(models.Model):
_inherit = "sign.oca.field"

is_exemption_number = fields.Boolean()
91 changes: 91 additions & 0 deletions account_avatax_exemption_sign_oca/models/sign_oca_request.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# Copyright 2023 ForgeFlow S.L. (http://www.forgeflow.com)
# Copyright 2025 Kencove (https://www.kencove.com).
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).

from odoo import fields, models


class SignOcaRequest(models.Model):
_inherit = "sign.oca.request"

is_exemption = fields.Boolean(related="template_id.is_exemption")
is_exemption_synchronized = fields.Boolean(
string="Exemption synchronized with AvaTax?", copy=False
)
exemption_ids = fields.One2many(
comodel_name="res.partner.exemption",
inverse_name="sign_oca_request_id",
string="Exemptions",
)

def _get_partner_id(self):
role_customer = self.env.ref("sign_oca.sign_role_customer")
customer_signers = self.signer_ids.filtered(
lambda x: x.role_id == role_customer
).partner_id
return customer_signers[0] if customer_signers else None

def _prepare_exemption_data(self):
avalara_salestax = (
self.env["avalara.salestax"]
.sudo()
.search([("exemption_export", "=", True)], limit=1)
)
use_commercial_entity = avalara_salestax.use_commercial_entity
data = {
"exemption_type": self.template_id.exemption_type.id,
"sign_oca_request_id": self.id,
}
exemption_number_field_id = (
self.template_id.item_ids.mapped("field_id")
.filtered("is_exemption_number")
.ids
)
# In case role is customer and not expression
partner_id = self._get_partner_id()
if exemption_number_field_id:
for item_id in self.signatory_data:
item = self.signatory_data[item_id]
if item["field_id"] == exemption_number_field_id[0]:
data["exemption_number"] = item["value"]
if not partner_id:
# In case role not customer and likely expression or any other
exemption_signer = self.signer_ids.filtered(
lambda signer, item: signer.role_id.id == item["role_id"]
)
partner_id = exemption_signer.partner_id
break
if partner_id:
data["partner_id"] = (
partner_id.commercial_partner_id.id
if use_commercial_entity
else partner_id.id
)
return data

def _check_signed(self):
res = super()._check_signed()
if self.state == "2_signed" and self.is_exemption:
exemption_data = self._prepare_exemption_data()
exemption = self.env["res.partner.exemption"].create(exemption_data)
exemption._rebuild_state_ids()
exemption._rebuild_expiry_date()
exemption._rebuild_exemption_lines()
if exemption.exemption_number and exemption.exemption_line_ids:
exemption.exemption_line_ids.write(
{
"add_exemption_number": True,
"exemption_number": exemption.exemption_number,
}
)
return res

def open_exemptions(self):
self.ensure_one()
return {
"name": "Exemptions",
"type": "ir.actions.act_window",
"res_model": "res.partner.exemption",
"view_mode": "list,form",
"domain": [("sign_oca_request_id", "=", self.id)],
}
12 changes: 12 additions & 0 deletions account_avatax_exemption_sign_oca/models/sign_oca_template.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Copyright 2023 ForgeFlow S.L. (http://www.forgeflow.com)
# Copyright 2025 Kencove (https://www.kencove.com).
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).

from odoo import fields, models


class SignOcaTemplate(models.Model):
_inherit = "sign.oca.template"

is_exemption = fields.Boolean(copy=False)
exemption_type = fields.Many2one("res.partner.exemption.type", copy=False)
3 changes: 3 additions & 0 deletions account_avatax_exemption_sign_oca/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[build-system]
requires = ["whool"]
build-backend = "whool.buildapi"
9 changes: 9 additions & 0 deletions account_avatax_exemption_sign_oca/readme/CONFIGURE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
1. Go to Invoicing \> Configuration \> Exemption Type:

- Create a new type and preferred to select a state
- If you don't see states to choose make sure to check `Avatax Nexus` field for some states.

2. Go to Sign \> Templates:

- Create a new template and check the field `Is Exemption` and choose the exemption type you created.
- Configure the template and make sure to add `Tax Exemption Number` item.
Loading