diff --git a/sale_order_sign_oca/README.rst b/sale_order_sign_oca/README.rst new file mode 100644 index 00000000..4886e014 --- /dev/null +++ b/sale_order_sign_oca/README.rst @@ -0,0 +1,129 @@ +=================== +Sale Order Sign Oca +=================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:8eed166d2b22be5ca399810f57661fccd2fdab9ff6db9c5e3a77882a25bd9d02 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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%2Fsign-lightgray.png?logo=github + :target: https://github.com/OCA/sign/tree/14.0/sale_order_sign_oca + :alt: OCA/sign +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/sign-14-0/sign-14-0-sale_order_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/sign&target_branch=14.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module allows you to generate manual and automatic signature +requests from sale order to customers. + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +#. Go to Sign > Roles and create a role with the following data: + +- Partner type: Expression +- Expression: ${object.partner_id.id} + +#. Go to Sign > Templates and create a template with the following data: + +- Model: Sale Order +- In one of the fields, you must set the previously created role. + +#. Go to Sales > Configuration > Settings. + +- In the Sale Order Sign section, mark the field Sale Order Sign + Template, define the template that will be used to generate the sales + order sign request. +- Use the template previously created. +- And choose the state in which this will happen. + +Usage +===== + +Creating a Signature Request from a Sale Order: + +- Go to Sales > Quotations. +- Open an existing quotation or create a new one (make sure to fill in + the ``partner_id`` field). +- In the sale order form view, click on the action "Sign from + template". +- Sign Requests will have been generated (and sent) linked to the + selected project and task. + +Automatic Signature Request creation: + +- Define a template in Sale > Configuration > Settings. +- When an customer is assigned to a sale order, a Sign Request will be + created (and sent) automatically. + +Viewing Signature Requests: + +- Go to Sale > Orders > Quotations. +- Open a sale order with an associated signature request. +- Click on the smart-button Sign Requests. +- Click on any signature request to view its details, status, and + progress. +- Alternatively, go to Sign > Requests. +- Use the Group By feature to group requests by Project and/or Task. + +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 +------- + +* KMEE + +Contributors +------------ + +- ``KMEE ``\ \_: + + - Tiago Amaral tiago.amaral@kmee.com.br + +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/sign `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/sale_order_sign_oca/__init__.py b/sale_order_sign_oca/__init__.py new file mode 100644 index 00000000..0650744f --- /dev/null +++ b/sale_order_sign_oca/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/sale_order_sign_oca/__manifest__.py b/sale_order_sign_oca/__manifest__.py new file mode 100644 index 00000000..530cb25e --- /dev/null +++ b/sale_order_sign_oca/__manifest__.py @@ -0,0 +1,23 @@ +# Copyright 2024 KMEE +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +{ + "name": "Sale Order Sign Oca", + "summary": """ + KMEE""", + "version": "14.0.1.0.0", + "license": "AGPL-3", + "author": "KMEE,Odoo Community Association (OCA)", + "website": "https://github.com/OCA/sign", + "depends": ["sign_oca", "sale"], + "data": [ + "security/sale_order_sign_oca_security.xml", + "views/sale_order.xml", + "views/sign_oca_request.xml", + "views/res_config_settings.xml", + ], + "demo": [ + "demo/sign_oca_role.xml", + "demo/sign_oca_template.xml", + ], +} diff --git a/sale_order_sign_oca/demo/sign_oca_role.xml b/sale_order_sign_oca/demo/sign_oca_role.xml new file mode 100644 index 00000000..cf32f68c --- /dev/null +++ b/sale_order_sign_oca/demo/sign_oca_role.xml @@ -0,0 +1,12 @@ + + + + + + Sale Order Customer + expression + ${object.partner_id.id} + + + diff --git a/sale_order_sign_oca/demo/sign_oca_template.xml b/sale_order_sign_oca/demo/sign_oca_template.xml new file mode 100644 index 00000000..579927e9 --- /dev/null +++ b/sale_order_sign_oca/demo/sign_oca_template.xml @@ -0,0 +1,25 @@ + + + + + + Sale Order Approval + + + + + + + + 1 + 10 + 10 + 30 + 4 + + + diff --git a/sale_order_sign_oca/models/__init__.py b/sale_order_sign_oca/models/__init__.py new file mode 100644 index 00000000..14d571aa --- /dev/null +++ b/sale_order_sign_oca/models/__init__.py @@ -0,0 +1,4 @@ +from . import sale_order +from . import res_company +from . import res_config_settings +from . import sign_oca_request diff --git a/sale_order_sign_oca/models/res_company.py b/sale_order_sign_oca/models/res_company.py new file mode 100644 index 00000000..c2ae9244 --- /dev/null +++ b/sale_order_sign_oca/models/res_company.py @@ -0,0 +1,25 @@ +# Copyright 2024 KMEE +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class ResCompany(models.Model): + _inherit = "res.company" + + sale_order_sign_oca_template_id = fields.Many2one( + comodel_name="sign.oca.template", + domain="[('model_id.model', '=', 'sale.order')]", + string="Sale Order Sign Oca Template", + ) + + sale_order_sign_oca_state = fields.Selection( + [ + ("draft", "Quotation"), + ("sent", "Quotation Sent"), + ("sale", "Sale Order"), + ("done", "Locked"), + ("cancel", "Cancelled"), + ], + string="Sales Order Status For Sign Request", + ) diff --git a/sale_order_sign_oca/models/res_config_settings.py b/sale_order_sign_oca/models/res_config_settings.py new file mode 100644 index 00000000..7d99ff0d --- /dev/null +++ b/sale_order_sign_oca/models/res_config_settings.py @@ -0,0 +1,40 @@ +# Copyright 2024 KMEE +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class ResConfigSettings(models.TransientModel): + + _inherit = "res.config.settings" + + group_sale_order_sign_oca = fields.Boolean( + "Sale Order Sign Template", + implied_group="sale_order_sign_oca.group_sale_order_sign_oca", + ) + + sale_order_sign_oca_template_id = fields.Many2one( + comodel_name="sign.oca.template", + related="company_id.sale_order_sign_oca_template_id", + string="Sale Order Sign Oca Template", + readonly=False, + ) + + sale_order_sign_oca_state = fields.Selection( + [ + ("draft", "Quotation"), + ("sent", "Quotation Sent"), + ("sale", "Sale Order"), + ("done", "Locked"), + ("cancel", "Cancelled"), + ], + string="Sales Order Status For Sign Request", + default=lambda self: self.env["res.company"] + .browse(self.env.user.company_id.id) + .sale_order_sign_oca_state, + ) + + def set_values(self): + super(ResConfigSettings, self).set_values() + company = self.env["res.company"].browse(self.env.user.company_id.id) + company.sale_order_sign_oca_state = self.sale_order_sign_oca_state diff --git a/sale_order_sign_oca/models/sale_order.py b/sale_order_sign_oca/models/sale_order.py new file mode 100644 index 00000000..77129862 --- /dev/null +++ b/sale_order_sign_oca/models/sale_order.py @@ -0,0 +1,82 @@ +# Copyright 2024 KMEE +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models + + +class SaleOrder(models.Model): + + _inherit = "sale.order" + + sign_request_ids = fields.One2many( + comodel_name="sign.oca.request", + inverse_name="sale_order_id", + string="Sign Requests", + ) + sign_request_count = fields.Integer( + string="Sign request count", + compute="_compute_sign_request_count", + compute_sudo=True, + ) + + @api.depends("sign_request_ids") + def _compute_sign_request_count(self): + for sale_order in self: + sale_order.sign_request_count = len(sale_order.sign_request_ids) + + def action_view_sign_requests(self): + self.ensure_one() + result = self.env["ir.actions.act_window"]._for_xml_id( + "sign_oca.sign_oca_request_act_window" + ) + result["domain"] = [("id", "in", self.sign_request_ids.ids)] + return result + + def _generate_sign_oca_request(self): + sign_request_obj = self.env["sign.oca.request"].sudo() + for sale_order in self: + sign_template = sale_order.company_id.sale_order_sign_oca_template_id + if sign_template: + sign_template = sign_template.sudo() + request = sign_request_obj.create( + sign_template._prepare_sign_oca_request_vals_from_record(sale_order) + ) + request.action_send() + + @api.model_create_multi + def create(self, vals_list): + res = super().create(vals_list) + if self.env.user.has_group("sale_order_sign_oca.group_sale_order_sign_oca"): + for sale_order in res: + if ( + sale_order.partner_id + and sale_order.company_id.sale_order_sign_oca_template_id + and sale_order.company_id.sale_order_sign_oca_state == "draft" + ): + sale_order._generate_sign_oca_request() + return res + + def write(self, vals): + old_partner_id = self.partner_id + new_partner_id = vals.get("partner_id") + old_state = self.state + new_state = vals.get("state") + res = super().write(vals) + if self.env.user.has_group("sale_order_sign_oca.group_sale_order_sign_oca"): + if ( + new_state + and new_state != old_state + and self.company_id.sale_order_sign_oca_template_id + and self.company_id.sale_order_sign_oca_state == new_state + ): + self._generate_sign_oca_request() + return res + + if ( + new_partner_id + and new_partner_id != old_partner_id + and self.company_id.sale_order_sign_oca_template_id + and self.company_id.sale_order_sign_oca_state == self.state + ): + self._generate_sign_oca_request() + return res diff --git a/sale_order_sign_oca/models/sign_oca_request.py b/sale_order_sign_oca/models/sign_oca_request.py new file mode 100644 index 00000000..a7dd9606 --- /dev/null +++ b/sale_order_sign_oca/models/sign_oca_request.py @@ -0,0 +1,23 @@ +# Copyright 2024 KMEE +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models + + +class SignOcaRequest(models.Model): + _inherit = "sign.oca.request" + + sale_order_id = fields.Many2one( + comodel_name="sale.order", + string="Sale Order", + compute="_compute_sale_order_id", + readonly=True, + store=True, + ) + + @api.depends("record_ref") + def _compute_sale_order_id(self): + for item in self.filtered( + lambda x: x.record_ref and x.record_ref._name == "sale.order" + ): + item.sale_order_id = item.record_ref.id diff --git a/sale_order_sign_oca/readme/CONFIGURE.md b/sale_order_sign_oca/readme/CONFIGURE.md new file mode 100644 index 00000000..b6f1d289 --- /dev/null +++ b/sale_order_sign_oca/readme/CONFIGURE.md @@ -0,0 +1,15 @@ +#. Go to Sign > Roles and create a role with the following data: + +- Partner type: Expression +- Expression: ${object.partner_id.id} + +#. Go to Sign > Templates and create a template with the following data: + +- Model: Sale Order +- In one of the fields, you must set the previously created role. + +#. Go to Sales > Configuration > Settings. + +- In the Sale Order Sign section, mark the field Sale Order Sign Template, define the template that will be used to generate the sales order sign request. +- Use the template previously created. +- And choose the state in which this will happen. diff --git a/sale_order_sign_oca/readme/CONTRIBUTORS.md b/sale_order_sign_oca/readme/CONTRIBUTORS.md new file mode 100644 index 00000000..1de5cdb4 --- /dev/null +++ b/sale_order_sign_oca/readme/CONTRIBUTORS.md @@ -0,0 +1,3 @@ +* `KMEE `_: + + * Tiago Amaral diff --git a/sale_order_sign_oca/readme/DESCRIPTION.md b/sale_order_sign_oca/readme/DESCRIPTION.md new file mode 100644 index 00000000..2330a69f --- /dev/null +++ b/sale_order_sign_oca/readme/DESCRIPTION.md @@ -0,0 +1 @@ +This module allows you to generate manual and automatic signature requests from sale order to customers. diff --git a/sale_order_sign_oca/readme/USAGE.md b/sale_order_sign_oca/readme/USAGE.md new file mode 100644 index 00000000..b264d18b --- /dev/null +++ b/sale_order_sign_oca/readme/USAGE.md @@ -0,0 +1,17 @@ +Creating a Signature Request from a Sale Order: +- Go to Sales > Quotations. +- Open an existing quotation or create a new one (make sure to fill in the `partner_id` field). +- In the sale order form view, click on the action "Sign from template". +- Sign Requests will have been generated (and sent) linked to the selected project and task. + +Automatic Signature Request creation: +- Define a template in Sale > Configuration > Settings. +- When an customer is assigned to a sale order, a Sign Request will be created (and sent) automatically. + +Viewing Signature Requests: +- Go to Sale > Orders > Quotations. +- Open a sale order with an associated signature request. +- Click on the smart-button Sign Requests. +- Click on any signature request to view its details, status, and progress. +- Alternatively, go to Sign > Requests. +- Use the Group By feature to group requests by Project and/or Task. diff --git a/sale_order_sign_oca/security/sale_order_sign_oca_security.xml b/sale_order_sign_oca/security/sale_order_sign_oca_security.xml new file mode 100644 index 00000000..082bcb3c --- /dev/null +++ b/sale_order_sign_oca/security/sale_order_sign_oca_security.xml @@ -0,0 +1,9 @@ + + + + + Sale Order Sign + + + + diff --git a/sale_order_sign_oca/static/description/icon.png b/sale_order_sign_oca/static/description/icon.png new file mode 100644 index 00000000..3a0328b5 Binary files /dev/null and b/sale_order_sign_oca/static/description/icon.png differ diff --git a/sale_order_sign_oca/static/description/index.html b/sale_order_sign_oca/static/description/index.html new file mode 100644 index 00000000..412ec251 --- /dev/null +++ b/sale_order_sign_oca/static/description/index.html @@ -0,0 +1,485 @@ + + + + + +Sale Order Sign Oca + + + +
+

Sale Order Sign Oca

+ + +

Beta License: AGPL-3 OCA/sign Translate me on Weblate Try me on Runboat

+

This module allows you to generate manual and automatic signature +requests from sale order to customers.

+

Table of contents

+ +
+

Configuration

+
    +
  1. Go to Sign > Roles and create a role with the following data:
  2. +
+
    +
  • Partner type: Expression
  • +
  • Expression: ${object.partner_id.id}
  • +
+
    +
  1. Go to Sign > Templates and create a template with the following data:
  2. +
+
    +
  • Model: Sale Order
  • +
  • In one of the fields, you must set the previously created role.
  • +
+
    +
  1. Go to Sales > Configuration > Settings.
  2. +
+
    +
  • In the Sale Order Sign section, mark the field Sale Order Sign +Template, define the template that will be used to generate the sales +order sign request.
  • +
  • Use the template previously created.
  • +
  • And choose the state in which this will happen.
  • +
+
+
+

Usage

+

Creating a Signature Request from a Sale Order:

+
    +
  • Go to Sales > Quotations.
  • +
  • Open an existing quotation or create a new one (make sure to fill in +the partner_id field).
  • +
  • In the sale order form view, click on the action “Sign from +template”.
  • +
  • Sign Requests will have been generated (and sent) linked to the +selected project and task.
  • +
+

Automatic Signature Request creation:

+
    +
  • Define a template in Sale > Configuration > Settings.
  • +
  • When an customer is assigned to a sale order, a Sign Request will be +created (and sent) automatically.
  • +
+

Viewing Signature Requests:

+
    +
  • Go to Sale > Orders > Quotations.
  • +
  • Open a sale order with an associated signature request.
  • +
  • Click on the smart-button Sign Requests.
  • +
  • Click on any signature request to view its details, status, and +progress.
  • +
  • Alternatively, go to Sign > Requests.
  • +
  • Use the Group By feature to group requests by Project and/or Task.
  • +
+
+
+

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

+
    +
  • KMEE
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

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/sign project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/sale_order_sign_oca/tests/__init__.py b/sale_order_sign_oca/tests/__init__.py new file mode 100644 index 00000000..9825ba76 --- /dev/null +++ b/sale_order_sign_oca/tests/__init__.py @@ -0,0 +1 @@ +from . import test_sale_order_sign_oca diff --git a/sale_order_sign_oca/tests/test_sale_order_sign_oca.py b/sale_order_sign_oca/tests/test_sale_order_sign_oca.py new file mode 100644 index 00000000..8aefb646 --- /dev/null +++ b/sale_order_sign_oca/tests/test_sale_order_sign_oca.py @@ -0,0 +1,88 @@ +# Copyright 2024 KMEE +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo.tests.common import SavepointCase + + +class TestSaleOrderSignOca(SavepointCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.company_id = cls.env.company + cls.template = cls.env.ref( + "sale_order_sign_oca.sign_oca_template_sale_order_demo" + ) + cls.customer_a = cls.env["res.partner"].create( + { + "name": "Test Customer A", + } + ) + cls.customer_b = cls.env["res.partner"].create( + { + "name": "Test Customer B", + } + ) + cls.sale_order_a = cls.env["sale.order"].create( + { + "name": "Test Sale Order A", + "partner_id": cls.customer_a.id, + "company_id": cls.company_id.id, + } + ) + cls.sale_order_b = cls.env["sale.order"].create( + { + "name": "Test Sale Order B", + "partner_id": cls.customer_b.id, + "company_id": cls.company_id.id, + } + ) + cls.ConfigSettings = cls.env["res.config.settings"] + config = cls.ConfigSettings.create({}) + config.sale_order_sign_oca_template_id = cls.template + config.sale_order_sign_oca_state = "draft" + config.group_sale_order_sign_oca = True + config.set_values() + + def test_sale_order_create(self): + sale_order_c = self.env["sale.order"].create( + { + "name": "Test Sale Order C", + "partner_id": self.customer_a.id, + "company_id": self.company_id.id, + } + ) + self.assertIn( + self.customer_a, + sale_order_c.sign_request_ids.mapped("signer_ids.partner_id"), + ) + self.assertEqual(sale_order_c.sign_request_count, 1) + self.assertEqual(sale_order_c.sign_request_ids[0].sale_order_id, sale_order_c) + + def test_sale_order_write(self): + customer_c = self.env["res.partner"].create( + { + "name": "Test Customer C", + } + ) + + sale_order_d = self.env["sale.order"].create( + { + "name": "Test Sale Order D", + "partner_id": customer_c.id, + "company_id": self.company_id.id, + } + ) + self.assertTrue(sale_order_d.sign_request_ids) + self.assertEqual(sale_order_d.sign_request_count, 1) + sale_order_d.write({"partner_id": self.customer_a.id}) + self.assertIn( + self.customer_a, + sale_order_d.sign_request_ids.mapped("signer_ids.partner_id"), + ) + self.assertEqual(sale_order_d.sign_request_count, 2) + sale_order_d.write({"partner_id": self.customer_b.id}) + self.assertIn( + self.customer_b, + sale_order_d.sign_request_ids.mapped("signer_ids.partner_id"), + ) + self.assertEqual(sale_order_d.sign_request_count, 3) diff --git a/sale_order_sign_oca/views/res_config_settings.xml b/sale_order_sign_oca/views/res_config_settings.xml new file mode 100644 index 00000000..ff614a33 --- /dev/null +++ b/sale_order_sign_oca/views/res_config_settings.xml @@ -0,0 +1,84 @@ + + + + + res.config.settings.view.form.inherit.sale (in sale_order_sign_oca) + res.config.settings + + + +

Sign

+
+
+
+ +
+
+
+
+
+
+ State for Generation +
+ Defines the state in which the sign request will be generated. +
+
+
+ +
+
+
+
+
+
+
+
+
diff --git a/sale_order_sign_oca/views/sale_order.xml b/sale_order_sign_oca/views/sale_order.xml new file mode 100644 index 00000000..1d93df16 --- /dev/null +++ b/sale_order_sign_oca/views/sale_order.xml @@ -0,0 +1,33 @@ + + + + + + sale.order.form (in sale_order_sign_oca) + sale.order + + + +
+ +
+
+
+ +
diff --git a/sale_order_sign_oca/views/sign_oca_request.xml b/sale_order_sign_oca/views/sign_oca_request.xml new file mode 100644 index 00000000..c9ce62b2 --- /dev/null +++ b/sale_order_sign_oca/views/sign_oca_request.xml @@ -0,0 +1,79 @@ + + + + + + sign.oca.request.search (in sale_order_sign_oca) + sign.oca.request + + + + + + + + + + + + + + sign.oca.request.form (in sale_order_sign_oca) + sign.oca.request + + + + + + + + + + + sign.oca.request.tree (in sale_order_sign_oca) + sign.oca.request + + + + + + + + + + + Sale Order Sign Templates + ir.actions.act_window + sign.oca.template + tree,form + [('model_id', '=', 'sale.order')] + +

+ Create your quotation template +

+ Use templates to create polished, professional quotes in minutes. + Send these quotes by email and let your customers sign online. + Use cross-selling and discounts to push and boost your sales. +

+
+
+ +
diff --git a/setup/sale_order_sign_oca/odoo/addons/sale_order_sign_oca b/setup/sale_order_sign_oca/odoo/addons/sale_order_sign_oca new file mode 120000 index 00000000..fb54048d --- /dev/null +++ b/setup/sale_order_sign_oca/odoo/addons/sale_order_sign_oca @@ -0,0 +1 @@ +../../../../sale_order_sign_oca \ No newline at end of file diff --git a/setup/sale_order_sign_oca/setup.py b/setup/sale_order_sign_oca/setup.py new file mode 100644 index 00000000..28c57bb6 --- /dev/null +++ b/setup/sale_order_sign_oca/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)