diff --git a/agreement_type/README.rst b/agreement_type/README.rst new file mode 100644 index 000000000..0a442d0ca --- /dev/null +++ b/agreement_type/README.rst @@ -0,0 +1,107 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + +============== +Agreement Type +============== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:041fcdae1f57046e4497687a5c81e347c6578c0916226e75b796797d468562e9 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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/license-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%2Fagreement-lightgray.png?logo=github + :target: https://github.com/OCA/agreement/tree/19.0/agreement_type + :alt: OCA/agreement +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/agreement-19-0/agreement-19-0-agreement_type + :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/agreement&target_branch=19.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module turns agreement types into a hierarchy: an agreement type +can have a parent type, so sub-types are simply child agreement types +(the standalone agreement.subtype model is no longer needed). + +It also carries the review-reminder feature: the review user/days on the +type, the agreement's computed review date, and the cron that schedules +a review activity before an agreement expires. + +.. image:: https://raw.githubusercontent.com/OCA/agreement/19.0/agreement_type/static/description/screenshot_form.png + :alt: Agreement Form + +**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 +------- + +* Pavlov Media +* Open Source Integrators +* Yves Goldberg (Ygol Internetwork) + +Contributors +------------ + +- Pavlov Media +- Open Source Integrators +- Yves Goldberg (Ygol Internetwork) +- `glueckkanja AG `__: + + - Christopher Rogos + +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-max3903| image:: https://github.com/max3903.png?size=40px + :target: https://github.com/max3903 + :alt: max3903 +.. |maintainer-ygol| image:: https://github.com/ygol.png?size=40px + :target: https://github.com/ygol + :alt: ygol + +Current `maintainers `__: + +|maintainer-max3903| |maintainer-ygol| + +This module is part of the `OCA/agreement `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/agreement_type/__init__.py b/agreement_type/__init__.py new file mode 100644 index 000000000..69f7babdf --- /dev/null +++ b/agreement_type/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import models diff --git a/agreement_type/__manifest__.py b/agreement_type/__manifest__.py new file mode 100644 index 000000000..91ea1313e --- /dev/null +++ b/agreement_type/__manifest__.py @@ -0,0 +1,24 @@ +# Copyright (C) 2018 - TODAY, Pavlov Media +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + "name": "Agreement Type", + "summary": "Hierarchical agreement types (with sub-types) and review reminders", + "author": "Pavlov Media, " + "Open Source Integrators, " + "Yves Goldberg (Ygol Internetwork), " + "Odoo Community Association (OCA)", + "website": "https://github.com/OCA/agreement", + "category": "Partner", + "license": "AGPL-3", + "version": "19.0.1.0.0", + "depends": ["agreement"], + "excludes": ["agreement_legal"], + "data": [ + "data/cron.xml", + "views/agreement_type.xml", + "views/agreement.xml", + ], + "development_status": "Beta", + "maintainers": ["max3903", "ygol"], +} diff --git a/agreement_type/data/cron.xml b/agreement_type/data/cron.xml new file mode 100644 index 000000000..048b0f1d0 --- /dev/null +++ b/agreement_type/data/cron.xml @@ -0,0 +1,23 @@ + + + + + Agreement needs a review + note + default + agreement + fa-tasks + 0 + + + + Agreement: Check to Review Days + + code + model._alert_to_review_date() + + 20 + minutes + + + diff --git a/agreement_type/models/__init__.py b/agreement_type/models/__init__.py new file mode 100644 index 000000000..6c3aa9160 --- /dev/null +++ b/agreement_type/models/__init__.py @@ -0,0 +1,4 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import agreement_type +from . import agreement diff --git a/agreement_type/models/agreement.py b/agreement_type/models/agreement.py new file mode 100644 index 000000000..3e73012a2 --- /dev/null +++ b/agreement_type/models/agreement.py @@ -0,0 +1,46 @@ +# Copyright (C) 2018 - TODAY, Pavlov Media +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from datetime import timedelta + +from odoo import api, fields, models + + +class Agreement(models.Model): + _inherit = "agreement" + + to_review_date = fields.Date( + compute="_compute_to_review_date", + store=True, + readonly=False, + help="Date used to warn us some days before agreement expires", + ) + + @api.depends("agreement_type_id", "end_date") + def _compute_to_review_date(self): + for record in self: + if record.end_date: + record.to_review_date = record.end_date + timedelta( + days=-record.agreement_type_id.review_days + ) + + @api.model + def _alert_to_review_date(self): + agreements = self.search( + [ + ("to_review_date", "=", fields.Date.today()), + ("agreement_type_id.review_user_id", "!=", False), + ] + ) + for agreement in agreements: + if ( + self.env["mail.activity"].search_count( + [("res_id", "=", agreement.id), ("res_model", "=", self._name)] + ) + == 0 + ): + agreement.activity_schedule( + "agreement_legal_type.mail_activity_review_agreement", + user_id=agreement.agreement_type_id.review_user_id.id, + note=self.env._("Your activity is going to end soon"), + ) diff --git a/agreement_type/models/agreement_type.py b/agreement_type/models/agreement_type.py new file mode 100644 index 000000000..5e0a6d89f --- /dev/null +++ b/agreement_type/models/agreement_type.py @@ -0,0 +1,31 @@ +# Copyright (C) 2018 - TODAY, Pavlov Media +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models + + +class AgreementType(models.Model): + _inherit = "agreement.type" + + parent_type_id = fields.Many2one( + "agreement.type", + string="Parent Type", + ondelete="cascade", + help="When set, this type is a sub-type of the selected parent type.", + ) + child_type_ids = fields.One2many( + "agreement.type", "parent_type_id", string="Sub-Types" + ) + review_user_id = fields.Many2one( + "res.users", help="User assigned automatically the activity on review date" + ) + review_days = fields.Integer() + + @api.depends("name") + def _compute_display_name(self): + for agreement_type in self: + agreement_type.display_name = ( + f"{agreement_type.parent_type_id.display_name} / {agreement_type.name}" + if agreement_type.parent_type_id + else agreement_type.name + ) diff --git a/agreement_type/pyproject.toml b/agreement_type/pyproject.toml new file mode 100644 index 000000000..4231d0ccc --- /dev/null +++ b/agreement_type/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/agreement_type/readme/CONTRIBUTORS.md b/agreement_type/readme/CONTRIBUTORS.md new file mode 100644 index 000000000..01af77936 --- /dev/null +++ b/agreement_type/readme/CONTRIBUTORS.md @@ -0,0 +1,5 @@ +- Pavlov Media +- Open Source Integrators +- Yves Goldberg (Ygol Internetwork) +- [glueckkanja AG](https://www.glueckkanja.com/): + - Christopher Rogos \ No newline at end of file diff --git a/agreement_type/readme/DESCRIPTION.md b/agreement_type/readme/DESCRIPTION.md new file mode 100644 index 000000000..2bf3332c6 --- /dev/null +++ b/agreement_type/readme/DESCRIPTION.md @@ -0,0 +1,9 @@ +This module turns agreement types into a hierarchy: an agreement type can have +a parent type, so sub-types are simply child agreement types (the standalone +agreement.subtype model is no longer needed). + +It also carries the review-reminder feature: the review user/days on the type, +the agreement's computed review date, and the cron that schedules a review +activity before an agreement expires. + +![Agreement Form](../static/description/screenshot_form.png) diff --git a/agreement_type/static/description/icon.png b/agreement_type/static/description/icon.png new file mode 100644 index 000000000..3a0328b51 Binary files /dev/null and b/agreement_type/static/description/icon.png differ diff --git a/agreement_type/static/description/index.html b/agreement_type/static/description/index.html new file mode 100644 index 000000000..0f8743750 --- /dev/null +++ b/agreement_type/static/description/index.html @@ -0,0 +1,445 @@ + + + + + +README.rst + + + +
+ + + +Odoo Community Association + +
+

Agreement Type

+ +

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

+

This module turns agreement types into a hierarchy: an agreement type +can have a parent type, so sub-types are simply child agreement types +(the standalone agreement.subtype model is no longer needed).

+

It also carries the review-reminder feature: the review user/days on the +type, the agreement’s computed review date, and the cron that schedules +a review activity before an agreement expires.

+Agreement Form +

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

+
    +
  • Pavlov Media
  • +
  • Open Source Integrators
  • +
  • Yves Goldberg (Ygol Internetwork)
  • +
+
+
+

Contributors

+
    +
  • Pavlov Media
  • +
  • Open Source Integrators
  • +
  • Yves Goldberg (Ygol Internetwork)
  • +
  • glueckkanja AG:
      +
    • Christopher Rogos
    • +
    +
  • +
+
+
+

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.

+

Current maintainers:

+

max3903 ygol

+

This module is part of the OCA/agreement project on GitHub.

+

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

+
+
+
+
+ + diff --git a/agreement_type/static/description/screenshot_form.png b/agreement_type/static/description/screenshot_form.png new file mode 100644 index 000000000..da4261bef Binary files /dev/null and b/agreement_type/static/description/screenshot_form.png differ diff --git a/agreement_type/tests/__init__.py b/agreement_type/tests/__init__.py new file mode 100644 index 000000000..77e5ca0a9 --- /dev/null +++ b/agreement_type/tests/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) + +from . import test_agreement_type diff --git a/agreement_type/tests/test_agreement_type.py b/agreement_type/tests/test_agreement_type.py new file mode 100644 index 000000000..d6ddce281 --- /dev/null +++ b/agreement_type/tests/test_agreement_type.py @@ -0,0 +1,74 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) + +from datetime import timedelta + +from odoo import fields +from odoo.tests.common import TransactionCase + + +class TestAgreementType(TransactionCase): + def setUp(self): + super().setUp() + self.test_customer = self.env["res.partner"].create({"name": "TestCustomer"}) + self.agreement_type = self.env["agreement.type"].create( + {"name": "Test Agreement Type", "domain": "sale"} + ) + self.test_agreement = self.env["agreement"].create( + { + "name": "TestAgreement", + "code": "TA001", + "partner_id": self.test_customer.id, + "start_date": fields.Date.today(), + "end_date": fields.Date.today() + timedelta(days=365), + } + ) + + # A sub-type is an agreement type with a parent type + def test_subtype_hierarchy(self): + subtype = self.env["agreement.type"].create( + {"name": "Test Sub-Type", "parent_type_id": self.agreement_type.id} + ) + self.assertIn(subtype, self.agreement_type.child_type_ids) + self.test_agreement.write( + { + "agreement_type_id": subtype.id, + } + ) + self.assertEqual(self.test_agreement.agreement_type_id, subtype) + + # The review cron schedules an activity on the review date + def test_cron(self): + self.agreement_type.write( + {"review_user_id": self.env.user.id, "review_days": 0} + ) + self.agreement_type.flush_recordset() + self.test_agreement.write({"agreement_type_id": self.agreement_type.id}) + self.test_agreement.flush_recordset() + self.test_agreement.invalidate_recordset() + self.assertFalse( + self.env["mail.activity"].search_count( + [ + ("res_id", "=", self.test_agreement.id), + ("res_model", "=", self.test_agreement._name), + ] + ) + ) + self.env["agreement"]._alert_to_review_date() + self.assertFalse( + self.env["mail.activity"].search_count( + [ + ("res_id", "=", self.test_agreement.id), + ("res_model", "=", self.test_agreement._name), + ] + ) + ) + self.test_agreement.to_review_date = fields.Date.today() + self.env["agreement"]._alert_to_review_date() + self.assertTrue( + self.env["mail.activity"].search_count( + [ + ("res_id", "=", self.test_agreement.id), + ("res_model", "=", self.test_agreement._name), + ] + ) + ) diff --git a/agreement_type/views/agreement.xml b/agreement_type/views/agreement.xml new file mode 100644 index 000000000..4422d4e5d --- /dev/null +++ b/agreement_type/views/agreement.xml @@ -0,0 +1,33 @@ + + + + agreement.form.subtype + agreement + + + + + + + + + + + agreement.search.subtype + agreement + + + + + + + + diff --git a/agreement_type/views/agreement_type.xml b/agreement_type/views/agreement_type.xml new file mode 100644 index 000000000..30d0a2e12 --- /dev/null +++ b/agreement_type/views/agreement_type.xml @@ -0,0 +1,50 @@ + + + + Agreement Type List + agreement.type + + + + + + + + + + + Agreement Type Form + agreement.type + + + + + + + + + + + + + + + + + + + + + Agreement Types + agreement.type + list,form + [('parent_type_id', '=', False)] + + + + Agreement Sub-Types + agreement.type + list,form + [('parent_type_id', '!=', False)] + +