From 3a126124a4be7759f97e57b22f0bc79549b2a6b8 Mon Sep 17 00:00:00 2001 From: RemiFr82 Date: Wed, 29 May 2024 16:37:37 +0200 Subject: [PATCH] [ADD] partner_contact_majority module --- partner_contact_majority/__init__.py | 6 + partner_contact_majority/__manifest__.py | 54 ++++++ partner_contact_majority/hooks.py | 121 ++++++++++++ partner_contact_majority/i18n/fr.po | 181 ++++++++++++++++++ partner_contact_majority/models/__init__.py | 5 + .../models/res_country.py | 9 + .../models/res_country_state.py | 28 +++ .../models/res_partner.py | 95 +++++++++ .../security/ir.model.access.csv | 3 + partner_contact_majority/security/ir_rule.xml | 19 ++ .../security/res_groups.xml | 15 ++ .../views/res_country.xml | 16 ++ .../views/res_country_state.xml | 42 ++++ .../views/res_partner.xml | 36 ++++ partner_contact_majority/wizard/__init__.py | 3 + .../wizard/res_partner_emancipate.py | 20 ++ .../wizard/res_partner_emancipate.xml | 45 +++++ 17 files changed, 698 insertions(+) create mode 100644 partner_contact_majority/__init__.py create mode 100644 partner_contact_majority/__manifest__.py create mode 100644 partner_contact_majority/hooks.py create mode 100644 partner_contact_majority/i18n/fr.po create mode 100644 partner_contact_majority/models/__init__.py create mode 100644 partner_contact_majority/models/res_country.py create mode 100644 partner_contact_majority/models/res_country_state.py create mode 100644 partner_contact_majority/models/res_partner.py create mode 100644 partner_contact_majority/security/ir.model.access.csv create mode 100644 partner_contact_majority/security/ir_rule.xml create mode 100644 partner_contact_majority/security/res_groups.xml create mode 100644 partner_contact_majority/views/res_country.xml create mode 100644 partner_contact_majority/views/res_country_state.xml create mode 100644 partner_contact_majority/views/res_partner.xml create mode 100644 partner_contact_majority/wizard/__init__.py create mode 100644 partner_contact_majority/wizard/res_partner_emancipate.py create mode 100644 partner_contact_majority/wizard/res_partner_emancipate.xml diff --git a/partner_contact_majority/__init__.py b/partner_contact_majority/__init__.py new file mode 100644 index 0000000..f80cfcb --- /dev/null +++ b/partner_contact_majority/__init__.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). +from . import models +from . import wizard + +from .hooks import post_init_hook diff --git a/partner_contact_majority/__manifest__.py b/partner_contact_majority/__manifest__.py new file mode 100644 index 0000000..8e12132 --- /dev/null +++ b/partner_contact_majority/__manifest__.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). +{ + "name": "Contact majority", + "version": "16.0.1.0.0", + "summary": "Module summary", + "description": """ + Module description + """, + "author": "RemiFr82", + "contributors": "", + "maintainer": "RemiFr82", + "website": "https://git.myceliandre.fr/RemiFr82/odoo-contact-addons.git", + "license": "AGPL-3", + "category": "Customer Relationship Management", + # "price": 0, + # "currency": "EUR", + "application": False, + "installable": True, + "auto_install": False, + # "pre_init_hook": "", + "post_init_hook": "post_init_hook", + # "uninstall_hook": "", + # "excludes": [], + # "external_dependencies": [], + "depends": [ + "partner_contact_birthdate", + "partner_contact_birthplace", + "partner_contact_nationality", + ], + "data": [ + # Base data + # "data/ir_model.xml", + # Security + # 'security/res_groups.xml', + "security/ir.model.access.csv", + # 'security/ir_rule.xml', + # Views + "views/res_country.xml", + "views/res_country_state.xml", + "views/res_partner.xml", + # Wizards + "wizard/res_partner_emancipate.xml", + # Reports + # 'reports/report_templates.xml', + # 'reports/sql_view.xml', + ], + # "assets": [], + # "css": [], + # "images": [], + # "js": [], + # "test": [], + # "demo": [], +} diff --git a/partner_contact_majority/hooks.py b/partner_contact_majority/hooks.py new file mode 100644 index 0000000..8908663 --- /dev/null +++ b/partner_contact_majority/hooks.py @@ -0,0 +1,121 @@ +import logging + +from odoo.api import Environment, SUPERUSER_ID + +_logger = logging.getLogger(__name__) + + +# def pre_init_hook(cr, registry): +# env = Environment(cr, SUPERUSER_ID, {}) +# _logger.info("Pre init hook") + + +def post_init_hook(cr, registry): + # Source : https://en.wikipedia.org/wiki/Age_of_majority (2024-05-29) + env = Environment(cr, SUPERUSER_ID, {}) + env["res.country"].search([("code", "in", ("ID", "YE"))]).write( + { + "majority_age": 15, + } + ) + env["res.country"].search([("code", "in", ("KH", "CU", "MM", "VN"))]).write( + { + "majority_age": 16, + } + ) + env["res.country"].search([("code", "in", ("KP", "TL"))]).write( + { + "majority_age": 17, + } + ) + env["res.country"].search([("code", "in", ("DZ", "KR"))]).write( + { + "majority_age": 19, + } + ) + env["res.country.state"].search( + [ + "|", + "&", + ("country_id.code", "=", "CA"), + ( + "code", + "in", + ( + "BC", + "NB", + "NL", + "NS", + "NT", + "NU", + "YT", + ), + ), + "&", + ("country_id.code", "=", "US"), + ( + "code", + "in", + ( + "AL", + "NE", + ), + ), + ] + ).write( + { + "majority_age": 19, + "same_country_age": False, + } + ) + env["res.country"].search([("code", "in", ("NZ", "TH"))]).write( + { + "majority_age": 20, + } + ) + env["res.country"].search( + [ + ( + "code", + "in", + ( + "CM", + "TD", + "CI", + "SZ", + "GA", + "GD", + "HN", + "KW", + "LS", + "MG", + "NI", + "NE", + "PR", + "WS", + "AE", + "ZM", + ), + ) + ] + ).write( + { + "majority_age": 21, + } + ) + env["res.country.state"].search( + [ + ("country_id.code", "=", "US"), + ("code", "=", "MS"), + ] + ).write( + { + "majority_age": 21, + } + ) + _logger.info("\n#####\nPost init hook for contacts majority passed...\n#####\n") + + +# def uninstall_hook(cr, registry): +# env = Environment(cr, SUPERUSER_ID, {}) +# _logger.info("Uninstall hook") diff --git a/partner_contact_majority/i18n/fr.po b/partner_contact_majority/i18n/fr.po new file mode 100644 index 0000000..78e67d1 --- /dev/null +++ b/partner_contact_majority/i18n/fr.po @@ -0,0 +1,181 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * partner_contact_majority +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0-20230613\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-05-29 12:58+0000\n" +"PO-Revision-Date: 2024-05-29 12: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: partner_contact_majority +#: model_terms:ir.ui.view,arch_db:partner_contact_majority.personal_information_form_inherit +msgid "for" +msgstr "depuis" + +#. module: partner_contact_majority +#: model_terms:ir.ui.view,arch_db:partner_contact_majority.personal_information_form_inherit +msgid "still for" +msgstr "pour encore" + +#. module: partner_contact_majority +#: model_terms:ir.ui.view,arch_db:partner_contact_majority.personal_information_form_inherit +msgid "years" +msgstr "ans" + +#. module: partner_contact_majority +#: model:ir.model.fields,field_description:partner_contact_majority.field_res_partner__age +#: model:ir.model.fields,field_description:partner_contact_majority.field_res_users__age +msgid "Age" +msgstr "Âge" + +#. module: partner_contact_majority +#: model_terms:ir.ui.view,arch_db:partner_contact_majority.res_partner_emancipate_view_form +msgid "Cancel" +msgstr "Annuler" + +#. module: partner_contact_majority +#: model:ir.model,name:partner_contact_majority.model_res_partner +msgid "Contact" +msgstr "" + +#. module: partner_contact_majority +#: model:ir.model,name:partner_contact_majority.model_res_country +msgid "Country" +msgstr "Pays" + +#. module: partner_contact_majority +#: model:ir.model,name:partner_contact_majority.model_res_country_state +msgid "Country state" +msgstr "État" + +#. module: partner_contact_majority +#: model:ir.model.fields,field_description:partner_contact_majority.field_res_partner_emancipate__create_uid +msgid "Created by" +msgstr "Créé par" + +#. module: partner_contact_majority +#: model:ir.model.fields,field_description:partner_contact_majority.field_res_partner_emancipate__create_date +msgid "Created on" +msgstr "Créé le" + +#. module: partner_contact_majority +#: model:ir.model.fields,field_description:partner_contact_majority.field_res_partner_emancipate__display_name +msgid "Display Name" +msgstr "Nom d'affichage" + +#. module: partner_contact_majority +#: model:ir.actions.act_window,name:partner_contact_majority.res_partner_emancipate_action +#: model:ir.actions.server,name:partner_contact_majority.res_partner_emancipate_action_server +msgid "Emancipate" +msgstr "Émanciper" + +#. module: partner_contact_majority +#: model:ir.model.fields,field_description:partner_contact_majority.field_res_partner__emancipation_date +#: model:ir.model.fields,field_description:partner_contact_majority.field_res_users__emancipation_date +msgid "Emancipation" +msgstr "Émancipation" + +#. module: partner_contact_majority +#: model:ir.model.fields,field_description:partner_contact_majority.field_res_partner_emancipate__emancipation_date +msgid "Emancipation date" +msgstr "Date d'émancipation" + +#. module: partner_contact_majority +#: model:ir.model.fields,field_description:partner_contact_majority.field_res_partner_emancipate__id +msgid "ID" +msgstr "" + +#. module: partner_contact_majority +#: model:ir.model.fields,field_description:partner_contact_majority.field_res_partner__is_emancipated +#: model:ir.model.fields,field_description:partner_contact_majority.field_res_users__is_emancipated +msgid "Is emancipated" +msgstr "Est émancipé" + +#. module: partner_contact_majority +#: model:ir.model.fields,field_description:partner_contact_majority.field_res_partner__is_major +#: model:ir.model.fields,field_description:partner_contact_majority.field_res_users__is_major +msgid "Is major" +msgstr "Est majeur" + +#. module: partner_contact_majority +#: model:ir.model.fields,field_description:partner_contact_majority.field_res_partner_emancipate____last_update +msgid "Last Modified on" +msgstr "Dernière modification le" + +#. module: partner_contact_majority +#: model:ir.model.fields,field_description:partner_contact_majority.field_res_partner_emancipate__write_uid +msgid "Last Updated by" +msgstr "Dernière modification par" + +#. module: partner_contact_majority +#: model:ir.model.fields,field_description:partner_contact_majority.field_res_partner_emancipate__write_date +msgid "Last Updated on" +msgstr "Dernière mise à jour le" + +#. module: partner_contact_majority +#: model:ir.model.fields,field_description:partner_contact_majority.field_res_partner__legal_status +#: model:ir.model.fields,field_description:partner_contact_majority.field_res_users__legal_status +msgid "Legal status" +msgstr "Statut légal" + +#. module: partner_contact_majority +#: model:ir.model.fields.selection,name:partner_contact_majority.selection__res_partner__legal_status__major +msgid "Major" +msgstr "Majeur" + +#. module: partner_contact_majority +#: model:ir.model.fields,field_description:partner_contact_majority.field_res_country__majority_age +#: model:ir.model.fields,field_description:partner_contact_majority.field_res_country_state__majority_age +#: model_terms:ir.ui.view,arch_db:partner_contact_majority.view_country_state_search_inherit_base +msgid "Majority age" +msgstr "Âge de majorité" + +#. module: partner_contact_majority +#: model:ir.model.fields,field_description:partner_contact_majority.field_res_partner__majority_date +#: model:ir.model.fields,field_description:partner_contact_majority.field_res_users__majority_date +msgid "Majority date" +msgstr "Date de majorité" + +#. module: partner_contact_majority +#: model:ir.model.fields,field_description:partner_contact_majority.field_res_partner__majority_years +#: model:ir.model.fields,field_description:partner_contact_majority.field_res_users__majority_years +msgid "Majority years" +msgstr "Années à la majorité" + +#. module: partner_contact_majority +#: model:ir.model.fields.selection,name:partner_contact_majority.selection__res_partner__legal_status__minor +msgid "Minor" +msgstr "Mineur" + +#. module: partner_contact_majority +#: model:ir.model.fields,field_description:partner_contact_majority.field_res_partner_emancipate__partner_id +msgid "Partner" +msgstr "Contact" + +#. module: partner_contact_majority +#: model:ir.model,name:partner_contact_majority.model_res_partner_emancipate +msgid "Partner Emancipation Wizard" +msgstr "Assistant d'épancipation de contact" + +#. module: partner_contact_majority +#: model_terms:ir.ui.view,arch_db:partner_contact_majority.res_partner_emancipate_view_form +msgid "Partner emancipation" +msgstr "Émancipation de contact" + +#. module: partner_contact_majority +#: model:ir.model.fields,field_description:partner_contact_majority.field_res_country_state__same_country_age +msgid "Same age as country" +msgstr "Même âge que le pays" + +#. module: partner_contact_majority +#: model_terms:ir.ui.view,arch_db:partner_contact_majority.res_partner_emancipate_view_form +msgid "Validate emancipation" +msgstr "Valider l'émancipation" diff --git a/partner_contact_majority/models/__init__.py b/partner_contact_majority/models/__init__.py new file mode 100644 index 0000000..d59d0f6 --- /dev/null +++ b/partner_contact_majority/models/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). +from . import res_country_state +from . import res_country +from . import res_partner diff --git a/partner_contact_majority/models/res_country.py b/partner_contact_majority/models/res_country.py new file mode 100644 index 0000000..3e28133 --- /dev/null +++ b/partner_contact_majority/models/res_country.py @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). +from odoo import fields, models + + +class ResCountry(models.Model): + _inherit = "res.country" + + majority_age = fields.Integer(string="Majority age", default=18) diff --git a/partner_contact_majority/models/res_country_state.py b/partner_contact_majority/models/res_country_state.py new file mode 100644 index 0000000..2d071b2 --- /dev/null +++ b/partner_contact_majority/models/res_country_state.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). +from odoo import fields, models, api + + +class ResCountryState(models.Model): + _inherit = "res.country.state" + + majority_age = fields.Integer( + string="Majority age", + compute="_get_country_age", + inverse="_set_standalone_age", + store=True, + readonly=False, + ) + same_country_age = fields.Boolean( + string="Same age as country", + default=True, + ) + + @api.depends("country_id", "country_id.majority_age") + def _get_country_age(self): + for state in self.filtered("same_country_age"): + state.majority_age = state.country_id.majority_age + + def _set_standalone_age(self): + for state in self: + state.same_country_age = False diff --git a/partner_contact_majority/models/res_partner.py b/partner_contact_majority/models/res_partner.py new file mode 100644 index 0000000..993a02b --- /dev/null +++ b/partner_contact_majority/models/res_partner.py @@ -0,0 +1,95 @@ +# -*- coding: utf-8 -*- +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). +from dateutil.relativedelta import relativedelta + +from odoo import fields, models, api + +STATUS = [ + ("minor", "Minor"), + ("major", "Major"), +] + + +class ResPartner(models.Model): + _inherit = "res.partner" + + age = fields.Integer(store=True) + majority_date = fields.Date( + string="Majority date", + compute="_get_majority", + compute_sudo=True, + store=True, + ) + majority_years = fields.Integer( + string="Majority years", + compute="_get_majority", + compute_sudo=True, + store=True, + ) + is_major = fields.Boolean( + string="Is major", + compute="_get_majority", + compute_sudo=True, + ) + legal_status = fields.Selection( + selection=STATUS, + string="Legal status", + compute="_get_legal_status", + ) + emancipation_date = fields.Date( + string="Emancipation", + readonly=True, + ) + is_emancipated = fields.Boolean( + string="Is emancipated", + compute="_get_majority", + compute_sudo=True, + store=True, + ) + + @api.depends( + "nationality_id", + "nationality_id.majority_age", + "birthdate_date", + "emancipation_date", + ) + def _get_majority(self): + for partner in self: + country_age = ( + partner.nationality_id.majority_age if partner.nationality_id else False + ) + birth = partner.birthdate_date + emancipation = partner.emancipation_date + major = False + today = fields.Date.today() + if emancipation: + major = emancipation <= today + partner.is_emancipated = True + partner.majority_date = emancipation + partner.is_major = major + partner.majority_years = ( + relativedelta(today, emancipation).years + if major + else relativedelta(emancipation, today).years + ) + elif country_age and birth: + majority = birth + relativedelta(years=country_age) + major = majority <= today + partner.is_emancipated = False + partner.majority_date = majority + partner.is_major = major + partner.majority_years = ( + relativedelta(today, majority).years + if major + else relativedelta(majority, today).years + ) + else: + partner.is_emancipated = False + partner.majority_date = False + partner.is_major = False + partner.majority_years = 0 + + @api.depends("is_major") + def _get_legal_status(self): + for partner in self: + partner.legal_status = "major" if partner.is_major else "minor" diff --git a/partner_contact_majority/security/ir.model.access.csv b/partner_contact_majority/security/ir.model.access.csv new file mode 100644 index 0000000..6c3894d --- /dev/null +++ b/partner_contact_majority/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_res_partner_emancipate_all,All res.partner.relation.instance,model_res_partner_emancipate,,1,0,0,0 +access_res_partner_emancipate_group_partner_manager,Partner manager res.partner.relation.instance,model_res_partner_emancipate,base.group_system,1,1,1,1 \ No newline at end of file diff --git a/partner_contact_majority/security/ir_rule.xml b/partner_contact_majority/security/ir_rule.xml new file mode 100644 index 0000000..c5d0d52 --- /dev/null +++ b/partner_contact_majority/security/ir_rule.xml @@ -0,0 +1,19 @@ + + + + + + + + + + \ No newline at end of file diff --git a/partner_contact_majority/security/res_groups.xml b/partner_contact_majority/security/res_groups.xml new file mode 100644 index 0000000..86dbb2c --- /dev/null +++ b/partner_contact_majority/security/res_groups.xml @@ -0,0 +1,15 @@ + + + + + + + + \ No newline at end of file diff --git a/partner_contact_majority/views/res_country.xml b/partner_contact_majority/views/res_country.xml new file mode 100644 index 0000000..b7da865 --- /dev/null +++ b/partner_contact_majority/views/res_country.xml @@ -0,0 +1,16 @@ + + + + + res.country.view.form.inherit + res.country + + 30 + + + + + + + + \ No newline at end of file diff --git a/partner_contact_majority/views/res_country_state.xml b/partner_contact_majority/views/res_country_state.xml new file mode 100644 index 0000000..257ef7a --- /dev/null +++ b/partner_contact_majority/views/res_country_state.xml @@ -0,0 +1,42 @@ + + + + + res.country.state.view.tree.inherit + res.country.state + + 30 + + + + + + + + + + res.country.state.view.form.inherit + res.country.state + + 30 + + + + + + + + + + res.country.state.view.search.inherit + res.country.state + + 30 + + + + + + + + \ No newline at end of file diff --git a/partner_contact_majority/views/res_partner.xml b/partner_contact_majority/views/res_partner.xml new file mode 100644 index 0000000..782214d --- /dev/null +++ b/partner_contact_majority/views/res_partner.xml @@ -0,0 +1,36 @@ + + + + + + res.partner.form.inherit.majority + res.partner + + 18 + + + + + + + + + + + + \ No newline at end of file diff --git a/partner_contact_majority/wizard/__init__.py b/partner_contact_majority/wizard/__init__.py new file mode 100644 index 0000000..cd991d4 --- /dev/null +++ b/partner_contact_majority/wizard/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). +from . import res_partner_emancipate diff --git a/partner_contact_majority/wizard/res_partner_emancipate.py b/partner_contact_majority/wizard/res_partner_emancipate.py new file mode 100644 index 0000000..e9804e5 --- /dev/null +++ b/partner_contact_majority/wizard/res_partner_emancipate.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). +from odoo import fields, models, api + + +class ResPartnerEmancipate(models.TransientModel): + _name = "res.partner.emancipate" + _description = "Partner Emancipation Wizard" + _rec_name = "partner_id" + + partner_id = fields.Many2one("res.partner", string="Partner", required=True) + emancipation_date = fields.Date( + string="Emancipation date", + required=True, + ) + + def emancipate_partner(self): + if self.partner_id.is_company: + return {"type": "ir.actions.act_window_close"} + self.partner_id.write({"emancipation_date": self.emancipation_date}) diff --git a/partner_contact_majority/wizard/res_partner_emancipate.xml b/partner_contact_majority/wizard/res_partner_emancipate.xml new file mode 100644 index 0000000..3913d53 --- /dev/null +++ b/partner_contact_majority/wizard/res_partner_emancipate.xml @@ -0,0 +1,45 @@ + + + + + res.partner.emancipate.view.form + res.partner.emancipate + +
+ + + + + +
+
+
+
+
+
+ + + Emancipate + res.partner.emancipate + form + + + new + {'default_partner_id': active_id} + + + + + Emancipate + + + form + code + + + + +
\ No newline at end of file