diff --git a/contract_sii/README.rst b/contract_sii/README.rst new file mode 100644 index 000000000..234bd9b27 --- /dev/null +++ b/contract_sii/README.rst @@ -0,0 +1,63 @@ +============ +Contract SII +============ + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:929437dbe6ec8ac86dd85522942ceaf5f646cc1e64ed2d17a910fa300548f822 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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-NuoBiT%2Fodoo--addons-lightgray.png?logo=github + :target: https://github.com/NuoBiT/odoo-addons/tree/18.0/contract_sii + :alt: NuoBiT/odoo-addons + +|badge1| |badge2| |badge3| + +This module adds SII data to contracts and propagate them to invoice + +**Table of contents** + +.. contents:: + :local: + +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 to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* NuoBiT Solutions SL + +Contributors +------------ + +- `NuoBiT `__: + + - Eric Antones eantones@nuobit.com + - Deniz Gallo dgallo@nuobit.com + +Maintainers +----------- + +This module is part of the `NuoBiT/odoo-addons `_ project on GitHub. + +You are welcome to contribute. diff --git a/contract_sii/__init__.py b/contract_sii/__init__.py new file mode 100644 index 000000000..0650744f6 --- /dev/null +++ b/contract_sii/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/contract_sii/__manifest__.py b/contract_sii/__manifest__.py new file mode 100644 index 000000000..a287cd53e --- /dev/null +++ b/contract_sii/__manifest__.py @@ -0,0 +1,20 @@ +# Copyright NuoBiT Solutions SL - Eric Antones +# Copyright 2025 NuoBiT Solutions SL - Deniz Gallo +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + +{ + "name": "Contract SII", + "summary": "This module adds SII data to contracts and propagate them to invoice", + "version": "18.0.1.0.0", + "category": "Contract Management", + "author": "NuoBiT Solutions SL", + "website": "https://github.com/NuoBiT/odoo-addons", + "license": "AGPL-3", + "depends": [ + "contract", + "l10n_es_aeat_sii_oca", + ], + "data": [ + "views/contract_view.xml", + ], +} diff --git a/contract_sii/i18n/es.po b/contract_sii/i18n/es.po new file mode 100644 index 000000000..6296c9b42 --- /dev/null +++ b/contract_sii/i18n/es.po @@ -0,0 +1,103 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * contract_sii +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-01-21 13:58+0000\n" +"PO-Revision-Date: 2022-01-21 13:58+0000\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: contract_sii +#: model:ir.model.fields,field_description:contract_sii.field_contract_contract__sii_registration_key_additional2 +msgid "Additional 2 SII registration key" +msgstr "Clave de registro adicional 2 SII" + +#. module: contract_sii +#: model:ir.model.fields,field_description:contract_sii.field_contract_contract__sii_registration_key_additional1 +msgid "Additional SII registration key" +msgstr "Clave de registro adicional SII" + +#. module: contract_sii +#: model:ir.model,name:contract_sii.model_contract_contract +msgid "Contract" +msgstr "Contrato" + +#. module: contract_sii +#: model:ir.model.fields,field_description:contract_sii.field_contract_contract__display_name +msgid "Display Name" +msgstr "Nombre mostrado" + +#. module: contract_sii +#: model:ir.model.fields,field_description:contract_sii.field_contract_contract__sii_enabled +msgid "Enable SII" +msgstr "Activar SII" + +#. module: contract_sii +#: model:ir.model.fields,field_description:contract_sii.field_contract_contract__id +msgid "ID" +msgstr "" + +#. module: contract_sii +#: model:ir.model.fields,field_description:contract_sii.field_contract_contract____last_update +msgid "Last Modified on" +msgstr "Última Modificación en" + +#. module: contract_sii +#: model:ir.model.fields,field_description:contract_sii.field_contract_contract__sii_property_cadastrial_code +msgid "Real property cadastrial code" +msgstr "Referencia catastral" + +#. module: contract_sii +#: model:ir.model.fields,field_description:contract_sii.field_contract_contract__sii_property_location +msgid "Real property location" +msgstr "Situación del inmueble" + +#. module: contract_sii +#: model:ir.model.fields,field_description:contract_sii.field_contract_contract__sii_registration_key_code +msgid "SII Code" +msgstr "Código SII" + +#. module: contract_sii +#: model_terms:ir.ui.view,arch_db:contract_sii.contract_contract_sale_form +msgid "SII Information" +msgstr "Información SII" + +#. module: contract_sii +#: model:ir.model.fields,field_description:contract_sii.field_contract_contract__sii_registration_key +msgid "SII registration key" +msgstr "Clave de registro SII" + +#. module: contract_sii +#: model:ir.model.fields.selection,name:contract_sii.selection__contract_contract__sii_property_location__1 +msgid "" +"[1]-Real property with cadastral code located within the Spanish territory " +"except Basque Country or Navarra" +msgstr "" +"[1]-Inmueble con referencia catastral situado dentro del territorio Español " +"excepto el País Vasco y Navarra" + +#. module: contract_sii +#: model:ir.model.fields.selection,name:contract_sii.selection__contract_contract__sii_property_location__2 +msgid "[2]-Real property located in the Basque Country or Navarra" +msgstr "[2]-Inmueble situado en el País Vasco o Navarra" + +#. module: contract_sii +#: model:ir.model.fields.selection,name:contract_sii.selection__contract_contract__sii_property_location__3 +msgid "" +"[3]-Real property in any of the above situations but without cadastral code" +msgstr "" +"[3]-Inmueble situado en cualquiera de las ubicaciones anteriores pero sin " +"referencia catastral" + +#. module: contract_sii +#: model:ir.model.fields.selection,name:contract_sii.selection__contract_contract__sii_property_location__4 +msgid "[4]-Real property located in a foreign country" +msgstr "[4]-Inmueble situado en un país extranjero" diff --git a/contract_sii/models/__init__.py b/contract_sii/models/__init__.py new file mode 100644 index 000000000..99a5468ac --- /dev/null +++ b/contract_sii/models/__init__.py @@ -0,0 +1 @@ +from . import contract diff --git a/contract_sii/models/contract.py b/contract_sii/models/contract.py new file mode 100644 index 000000000..80edaf644 --- /dev/null +++ b/contract_sii/models/contract.py @@ -0,0 +1,96 @@ +# Copyright NuoBiT Solutions SL - Eric Antones +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + +from odoo import api, fields, models + + +class ContractContract(models.Model): + _inherit = "contract.contract" + + def _default_sii_registration_key(self): + sii_key_obj = self.env["aeat.sii.mapping.registration.keys"] + contract_type = self.env.context.get("default_contract_type") + key = sii_key_obj.search( + [("code", "=", "01"), ("type", "=", contract_type)], limit=1 + ) + return key + + sii_registration_key = fields.Many2one( + comodel_name="aeat.sii.mapping.registration.keys", + string="SII registration key", + default=_default_sii_registration_key, + ) + sii_registration_key_additional1 = fields.Many2one( + comodel_name="aeat.sii.mapping.registration.keys", + string="Additional SII registration key", + ) + sii_registration_key_additional2 = fields.Many2one( + comodel_name="aeat.sii.mapping.registration.keys", + string="Additional 2 SII registration key", + ) + sii_registration_key_code = fields.Char( + related="sii_registration_key.code", + readonly=True, + string="SII Code", + ) + sii_enabled = fields.Boolean( + string="Enable SII", + compute="_compute_sii_enabled", + ) + sii_property_location = fields.Selection( + string="Real property location", + copy=False, + selection=[ + ( + "1", + "[1]-Real property with cadastral code located within " + "the Spanish territory except Basque Country or Navarra", + ), + ("2", "[2]-Real property located in the " "Basque Country or Navarra"), + ( + "3", + "[3]-Real property in any of the above situations " + "but without cadastral code", + ), + ("4", "[4]-Real property located in a foreign country"), + ], + ) + sii_property_cadastrial_code = fields.Char( + string="Real property cadastrial code", + size=25, + copy=False, + ) + + @api.depends("company_id", "company_id.sii_enabled") + def _compute_sii_enabled(self): + for rec in self: + rec.sii_enabled = rec.company_id.sii_enabled + + def _prepare_invoice(self, date_invoice, journal=None): + self.ensure_one() + invoice_vals = super()._prepare_invoice(date_invoice, journal) + + values = {} + if self.sii_registration_key: + values["sii_registration_key"] = self.sii_registration_key.id + if self.sii_registration_key_additional1: + values["sii_registration_key_additional1"] = ( + self.sii_registration_key_additional1.id + ) + if self.sii_registration_key_additional2: + values["sii_registration_key_additional2"] = ( + self.sii_registration_key_additional2.id + ) + + if self.contract_type == "sale": + if self.sii_property_location: + values["sii_property_location"] = self.sii_property_location + if self.sii_property_cadastrial_code: + values["sii_property_cadastrial_code"] = ( + self.sii_property_cadastrial_code + ) + + if values: + invoice_vals.update(values) + + return invoice_vals diff --git a/contract_sii/pyproject.toml b/contract_sii/pyproject.toml new file mode 100644 index 000000000..4231d0ccc --- /dev/null +++ b/contract_sii/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/contract_sii/readme/CONTRIBUTORS.md b/contract_sii/readme/CONTRIBUTORS.md new file mode 100644 index 000000000..909507cba --- /dev/null +++ b/contract_sii/readme/CONTRIBUTORS.md @@ -0,0 +1,3 @@ +- [NuoBiT](https://www.nuobit.com): + - Eric Antones + - Deniz Gallo diff --git a/contract_sii/readme/DESCRIPTION.md b/contract_sii/readme/DESCRIPTION.md new file mode 100644 index 000000000..94765dcf6 --- /dev/null +++ b/contract_sii/readme/DESCRIPTION.md @@ -0,0 +1 @@ +This module adds SII data to contracts and propagate them to invoice diff --git a/contract_sii/static/description/icon.png b/contract_sii/static/description/icon.png new file mode 100644 index 000000000..1cd641e79 Binary files /dev/null and b/contract_sii/static/description/icon.png differ diff --git a/contract_sii/static/description/index.html b/contract_sii/static/description/index.html new file mode 100644 index 000000000..ec5e85660 --- /dev/null +++ b/contract_sii/static/description/index.html @@ -0,0 +1,420 @@ + + + + + +Contract SII + + + +
+

Contract SII

+ + +

Beta License: AGPL-3 NuoBiT/odoo-addons

+

This module adds SII data to contracts and propagate them to invoice

+

Table of contents

+ +
+

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 to smash it by providing a detailed and welcomed +feedback.

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • NuoBiT Solutions SL
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is part of the NuoBiT/odoo-addons project on GitHub.

+

You are welcome to contribute.

+
+
+
+ + diff --git a/contract_sii/tests/__init__.py b/contract_sii/tests/__init__.py new file mode 100644 index 000000000..4f96d644b --- /dev/null +++ b/contract_sii/tests/__init__.py @@ -0,0 +1 @@ +from . import test_contract_sii diff --git a/contract_sii/tests/test_contract_sii.py b/contract_sii/tests/test_contract_sii.py new file mode 100644 index 000000000..d06458e37 --- /dev/null +++ b/contract_sii/tests/test_contract_sii.py @@ -0,0 +1,147 @@ +from odoo.tests import Form + +from odoo.addons.contract.tests.test_contract import TestContractBase + + +class TestContractSii(TestContractBase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.company_model = cls.env["res.company"] + cls.contract_model = cls.env["contract.contract"] + cls.aml_model = cls.env["account.move.line"] + # cls.registration_keys_model = cls.env.["aeat.sii.mapping.registration.keys"] + cls.env.company.write( + { + "sii_enabled": True, + "sii_test": True, + } + ) + + def test_contract_sale_sii(self): + contract_sale_form = Form( + self.contract_model.with_context( + is_contract=True, default_contract_type="sale" + ) + ) + contract_sale_form.name = "Test Contract" + contract_sale_form.partner_id = self.partner + contract_sale_form.pricelist_id = self.partner.property_product_pricelist + contract_sale_form.recurring_interval = 1 + contract_sale_form.recurring_rule_type = "monthly" + sale12_key = self.env.ref( + "l10n_es_aeat_sii_oca.aeat_sii_mapping_registration_keys_12" + ) + contract_sale_form.sii_registration_key = sale12_key + contract_sale_form.sii_registration_key_additional1 = sale12_key + contract_sale_form.sii_registration_key_additional2 = sale12_key + contract_sale_form.sii_property_cadastrial_code = "12345" + contract_sale_form.sii_property_location = "1" + contract_sale_form.line_recurrence = True + line_form = contract_sale_form.contract_line_ids.new() + line_form.product_id = self.product_1 + line_form.name = "Services from #START# to #END#" + line_form.quantity = 1 + line_form.price_unit = 100 + line_form.discount = 50 + line_form.recurring_rule_type = "monthly" + line_form.recurring_interval = 1 + line_form.date_start = "2018-02-15" + line_form.recurring_next_date = "2018-02-22" + line_form.save() + self.contract_sale_ssi = contract_sale_form.save() + self.contract_sale_ssi._compute_recurring_next_date() + self.contract_sale_ssi.recurring_create_invoice() + invoices = self.aml_model.search( + [ + ( + "contract_line_id", + "in", + self.contract_sale_ssi.contract_line_ids.ids, + ) + ] + ).mapped("move_id") + self.assertEqual( + invoices.mapped("sii_registration_key").ids, + self.contract_sale_ssi.sii_registration_key.ids, + ) + self.assertEqual( + invoices.mapped("sii_registration_key_additional1").ids, + self.contract_sale_ssi.sii_registration_key_additional1.ids, + ) + self.assertEqual( + invoices.mapped("sii_registration_key_additional2").ids, + self.contract_sale_ssi.sii_registration_key_additional2.ids, + ) + self.assertEqual( + invoices.mapped("sii_property_location")[0], + self.contract_sale_ssi.sii_property_location, + ) + self.assertEqual( + invoices.mapped("sii_property_cadastrial_code")[0], + self.contract_sale_ssi.sii_property_cadastrial_code, + ) + + def test_contract_purchase_sii(self): + contract_purchase_form = Form( + self.contract_model.with_context( + is_contract=True, default_contract_type="purchase" + ) + ) + + journal = self.env["account.journal"].create( + { + "name": "Test Purchase Journal", + "code": "TPJ", + "type": "purchase", + "company_id": self.env.company.id, + } + ) + + contract_purchase_form.name = "Test Contract" + contract_purchase_form.partner_id = self.partner + contract_purchase_form.pricelist_id = self.partner.property_product_pricelist + sale01_key = self.env.ref( + "l10n_es_aeat_sii_oca.aeat_sii_mapping_registration_keys_01" + ) + contract_purchase_form.sii_registration_key = sale01_key + contract_purchase_form.sii_registration_key_additional1 = sale01_key + contract_purchase_form.sii_registration_key_additional2 = sale01_key + contract_purchase_form.recurring_rule_type = "monthly" + contract_purchase_form.journal_id = journal + contract_purchase_form.line_recurrence = True + line_form = contract_purchase_form.contract_line_ids.new() + line_form.product_id = self.product_1 + line_form.name = "Services from #START# to #END#" + line_form.quantity = 1 + line_form.price_unit = 100 + line_form.discount = 50 + line_form.recurring_rule_type = "monthly" + line_form.recurring_interval = 1 + line_form.date_start = "2018-02-15" + line_form.recurring_next_date = "2018-02-22" + line_form.save() + self.contract_purchase_ssi = contract_purchase_form.save() + self.contract_purchase_ssi._compute_recurring_next_date() + self.contract_purchase_ssi.recurring_create_invoice() + invoices = self.aml_model.search( + [ + ( + "contract_line_id", + "in", + self.contract_purchase_ssi.contract_line_ids.ids, + ) + ] + ).mapped("move_id") + self.assertEqual( + invoices.mapped("sii_registration_key").ids, + self.contract_purchase_ssi.sii_registration_key.ids, + ) + self.assertEqual( + invoices.mapped("sii_registration_key_additional1").ids, + self.contract_purchase_ssi.sii_registration_key_additional1.ids, + ) + self.assertEqual( + invoices.mapped("sii_registration_key_additional2").ids, + self.contract_purchase_ssi.sii_registration_key_additional2.ids, + ) diff --git a/contract_sii/views/contract_view.xml b/contract_sii/views/contract_view.xml new file mode 100644 index 000000000..bc2a99895 --- /dev/null +++ b/contract_sii/views/contract_view.xml @@ -0,0 +1,51 @@ + + + + + contract.contract + + + + + + + + + + + + + + + + + + + +