From 91d52d1852222f7ce30eb7c1f7c5392a9a3967f3 Mon Sep 17 00:00:00 2001 From: Anjeel Haria Date: Wed, 13 Nov 2024 15:10:35 +0530 Subject: [PATCH] Updates as per suggestions Updates as per suggestions Pre-commit fixes Make mass_mailing_membership_group auto installed (auto_install = True) Updated membership modules Added partner_cde module updates Changed from AbstractModel to Model Changes to add applications menu in Members,move wants_to_collaborate and type field to membership_group, made allow_membership_registration True by default pre-commit fix pre-commit fix --- mass_mailing_membership_group/__manifest__.py | 1 + .../views/membership_group_view.xml | 2 +- membership_contribution/__init__.py | 2 +- membership_contribution/models/__init__.py | 2 +- membership_group/menuitems.xml | 12 +- membership_group/models/membership_group.py | 20 +- .../models/membership_group_member.py | 19 + .../views/membership_group_member_view.xml | 19 +- .../views/membership_group_view.xml | 4 +- membership_group/views/res_partner_view.xml | 14 +- membership_hr/__manifest__.py | 4 +- membership_hr/data/hr_department_demo.xml | 12 +- membership_hr/data/hr_employee_demo.xml | 6 +- membership_hr/data/hr_job_demo.xml | 4 +- membership_hr/data/res_users_demo.xml | 6 +- membership_hr/models/__init__.py | 2 +- membership_hr/models/hr_department.py | 4 +- membership_hr/models/hr_employee.py | 6 +- membership_hr/models/membership_group.py | 36 ++ membership_hr/models/membership_section.py | 34 -- membership_hr/tests/__init__.py | 1 + membership_hr/tests/test_membership_hr.py | 24 + membership_hr/views/hr_department.xml | 2 +- membership_hr/views/hr_employee_view.xml | 5 +- ...rship_section.xml => membership_group.xml} | 14 +- membership_hr_recruitment/__manifest__.py | 3 +- .../data/hr_applicant_demo.xml | 4 +- membership_hr_recruitment/menuitems.xml | 9 + .../models/hr_applicant.py | 4 +- membership_hr_recruitment/tests/__init__.py | 1 + .../tests/test_membership_hr_recruitment.py | 30 ++ .../views/hr_applicant_view.xml | 5 +- membership_sale_prorate/README.rst | 79 +++- membership_sale_prorate/__manifest__.py | 8 +- .../models/sale_order_line.py | 4 +- .../readme/CONTRIBUTORS.rst | 1 + .../readme/DESCRIPTION.rst | 1 + .../static/description/index.html | 423 ++++++++++++++++++ membership_sale_prorate/tests/__init__.py | 2 + .../tests/test_membership_sale_prorate.py | 74 +++ partner_cde/__init__.py | 1 + partner_cde/__manifest__.py | 13 + partner_cde/models/__init__.py | 1 + partner_cde/models/res_partner.py | 11 + partner_cde/views/res_partner_view.xml | 14 + .../README.rst | 5 + .../__init__.py | 1 + .../__manifest__.py | 18 + .../controllers/__init__.py | 1 + .../controllers/main.py | 166 +++++++ .../readme/CONTRIBUTORS.rst | 1 + .../readme/DESCRIPTION.rst | 1 + .../templates/website.xml | 86 ++++ website_membership_group/__init__.py | 2 + website_membership_group/__manifest__.py | 19 + .../controllers/__init__.py | 1 + website_membership_group/controllers/main.py | 36 ++ website_membership_group/models/__init__.py | 1 + .../models/membership_group.py | 29 ++ .../readme/CONTRIBUTORS.rst | 1 + .../readme/DESCRIPTION.rst | 1 + .../templates/website.xml | 29 ++ .../views/membership_group_view.xml | 39 ++ .../__manifest__.py | 14 +- .../controllers/main.py | 298 +++++++----- .../controllers/portal.py | 14 +- .../data/res_partner_category_data.xml | 6 + .../data/res_partner_demo.xml | 26 +- website_membership_registration/i18n/nl.po | 83 ++-- .../models/__init__.py | 3 +- .../models/membership_group.py | 54 +++ .../models/res_config_settings.py | 29 +- .../models/res_partner.py | 67 ++- .../models/website.py | 32 +- .../website_membership_registration.editor.js | 86 ++++ .../scss/website_membership_registration.scss | 2 +- .../templates/website.xml | 140 +++--- .../views/hr_applicant_view.xml | 2 +- .../views/hr_employee_view.xml | 2 +- .../views/membership_group_view.xml | 15 + .../views/membership_section_view.xml | 15 - .../views/res_config_settings_view.xml | 43 -- .../views/res_partner_view.xml | 16 +- .../views/snippets/snippets.xml | 30 ++ .../__init__.py | 1 + .../__manifest__.py | 18 + .../controllers/__init__.py | 2 + .../controllers/main.py | 26 ++ .../controllers/portal.py | 9 + .../templates/website.xml | 67 +++ .../views/snippets/snippets.xml | 19 + .../__init__.py | 1 + .../__manifest__.py | 18 + .../controllers/__init__.py | 2 + .../controllers/main.py | 24 + .../controllers/portal.py | 5 + .../templates/website.xml | 67 +++ .../views/snippets/snippets.xml | 19 + .../__init__.py | 0 .../__manifest__.py | 19 + .../views/res_partner_view.xml | 20 + .../__init__.py | 2 + .../__manifest__.py | 20 + .../controllers/__init__.py | 2 + .../controllers/main.py | 44 ++ .../controllers/portal.py | 18 + .../models/__init__.py | 1 + .../models/res_partner.py | 7 + .../templates/website.xml | 29 ++ .../views/res_partner_view.xml | 15 + .../views/snippets/snippets.xml | 11 + 111 files changed, 2341 insertions(+), 482 deletions(-) create mode 100644 membership_hr/models/membership_group.py delete mode 100644 membership_hr/models/membership_section.py create mode 100644 membership_hr/tests/__init__.py create mode 100644 membership_hr/tests/test_membership_hr.py rename membership_hr/views/{membership_section.xml => membership_group.xml} (50%) create mode 100644 membership_hr_recruitment/menuitems.xml create mode 100644 membership_hr_recruitment/tests/__init__.py create mode 100644 membership_hr_recruitment/tests/test_membership_hr_recruitment.py create mode 100644 membership_sale_prorate/readme/CONTRIBUTORS.rst create mode 100644 membership_sale_prorate/readme/DESCRIPTION.rst create mode 100644 membership_sale_prorate/static/description/index.html create mode 100644 membership_sale_prorate/tests/__init__.py create mode 100644 membership_sale_prorate/tests/test_membership_sale_prorate.py create mode 100644 partner_cde/__init__.py create mode 100644 partner_cde/__manifest__.py create mode 100644 partner_cde/models/__init__.py create mode 100644 partner_cde/models/res_partner.py create mode 100644 partner_cde/views/res_partner_view.xml create mode 100644 website_mass_mailing_membership_group/README.rst create mode 100644 website_mass_mailing_membership_group/__init__.py create mode 100644 website_mass_mailing_membership_group/__manifest__.py create mode 100644 website_mass_mailing_membership_group/controllers/__init__.py create mode 100644 website_mass_mailing_membership_group/controllers/main.py create mode 100644 website_mass_mailing_membership_group/readme/CONTRIBUTORS.rst create mode 100644 website_mass_mailing_membership_group/readme/DESCRIPTION.rst create mode 100644 website_mass_mailing_membership_group/templates/website.xml create mode 100644 website_membership_group/__init__.py create mode 100644 website_membership_group/__manifest__.py create mode 100644 website_membership_group/controllers/__init__.py create mode 100644 website_membership_group/controllers/main.py create mode 100644 website_membership_group/models/__init__.py create mode 100644 website_membership_group/models/membership_group.py create mode 100644 website_membership_group/readme/CONTRIBUTORS.rst create mode 100644 website_membership_group/readme/DESCRIPTION.rst create mode 100644 website_membership_group/templates/website.xml create mode 100644 website_membership_group/views/membership_group_view.xml create mode 100644 website_membership_registration/data/res_partner_category_data.xml create mode 100644 website_membership_registration/models/membership_group.py create mode 100644 website_membership_registration/static/src/js/website_membership_registration.editor.js create mode 100644 website_membership_registration/views/membership_group_view.xml delete mode 100644 website_membership_registration/views/membership_section_view.xml create mode 100644 website_membership_registration/views/snippets/snippets.xml create mode 100644 website_membership_registration_partner_cde/__init__.py create mode 100644 website_membership_registration_partner_cde/__manifest__.py create mode 100644 website_membership_registration_partner_cde/controllers/__init__.py create mode 100644 website_membership_registration_partner_cde/controllers/main.py create mode 100644 website_membership_registration_partner_cde/controllers/portal.py create mode 100644 website_membership_registration_partner_cde/templates/website.xml create mode 100644 website_membership_registration_partner_cde/views/snippets/snippets.xml create mode 100644 website_membership_registration_partner_contact_birthdate/__init__.py create mode 100644 website_membership_registration_partner_contact_birthdate/__manifest__.py create mode 100644 website_membership_registration_partner_contact_birthdate/controllers/__init__.py create mode 100644 website_membership_registration_partner_contact_birthdate/controllers/main.py create mode 100644 website_membership_registration_partner_contact_birthdate/controllers/portal.py create mode 100644 website_membership_registration_partner_contact_birthdate/templates/website.xml create mode 100644 website_membership_registration_partner_contact_birthdate/views/snippets/snippets.xml create mode 100644 website_membership_registration_project_role_members/__init__.py create mode 100644 website_membership_registration_project_role_members/__manifest__.py create mode 100644 website_membership_registration_project_role_members/views/res_partner_view.xml create mode 100644 website_membership_registration_social/__init__.py create mode 100644 website_membership_registration_social/__manifest__.py create mode 100644 website_membership_registration_social/controllers/__init__.py create mode 100644 website_membership_registration_social/controllers/main.py create mode 100644 website_membership_registration_social/controllers/portal.py create mode 100644 website_membership_registration_social/models/__init__.py create mode 100644 website_membership_registration_social/models/res_partner.py create mode 100644 website_membership_registration_social/templates/website.xml create mode 100644 website_membership_registration_social/views/res_partner_view.xml create mode 100644 website_membership_registration_social/views/snippets/snippets.xml diff --git a/mass_mailing_membership_group/__manifest__.py b/mass_mailing_membership_group/__manifest__.py index 224035d..85b0406 100644 --- a/mass_mailing_membership_group/__manifest__.py +++ b/mass_mailing_membership_group/__manifest__.py @@ -25,4 +25,5 @@ "data/mailing_contact_demo.xml", "data/res_partner_demo.xml", ], + "auto_install": True, } diff --git a/mass_mailing_membership_group/views/membership_group_view.xml b/mass_mailing_membership_group/views/membership_group_view.xml index 0085809..44c6abf 100644 --- a/mass_mailing_membership_group/views/membership_group_view.xml +++ b/mass_mailing_membership_group/views/membership_group_view.xml @@ -5,7 +5,7 @@ membership.group - + diff --git a/membership_contribution/__init__.py b/membership_contribution/__init__.py index 0650744..9a7e03e 100644 --- a/membership_contribution/__init__.py +++ b/membership_contribution/__init__.py @@ -1 +1 @@ -from . import models +from . import models \ No newline at end of file diff --git a/membership_contribution/models/__init__.py b/membership_contribution/models/__init__.py index 91fed54..4c58886 100644 --- a/membership_contribution/models/__init__.py +++ b/membership_contribution/models/__init__.py @@ -1 +1 @@ -from . import res_partner +from . import res_partner \ No newline at end of file diff --git a/membership_group/menuitems.xml b/membership_group/menuitems.xml index d283672..eb46ccc 100644 --- a/membership_group/menuitems.xml +++ b/membership_group/menuitems.xml @@ -10,18 +10,24 @@ + + diff --git a/membership_group/models/membership_group.py b/membership_group/models/membership_group.py index b3d9d88..5474aa6 100644 --- a/membership_group/models/membership_group.py +++ b/membership_group/models/membership_group.py @@ -6,16 +6,21 @@ class MembershipGroup(models.Model): _description = "Membership Group" _parent_store = True _parent_name = "parent_id" + _rec_name = "complete_name" + _order = "complete_name" name = fields.Char() + complete_name = fields.Char( + compute="_compute_complete_name", recursive=True, store=True + ) membership_group_member_ids = fields.One2many("membership.group.member", "group_id") parent_id = fields.Many2one( - comodel_name="membership.group", string="Parent Membership Group", index=True + comodel_name="membership.group", string="Parent", index=True ) child_ids = fields.One2many( comodel_name="membership.group", inverse_name="parent_id", - string="Sub Membership Groups", + string="Subgroups", ) parent_path = fields.Char(index=True, unaccent=False) partner_ids = fields.Many2many( @@ -23,6 +28,17 @@ class MembershipGroup(models.Model): ) partner_ids_count = fields.Integer("# of Members", compute="_compute_partner_ids") + @api.depends("name", "parent_id.complete_name") + def _compute_complete_name(self): + for group in self: + if group.parent_id: + group.complete_name = "%s / %s" % ( + group.parent_id.complete_name, + group.name, + ) + else: + group.complete_name = group.name + @api.depends( "membership_group_member_ids", "membership_group_member_ids.partner_id" ) diff --git a/membership_group/models/membership_group_member.py b/membership_group/models/membership_group_member.py index 1d8e766..1f83d79 100644 --- a/membership_group/models/membership_group_member.py +++ b/membership_group/models/membership_group_member.py @@ -7,3 +7,22 @@ class MembershipGroupMember(models.Model): partner_id = fields.Many2one("res.partner", required=True, ondelete="cascade") group_id = fields.Many2one("membership.group", required=True, ondelete="cascade") + wants_to_collaborate = fields.Boolean() + type = fields.Selection( + [ + ("follower", "Follower"), + ("applicant", "Applicant"), + ("applicant_follower", "Applicant / Follower"), + ("collaborator_follower", "Collaborator / Follower"), + ("collaborator", "Collaborator"), + ("committee", "Committee"), + ], + ) + + _sql_constraints = [ + ( + "partner_group_uniq", + "unique(partner_id, group_id)", + "Member already exists for this group!", + ) + ] diff --git a/membership_group/views/membership_group_member_view.xml b/membership_group/views/membership_group_member_view.xml index 6528a2d..f8ff6b2 100644 --- a/membership_group/views/membership_group_member_view.xml +++ b/membership_group/views/membership_group_member_view.xml @@ -4,22 +4,37 @@ membership.group.member - + + + + + membership.group.member + + + + + + + + + membership.group.member + + @@ -28,6 +43,6 @@ Membership Group Members membership.group.member - tree + tree,pivot diff --git a/membership_group/views/membership_group_view.xml b/membership_group/views/membership_group_view.xml index 3ee8b59..8d8d63c 100644 --- a/membership_group/views/membership_group_view.xml +++ b/membership_group/views/membership_group_view.xml @@ -5,7 +5,7 @@ membership.group - + @@ -60,7 +60,7 @@ - + diff --git a/membership_group/views/res_partner_view.xml b/membership_group/views/res_partner_view.xml index 417f861..959674d 100644 --- a/membership_group/views/res_partner_view.xml +++ b/membership_group/views/res_partner_view.xml @@ -21,11 +21,15 @@ - - - - - + + + + + + + + + diff --git a/membership_hr/__manifest__.py b/membership_hr/__manifest__.py index 6f492e1..2ba60be 100644 --- a/membership_hr/__manifest__.py +++ b/membership_hr/__manifest__.py @@ -10,13 +10,13 @@ "website": "https://www.onestein.nl", "depends": [ "membership", - "membership_section", + "membership_group", "hr", ], "data": [ "views/hr_employee_view.xml", "views/hr_department.xml", - "views/membership_section.xml", + "views/membership_group.xml", ], "demo": [ "data/hr_department_demo.xml", diff --git a/membership_hr/data/hr_department_demo.xml b/membership_hr/data/hr_department_demo.xml index 753ff77..77e09cc 100644 --- a/membership_hr/data/hr_department_demo.xml +++ b/membership_hr/data/hr_department_demo.xml @@ -1,22 +1,20 @@ - - + - + Executive Board - + Marketing Team - + Finance Committee - + Youth Club - diff --git a/membership_hr/data/hr_employee_demo.xml b/membership_hr/data/hr_employee_demo.xml index 16e988d..1c8ce47 100644 --- a/membership_hr/data/hr_employee_demo.xml +++ b/membership_hr/data/hr_employee_demo.xml @@ -1,15 +1,13 @@ - - + John Doe - + member - diff --git a/membership_hr/data/hr_job_demo.xml b/membership_hr/data/hr_job_demo.xml index fef8c77..939ad60 100644 --- a/membership_hr/data/hr_job_demo.xml +++ b/membership_hr/data/hr_job_demo.xml @@ -1,10 +1,8 @@ - - + Member - diff --git a/membership_hr/data/res_users_demo.xml b/membership_hr/data/res_users_demo.xml index b8c3e39..a24ee08 100644 --- a/membership_hr/data/res_users_demo.xml +++ b/membership_hr/data/res_users_demo.xml @@ -1,14 +1,12 @@ - - + - + demo_member demo_member - diff --git a/membership_hr/models/__init__.py b/membership_hr/models/__init__.py index 0d1d1eb..23ae695 100644 --- a/membership_hr/models/__init__.py +++ b/membership_hr/models/__init__.py @@ -1,4 +1,4 @@ from . import hr_department from . import hr_employee_base from . import hr_employee -from . import membership_section +from . import membership_group diff --git a/membership_hr/models/hr_department.py b/membership_hr/models/hr_department.py index 15d33fd..3691a40 100644 --- a/membership_hr/models/hr_department.py +++ b/membership_hr/models/hr_department.py @@ -1,7 +1,7 @@ from odoo import fields, models -class HRDepartment(models.AbstractModel): +class HRDepartment(models.Model): _inherit = "hr.department" - section_id = fields.Many2one("membership.section") + membership_group_id = fields.Many2one("membership.group") diff --git a/membership_hr/models/hr_employee.py b/membership_hr/models/hr_employee.py index 100ab09..b06b0a7 100644 --- a/membership_hr/models/hr_employee.py +++ b/membership_hr/models/hr_employee.py @@ -1,9 +1,9 @@ from odoo import fields, models -class HREmployee(models.AbstractModel): +class HREmployee(models.Model): _inherit = "hr.employee" - section_membership_ids = fields.One2many( - related="user_partner_id.section_membership_ids" + membership_group_member_ids = fields.One2many( + related="user_partner_id.membership_group_member_ids" ) diff --git a/membership_hr/models/membership_group.py b/membership_hr/models/membership_group.py new file mode 100644 index 0000000..4206cdd --- /dev/null +++ b/membership_hr/models/membership_group.py @@ -0,0 +1,36 @@ +from odoo import api, fields, models + + +class MembershipGroup(models.AbstractModel): + _inherit = "membership.group" + + department_id = fields.Many2one( + "hr.department", + compute="_compute_department", + inverse="_inverse_department", + store=True, + readonly=False, + ) + + department_ids = fields.One2many( + "hr.department", "membership_group_id", string="Departments" + ) + + @api.depends("department_ids") + def _compute_department(self): + for membership_group in self: + membership_group.department_id = ( + membership_group.department_ids + and membership_group.department_ids[0] + or False + ) + + def _inverse_department(self): + hr_department_obj = self.env["hr.department"] + for membership_group in self: + if membership_group.department_ids: + department = hr_department_obj.browse( + membership_group.department_ids[0].id + ) + department.membership_group_id = False + membership_group.department_id.membership_group_id = membership_group diff --git a/membership_hr/models/membership_section.py b/membership_hr/models/membership_section.py deleted file mode 100644 index 433904a..0000000 --- a/membership_hr/models/membership_section.py +++ /dev/null @@ -1,34 +0,0 @@ -from odoo import api, fields, models - - -class MembershipSection(models.AbstractModel): - _inherit = "membership.section" - - department_id = fields.Many2one( - "hr.department", - compute="_compute_department", - inverse="_inverse_department", - store=True, - readonly=False, - ) - - department_ids = fields.One2many( - "hr.department", "section_id", string="Departments" - ) - - @api.depends("department_ids") - def _compute_department(self): - for section in self: - if len(self.department_ids) > 0: - section.department_id = section.department_ids[0] - else: - section.department_id = False - - def _inverse_department(self): - for section in self: - if len(section.department_ids) > 0: - department = self.env["hr.department"].browse( - section.department_ids[0].id - ) - department.section_id = False - section.department_id.section_id = section diff --git a/membership_hr/tests/__init__.py b/membership_hr/tests/__init__.py new file mode 100644 index 0000000..d0c2641 --- /dev/null +++ b/membership_hr/tests/__init__.py @@ -0,0 +1 @@ +from . import test_membership_hr diff --git a/membership_hr/tests/test_membership_hr.py b/membership_hr/tests/test_membership_hr.py new file mode 100644 index 0000000..9f1433f --- /dev/null +++ b/membership_hr/tests/test_membership_hr.py @@ -0,0 +1,24 @@ +from odoo.tests import common + + +class TestMembershipHr(common.TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + membership_group_obj = cls.env["membership.group"] + hr_department_obj = cls.env["hr.department"] + + cls.group_1 = membership_group_obj.create({"name": "Test Group 1"}) + cls.group_2 = membership_group_obj.create({"name": "Test Group 2"}) + cls.hr_department_1 = hr_department_obj.create({"name": "Test Department 1"}) + cls.hr_department_2 = hr_department_obj.create({"name": "Test Department 2"}) + + def test_01_membership_hr(self): + self.group_1.department_ids = [ + (6, 0, [self.hr_department_1.id, self.hr_department_2.id]) + ] + self.assertEqual(self.group_1.department_id, self.hr_department_1) + self.group_1.department_id = self.hr_department_2.id + self.assertEqual(self.hr_department_2.membership_group_id, self.group_1) + self.group_2.department_id = self.hr_department_1.id + self.assertEqual(self.hr_department_1.membership_group_id, self.group_2) diff --git a/membership_hr/views/hr_department.xml b/membership_hr/views/hr_department.xml index 4313f0f..9818589 100644 --- a/membership_hr/views/hr_department.xml +++ b/membership_hr/views/hr_department.xml @@ -6,7 +6,7 @@ - + diff --git a/membership_hr/views/hr_employee_view.xml b/membership_hr/views/hr_employee_view.xml index 3dbf5b4..36aa61a 100644 --- a/membership_hr/views/hr_employee_view.xml +++ b/membership_hr/views/hr_employee_view.xml @@ -8,10 +8,9 @@ - + - - + diff --git a/membership_hr/views/membership_section.xml b/membership_hr/views/membership_group.xml similarity index 50% rename from membership_hr/views/membership_section.xml rename to membership_hr/views/membership_group.xml index e2388f9..1b81186 100644 --- a/membership_hr/views/membership_section.xml +++ b/membership_hr/views/membership_group.xml @@ -1,19 +1,19 @@ - - membership.section - + + membership.group + - + - - membership.section - + + membership.group + diff --git a/membership_hr_recruitment/__manifest__.py b/membership_hr_recruitment/__manifest__.py index 232a886..082c1ff 100644 --- a/membership_hr_recruitment/__manifest__.py +++ b/membership_hr_recruitment/__manifest__.py @@ -10,11 +10,12 @@ "website": "https://www.onestein.nl", "depends": [ "membership_hr", - "membership_section", + "membership_group", "hr_recruitment", ], "data": [ "views/hr_applicant_view.xml", + "menuitems.xml", ], "demo": [ "data/hr_applicant_demo.xml", diff --git a/membership_hr_recruitment/data/hr_applicant_demo.xml b/membership_hr_recruitment/data/hr_applicant_demo.xml index a9e1da9..4e6d838 100644 --- a/membership_hr_recruitment/data/hr_applicant_demo.xml +++ b/membership_hr_recruitment/data/hr_applicant_demo.xml @@ -5,10 +5,10 @@ Aspiring Member - + 1 - + Jane Smith diff --git a/membership_hr_recruitment/menuitems.xml b/membership_hr_recruitment/menuitems.xml new file mode 100644 index 0000000..cf2c157 --- /dev/null +++ b/membership_hr_recruitment/menuitems.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/membership_hr_recruitment/models/hr_applicant.py b/membership_hr_recruitment/models/hr_applicant.py index f5a5bfd..83ffa63 100644 --- a/membership_hr_recruitment/models/hr_applicant.py +++ b/membership_hr_recruitment/models/hr_applicant.py @@ -5,8 +5,8 @@ class HRApplicant(models.Model): _inherit = "hr.applicant" membership_applicant = fields.Boolean() - section_membership_ids = fields.One2many( - related="partner_id.section_membership_ids" + membership_group_member_ids = fields.One2many( + related="partner_id.membership_group_member_ids" ) def create_employee_from_applicant(self): diff --git a/membership_hr_recruitment/tests/__init__.py b/membership_hr_recruitment/tests/__init__.py new file mode 100644 index 0000000..aebb8f6 --- /dev/null +++ b/membership_hr_recruitment/tests/__init__.py @@ -0,0 +1 @@ +from . import test_membership_hr_recruitment diff --git a/membership_hr_recruitment/tests/test_membership_hr_recruitment.py b/membership_hr_recruitment/tests/test_membership_hr_recruitment.py new file mode 100644 index 0000000..5029e54 --- /dev/null +++ b/membership_hr_recruitment/tests/test_membership_hr_recruitment.py @@ -0,0 +1,30 @@ +from odoo.tests import common + + +class TestMembershipHrRecruitment(common.TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.user = cls.env["res.users"].create( + {"name": "John", "login": "test1", "email": "john@test.com"} + ) + cls.applicant_1 = cls.env["hr.applicant"].create( + { + "name": "John", + "partner_id": cls.user.partner_id.id, + "membership_applicant": True, + } + ) + + def test_01_default_values_for_employee_for_member_applicant(self): + action = self.applicant_1.create_employee_from_applicant() + self.assertEqual(action["context"]["default_employee_type"], "member") + self.assertEqual(action["context"]["default_user_id"], self.user.id) + + def test_02_user_groups_for_member_employee_user(self): + self.env["hr.employee"].create( + {"name": "Mike", "employee_type": "member", "user_id": self.user.id} + ) + self.assertIn( + self.env["hr.employee"].get_member_groups()[0], self.user.groups_id.ids + ) diff --git a/membership_hr_recruitment/views/hr_applicant_view.xml b/membership_hr_recruitment/views/hr_applicant_view.xml index 30d4343..e1461c3 100644 --- a/membership_hr_recruitment/views/hr_applicant_view.xml +++ b/membership_hr_recruitment/views/hr_applicant_view.xml @@ -10,10 +10,9 @@ - + - - + diff --git a/membership_sale_prorate/README.rst b/membership_sale_prorate/README.rst index f25b9bf..dc9d9f7 100644 --- a/membership_sale_prorate/README.rst +++ b/membership_sale_prorate/README.rst @@ -1,5 +1,76 @@ -========================================= -Prorate membership fee - Sale Integration -========================================= +======================= +Membership Sale Prorate +======================= -Prorate membership fee - Sale Integration +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:481e8310c0b91adbd533f0662f28937fa890d6ca476e734e32059244e832f3fb + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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%2Fvertical--association-lightgray.png?logo=github + :target: https://github.com/OCA/vertical-association/tree/16.0/membership_sale_prorate + :alt: OCA/vertical-association +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/vertical-association-16-0/vertical-association-16-0-membership_sale_prorate + :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/vertical-association&target_branch=16.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module calculates and sets the quantity for sale order lines having prorate membership products so that the sale order line price is calculated accordingly + +**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 +~~~~~~~ + +* Onestein + +Contributors +~~~~~~~~~~~~ + +* `Onestein `_ + +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/vertical-association `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/membership_sale_prorate/__manifest__.py b/membership_sale_prorate/__manifest__.py index 82fe19f..3463dd6 100644 --- a/membership_sale_prorate/__manifest__.py +++ b/membership_sale_prorate/__manifest__.py @@ -1,12 +1,14 @@ # Copyright 2024 Onestein () # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - { - "name": "Prorate membership fee - Sale Integration", + "name": "Membership Sale Prorate", + "summary": "Calculates and sets the quantity for sale order lines having " + "prorate membership products so that the sale order line price " + "is calculated accordingly", "version": "16.0.1.0.0", "license": "AGPL-3", "category": "Association", - "author": "Onestein", + "author": "Onestein, Odoo Community Association (OCA)", "website": "https://www.onestein.nl", "depends": [ "membership", diff --git a/membership_sale_prorate/models/sale_order_line.py b/membership_sale_prorate/models/sale_order_line.py index 008e453..3513dd3 100644 --- a/membership_sale_prorate/models/sale_order_line.py +++ b/membership_sale_prorate/models/sale_order_line.py @@ -1,3 +1,4 @@ +# Copyright 2024 Onestein () from datetime import timedelta from odoo import api, fields, models @@ -17,6 +18,8 @@ def _prepare_sale_line_prorate_vals(self, sale_line): date_from, date_to = self.env["account.move.line"]._get_membership_interval( product, date_order ) + if not date_from: + return {"quantity": 1.0} if date_order < date_from: date_order = date_from if date_order > date_to: @@ -28,7 +31,6 @@ def _prepare_sale_line_prorate_vals(self, sale_line): "quantity": round( float(real_duration.days) / theoretical_duration.days, 2 ), - "date_from": date_order, } @api.model_create_multi diff --git a/membership_sale_prorate/readme/CONTRIBUTORS.rst b/membership_sale_prorate/readme/CONTRIBUTORS.rst new file mode 100644 index 0000000..85125ab --- /dev/null +++ b/membership_sale_prorate/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ +* `Onestein `_ diff --git a/membership_sale_prorate/readme/DESCRIPTION.rst b/membership_sale_prorate/readme/DESCRIPTION.rst new file mode 100644 index 0000000..f6b4c88 --- /dev/null +++ b/membership_sale_prorate/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +This module calculates and sets the quantity for sale order lines having prorate membership products so that the sale order line price is calculated accordingly diff --git a/membership_sale_prorate/static/description/index.html b/membership_sale_prorate/static/description/index.html new file mode 100644 index 0000000..1be12b7 --- /dev/null +++ b/membership_sale_prorate/static/description/index.html @@ -0,0 +1,423 @@ + + + + + +Membership Sale Prorate + + + +
+

Membership Sale Prorate

+ + +

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

+

This module calculates and sets the quantity for sale order lines having prorate membership products so that the sale order line price is calculated accordingly

+

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

+
    +
  • Onestein
  • +
+
+ +
+

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

+

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

+
+
+
+ + diff --git a/membership_sale_prorate/tests/__init__.py b/membership_sale_prorate/tests/__init__.py new file mode 100644 index 0000000..6ca1c1e --- /dev/null +++ b/membership_sale_prorate/tests/__init__.py @@ -0,0 +1,2 @@ +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html +from . import test_membership_sale_prorate diff --git a/membership_sale_prorate/tests/test_membership_sale_prorate.py b/membership_sale_prorate/tests/test_membership_sale_prorate.py new file mode 100644 index 0000000..de825e3 --- /dev/null +++ b/membership_sale_prorate/tests/test_membership_sale_prorate.py @@ -0,0 +1,74 @@ +# Copyright 2024 Onestein () +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html +from datetime import date +from unittest.mock import patch + +from odoo import fields +from odoo.tests.common import TransactionCase + +from odoo.addons.membership_prorate.models.account_move_line import AccountMoveLine + + +class TestMembershipProrate(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.product = cls.env["product.product"].create( + { + "name": "Membership product with prorate", + "membership": True, + "membership_prorate": True, + "membership_date_from": "2017-01-01", + "membership_date_to": "2017-12-31", + } + ) + cls.partner = cls.env["res.partner"].create( + { + "name": "Test", + } + ) + + def create_membership_sale(self, date_order=False): + vals = { + "partner_id": self.partner.id, + "date_order": date_order or fields.Date.today(), + "order_line": [ + ( + 0, + None, + { + "product_id": self.product.id, + "product_uom_qty": 1, + }, + ) + ], + } + return self.env["sale.order"].create(vals) + + def test_create_sale_membership_product_wo_prorate(self): + self.product.membership_prorate = False + sale = self.create_membership_sale() + self.assertEqual(sale.order_line[0].product_uom_qty, 1.0) + + def test_create_sale_membership_product_prorate(self): + sale = self.create_membership_sale(date_order=date(2017, 7, 1)) + self.assertAlmostEqual(sale.order_line[0].product_uom_qty, 0.50, 2) + sale = self.create_membership_sale(date_order=date(2016, 7, 1)) + self.assertAlmostEqual(sale.order_line[0].product_uom_qty, 1.0, 2) + sale = self.create_membership_sale(date_order=date(2018, 7, 1)) + self.assertAlmostEqual(sale.order_line[0].product_uom_qty, 0, 2) + + def test_create_sale_membership_prorate_variable_period(self): + """It is a test for case where membership type is set to variable + on product with membership_prorate_variable_period not installed""" + + def _get_membership_interval(self, product, date): + return False, False + + with patch.object( + AccountMoveLine, + "_get_membership_interval", + _get_membership_interval, + ): + sale = self.create_membership_sale(date_order=date(2017, 7, 1)) + self.assertEqual(sale.order_line[0].product_uom_qty, 1.0) diff --git a/partner_cde/__init__.py b/partner_cde/__init__.py new file mode 100644 index 0000000..0650744 --- /dev/null +++ b/partner_cde/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/partner_cde/__manifest__.py b/partner_cde/__manifest__.py new file mode 100644 index 0000000..b91a769 --- /dev/null +++ b/partner_cde/__manifest__.py @@ -0,0 +1,13 @@ +{ + "name": "Partner extension for collaborative development environments", + "summary": "Allows to capture details of collaborative development environments for partners", + "category": "Membership", + "version": "16.0.1.0.0", + "author": "Onestein", + "website": "https://www.onestein.nl", + "license": "AGPL-3", + "depends": ["base"], + "data": [ + "views/res_partner_view.xml", + ], +} diff --git a/partner_cde/models/__init__.py b/partner_cde/models/__init__.py new file mode 100644 index 0000000..91fed54 --- /dev/null +++ b/partner_cde/models/__init__.py @@ -0,0 +1 @@ +from . import res_partner diff --git a/partner_cde/models/res_partner.py b/partner_cde/models/res_partner.py new file mode 100644 index 0000000..09a5c65 --- /dev/null +++ b/partner_cde/models/res_partner.py @@ -0,0 +1,11 @@ +from odoo import fields, models + + +class ResPartner(models.Model): + _inherit = "res.partner" + + github_login = fields.Char(string="Github Username") + gitlab_email = fields.Char(help="Can be used to reconcile commits") + gitlab_username = fields.Char( + help="Can be used to reconcile merge requests, issues, comment, and reviews", + ) diff --git a/partner_cde/views/res_partner_view.xml b/partner_cde/views/res_partner_view.xml new file mode 100644 index 0000000..839fd4b --- /dev/null +++ b/partner_cde/views/res_partner_view.xml @@ -0,0 +1,14 @@ + + + + res.partner + + + + + + + + + + diff --git a/website_mass_mailing_membership_group/README.rst b/website_mass_mailing_membership_group/README.rst new file mode 100644 index 0000000..2cf46e5 --- /dev/null +++ b/website_mass_mailing_membership_group/README.rst @@ -0,0 +1,5 @@ +===================================== +Website Mass Mailing Membership Group +===================================== + +Website Mass Mailing Membership Group diff --git a/website_mass_mailing_membership_group/__init__.py b/website_mass_mailing_membership_group/__init__.py new file mode 100644 index 0000000..e046e49 --- /dev/null +++ b/website_mass_mailing_membership_group/__init__.py @@ -0,0 +1 @@ +from . import controllers diff --git a/website_mass_mailing_membership_group/__manifest__.py b/website_mass_mailing_membership_group/__manifest__.py new file mode 100644 index 0000000..e406e53 --- /dev/null +++ b/website_mass_mailing_membership_group/__manifest__.py @@ -0,0 +1,18 @@ +# Copyright 2020 Onestein () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +{ + "name": "Website Mass Mailing Membership Group", + "category": "Membership", + "version": "16.0.1.0.0", + "author": "Onestein", + "license": "AGPL-3", + "website": "https://www.onestein.nl", + "depends": [ + "website_membership_group", + "mass_mailing_membership_group", + ], + "data": [ + "templates/website.xml", + ], +} diff --git a/website_mass_mailing_membership_group/controllers/__init__.py b/website_mass_mailing_membership_group/controllers/__init__.py new file mode 100644 index 0000000..12a7e52 --- /dev/null +++ b/website_mass_mailing_membership_group/controllers/__init__.py @@ -0,0 +1 @@ +from . import main diff --git a/website_mass_mailing_membership_group/controllers/main.py b/website_mass_mailing_membership_group/controllers/main.py new file mode 100644 index 0000000..cfb07d6 --- /dev/null +++ b/website_mass_mailing_membership_group/controllers/main.py @@ -0,0 +1,166 @@ +from odoo import http +from odoo.http import request + +from odoo.addons.website_membership_group.controllers import main + + +class MembershipGroupController(main.MembershipGroupController): + def _membership_group_page_render_vals(self, membership_group): + res = super()._membership_group_page_render_vals(membership_group) + in_mailing_list, related_contact, email_needed, name_needed = ( + False, + False, + False, + False, + ) + mailing_list = membership_group.mailing_list_id + if mailing_list: + if request.env.user._is_public(): + if request.session.get( + "group_%s_subscribed" % membership_group.id, False + ): + in_mailing_list = True + else: + email_needed, name_needed = True, True + else: + related_contacts = request.env.user.partner_id.mass_mailing_contact_ids + if related_contacts: + related_contact = related_contacts[0] + else: + email_needed = bool(not request.env.user.partner_id.email) + in_mailing_list = bool( + related_contacts.mapped("subscription_list_ids") + .mapped("list_id") + .filtered(lambda ml: ml == mailing_list) + ) + res.update( + { + "mailing_list": mailing_list, + "in_mailing_list": in_mailing_list, + "related_contact": related_contact, + "email_needed": email_needed, + "name_needed": name_needed, + "member_name": "", + "member_email": "", + } + ) + return res + + def _get_contact_data(self, post, defaults=None): + contact_data = {} + if not defaults: + defaults = {} + contact_data["member_email"] = ( + defaults.get("member_email", "") or post["member_email"] + ) + contact_data["member_name"] = ( + defaults.get("member_name", "") or post["member_name"] + ) + return contact_data + + def _get_new_contact_vals_dict(self, partner_data): + res = { + "name": partner_data["member_name"], + "email": partner_data["member_email"], + } + if not request.env.user._is_public() and request.env.user.partner_id: + res["partner_id"] = request.env.user.partner_id.id + return res + + @http.route( + ["/subscribe-to-group-mailing-list"], + type="http", + methods=["POST"], + auth="public", + csrf=False, + website=True, + ) + def post_subscribe_to_membership_group_mailing_list(self, **post): + group_id = post.get("group_id") + group = request.env["membership.group"].sudo().browse(int(group_id)) + if not group: + return http.request.not_found() + if request.env.user._is_public(): + contact_data = self._get_contact_data(post) + contact = ( + request.env["mailing.contact"] + .sudo() + .search( + [ + ("email", "=", contact_data["member_email"]), + ("name", "=", contact_data["member_name"]), + ], + limit=1, + ) + ) + if not contact: + contact = ( + request.env["mailing.contact"] + .sudo() + .create(self._get_new_contact_vals_dict(contact_data)) + ) + else: + partner = request.env.user.partner_id + related_contacts = partner.mass_mailing_contact_ids + if related_contacts: + contact = related_contacts[0] + else: + contact_data = self._get_contact_data( + post, {"member_name": partner.name, "member_email": partner.email} + ) + contact = ( + request.env["mailing.contact"] + .sudo() + .search( + [ + ("email", "=", contact_data["member_email"]), + ("name", "=", contact_data["member_name"]), + ], + limit=1, + ) + ) + if not contact: + contact = ( + request.env["mailing.contact"] + .sudo() + .create(self._get_new_contact_vals_dict(contact_data)) + ) + else: + contact.write({"partner_id": partner.id}) + + group.mailing_list_id.write({"contact_ids": [(4, contact.id)]}) + + request.session.update( + {"group_%s_subscribed" % group.id: True, "related_contact": contact.id} + ) + return request.redirect("/members/group/%s" % group.id) + + @http.route( + ["/unsubscribe-from-group-mailing-list"], + type="http", + methods=["POST"], + auth="public", + csrf=False, + website=True, + ) + def post_unsubscribe_from_membership_group_mailing_list(self, **post): + group_id = post.get("group_id") + group = request.env["membership.group"].sudo().browse(int(group_id)) + if not group: + return http.request.not_found() + + if request.session.get("related_contact"): + related_contacts = ( + request.env["mailing.contact"] + .sudo() + .browse(request.session.get("related_contact")) + ) + else: + related_contacts = request.env.user.partner_id.mass_mailing_contact_ids + + group.mailing_list_id.write( + {"contact_ids": [(3, contact.id) for contact in related_contacts]} + ) + request.session.pop("group_%s_subscribed" % group.id, None) + request.session.pop("related_contact", None) + return request.redirect("/members/group/%s" % group.id) diff --git a/website_mass_mailing_membership_group/readme/CONTRIBUTORS.rst b/website_mass_mailing_membership_group/readme/CONTRIBUTORS.rst new file mode 100644 index 0000000..85125ab --- /dev/null +++ b/website_mass_mailing_membership_group/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ +* `Onestein `_ diff --git a/website_mass_mailing_membership_group/readme/DESCRIPTION.rst b/website_mass_mailing_membership_group/readme/DESCRIPTION.rst new file mode 100644 index 0000000..aa7ecbd --- /dev/null +++ b/website_mass_mailing_membership_group/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +This module allows members to subscribe/unsubsrcibe from mailing list associated with membership groups from website. diff --git a/website_mass_mailing_membership_group/templates/website.xml b/website_mass_mailing_membership_group/templates/website.xml new file mode 100644 index 0000000..a7fbb1f --- /dev/null +++ b/website_mass_mailing_membership_group/templates/website.xml @@ -0,0 +1,86 @@ + + + + + + + diff --git a/website_membership_group/__init__.py b/website_membership_group/__init__.py new file mode 100644 index 0000000..91c5580 --- /dev/null +++ b/website_membership_group/__init__.py @@ -0,0 +1,2 @@ +from . import controllers +from . import models diff --git a/website_membership_group/__manifest__.py b/website_membership_group/__manifest__.py new file mode 100644 index 0000000..2d8de4d --- /dev/null +++ b/website_membership_group/__manifest__.py @@ -0,0 +1,19 @@ +# Copyright 2020 Onestein () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +{ + "name": "Website Membership Group", + "category": "Membership", + "version": "16.0.1.0.0", + "author": "Onestein", + "license": "AGPL-3", + "website": "https://www.onestein.nl", + "depends": [ + "membership_group", + "website", + ], + "data": [ + "views/membership_group_view.xml", + "templates/website.xml", + ], +} diff --git a/website_membership_group/controllers/__init__.py b/website_membership_group/controllers/__init__.py new file mode 100644 index 0000000..12a7e52 --- /dev/null +++ b/website_membership_group/controllers/__init__.py @@ -0,0 +1 @@ +from . import main diff --git a/website_membership_group/controllers/main.py b/website_membership_group/controllers/main.py new file mode 100644 index 0000000..dbd69c2 --- /dev/null +++ b/website_membership_group/controllers/main.py @@ -0,0 +1,36 @@ +from odoo import http +from odoo.http import request + + +class MembershipGroupController(http.Controller): + def _membership_group_page_render_vals(self, membership_group): + return { + "main_object": membership_group, + "membership_group": membership_group, + "title": membership_group.name, + } + + @http.route( + [ + """/members/group/ + +
+ +
+
+ +
+
+
+
+
+ + + +
diff --git a/website_membership_group/views/membership_group_view.xml b/website_membership_group/views/membership_group_view.xml new file mode 100644 index 0000000..d1bd78b --- /dev/null +++ b/website_membership_group/views/membership_group_view.xml @@ -0,0 +1,39 @@ + + + + + membership.group + + + + + + + + + + membership.group + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/website_membership_registration/__manifest__.py b/website_membership_registration/__manifest__.py index 085489b..5d3e21a 100644 --- a/website_membership_registration/__manifest__.py +++ b/website_membership_registration/__manifest__.py @@ -9,24 +9,25 @@ "license": "AGPL-3", "website": "https://www.onestein.nl", "depends": [ - "mass_mailing_membership_section", + "mass_mailing_membership_group", "membership_extension", "membership_hr", "membership_hr_recruitment", - "membership_origin", - "membership_section", + "membership_group", "portal", "website", - "website_membership_section", + "website_membership_group", "website_partner", "website_sale", ], "data": [ "data/ir_cron_data.xml", "data/mail_template_data.xml", + "data/res_partner_category_data.xml", + "views/snippets/snippets.xml", "views/hr_applicant_view.xml", "views/hr_employee_view.xml", - "views/membership_section_view.xml", + "views/membership_group_view.xml", "views/product_template_view.xml", "views/res_config_settings_view.xml", "views/res_partner_view.xml", @@ -37,6 +38,9 @@ "website_membership_registration/static/src/js/website_membership_registration.js", "website_membership_registration/static/src/scss/website_membership_registration.scss", ], + "website.assets_wysiwyg": [ + "website_membership_registration/static/src/js/website_membership_registration.editor.js", + ], }, "demo": [ "data/product_demo.xml", diff --git a/website_membership_registration/controllers/main.py b/website_membership_registration/controllers/main.py index 3ad151c..b388152 100644 --- a/website_membership_registration/controllers/main.py +++ b/website_membership_registration/controllers/main.py @@ -1,5 +1,8 @@ +import base64 import re +from werkzeug.exceptions import NotFound + from odoo import _, fields, http from odoo.exceptions import ValidationError from odoo.http import request @@ -35,6 +38,37 @@ def _validate_membership_email(self, email): return email, email_valid, error_message + def _validate_membership_cv(self, cv): + cv_valid = True + error_message = "" + cv_file = cv + if cv: + if ( + not request.website.membership_registration_cv_file_formats_supported + == "*" + ): + for ( + file_format + ) in request.website.membership_registration_cv_file_formats_supported.split( + "," + ): + if not cv.filename.endswith(file_format): + cv_valid = cv_file = False + error_message = _( + "Only %s files are accepted.", + request.website.membership_registration_cv_file_formats_supported, + ) + break + if cv_valid: + cv_file = cv.stream.read() + size = cv.stream.tell() + if size > ( + request.website.membership_registration_max_cv_file_size * 1048576 + ): + cv_valid = cv_file = False + error_message = _("File is too big.") + return cv_file, cv_valid, error_message + def _validate_membership_phone(self, phone): phone_valid = True if (not phone or re.match(r"^\+?[\d]+$", phone)) else False error_message = "" @@ -52,10 +86,13 @@ def _validate_membership_name(self, name): return name, name_valid, error_message def _validate_membership_nickname(self, nickname): - error_message = "" - nickname_valid = nickname and all(c.isalnum() or c.isspace() for c in nickname) - if not nickname_valid: - error_message = _("Nickname is empty or invalid.") + error_message, nickname_valid = "", True + if nickname: + nickname_valid = nickname and all( + c.isalnum() or c.isspace() for c in nickname + ) + if not nickname_valid: + error_message = _("Nickname is invalid.") return nickname, nickname_valid, error_message def _validate_membership_product(self, product_id): @@ -115,8 +152,8 @@ def _validate_membership_address(self, post): return res - def _validate_membership_sections(self, section_list): - return section_list, True, "" + def _validate_membership_groups(self, membership_group_list): + return membership_group_list, True, "" def _get_errors_dict(self, validation_data): error_dict = {} @@ -158,12 +195,15 @@ def _get_error_message_list(self, validation_data, error_data): error_list.append(error_data["member_country_id"]) if not validation_data["member_state_id"]: error_list.append(error_data["member_state_id"]) + if not validation_data["member_cv"]: + error_list.append(error_data["member_cv"]) return error_list def _get_partner_and_validation_data(self, post): partner_data = {} validation_data = {} error_data = {} + partner_data["website_description"] = post.get("website_description", "") ( partner_data["member_email"], validation_data["member_email"], @@ -184,6 +224,11 @@ def _get_partner_and_validation_data(self, post): validation_data["member_phone"], error_data["member_phone"], ) = self._validate_membership_phone(post["member_phone"]) + ( + partner_data["member_cv"], + validation_data["member_cv"], + error_data["member_cv"], + ) = self._validate_membership_cv(post.get("member_cv", False)) ( partner_data["application_date"], validation_data["application_date"], @@ -233,29 +278,36 @@ def _get_partner_and_validation_data(self, post): error_data["member_state_id"], ) = address_data["member_state_id"] - section_ids = request.env["membership.section"].search( + membership_group_ids = request.env["membership.group"].search( [("is_published", "=", True)] ) - section_list = {} - for section in section_ids: - if "section_%s_follow" % section.id in post: - section_list["section_%s_follow" % section.id] = ( - post["section_%s_follow" % section.id] == "on" or False + membership_group_list = {} + for membership_group in membership_group_ids: + if "membership_group_%s_follow" % membership_group.id in post: + membership_group_list[ + "membership_group_%s_follow" % membership_group.id + ] = ( + post["membership_group_%s_follow" % membership_group.id] == "on" + or False ) - if "section_%s_collaborate" % section.id in post: - section_list["section_%s_collaborate" % section.id] = ( - post["section_%s_collaborate" % section.id] == "on" or False + if "membership_group_%s_collaborate" % membership_group.id in post: + membership_group_list[ + "membership_group_%s_collaborate" % membership_group.id + ] = ( + post["membership_group_%s_collaborate" % membership_group.id] + == "on" + or False ) ( - partner_data["section_data"], - validation_data["section_data"], - error_data["section_data"], - ) = self._validate_membership_sections(section_list) + partner_data["membership_group_data"], + validation_data["membership_group_data"], + error_data["membership_group_data"], + ) = self._validate_membership_groups(membership_group_list) return partner_data, validation_data, error_data def _get_new_member_vals_dict(self, partner_data): - return { + vals = { "name": partner_data["member_name"], "nickname": partner_data["member_nickname"], "street": partner_data["member_street"], @@ -273,22 +325,30 @@ def _get_new_member_vals_dict(self, partner_data): "is_published": partner_data["member_publish"], "website_id": request.website.id, "company_id": request.env.company.id, - "membership_origin": "website_form", + "website_description": partner_data["website_description"], } + partner_category = request.env.ref( + "website_membership_registration.res_partner_category_website_form", False + ) + if partner_category: + vals["category_id"] = [(4, partner_category.id)] + return vals - def _set_partner_membership_section(self, partner, partner_data): - sections = request.env["membership.section"].search( + def _set_partner_membership_group(self, partner, partner_data): + membership_groups = request.env["membership.group"].search( [("is_published", "=", True)] ) - section_data = self._get_section_data(sections, partner_data["section_data"]) - section_membership_data_list = self._get_section_membership_data_list( - section_data, partner_data + membership_group_data = self._get_membership_group_data( + membership_groups, partner_data["membership_group_data"] + ) + membership_group_member_data_list = self._get_membership_group_member_data_list( + membership_group_data, partner_data ) partner.write( { - "section_membership_ids": [ - (0, 0, section_membership_data) - for section_membership_data in section_membership_data_list + "membership_group_member_ids": [ + (0, 0, membership_group_data) + for membership_group_data in membership_group_member_data_list ] } ) @@ -309,37 +369,46 @@ def _get_order_vals(self, partner, product): ], } - def _get_section_data(self, sections, data): - follow_sections = sections.filtered( - lambda c: "section_%s_follow" % c.id in data - and data["section_%s_follow" % c.id] + def _get_membership_group_data(self, membership_groups, data): + follow_membership_groups = membership_groups.filtered( + lambda c: "membership_group_%s_follow" % c.id in data + and data["membership_group_%s_follow" % c.id] ) - contribute_sections = sections.filtered( - lambda c: "section_%s_collaborate" % c.id in data - and data["section_%s_collaborate" % c.id] + contribute_membership_groups = membership_groups.filtered( + lambda c: "membership_group_%s_collaborate" % c.id in data + and data["membership_group_%s_collaborate" % c.id] ) - return {"follow": follow_sections, "collaborate": contribute_sections} + return { + "follow": follow_membership_groups, + "collaborate": contribute_membership_groups, + } - def _get_section_membership_data_list(self, section_data, partner_data): - sections = self._get_all_sections(section_data) + def _get_membership_group_member_data_list( + self, membership_group_data, partner_data + ): + membership_groups = self._get_all_membership_groups(membership_group_data) res = [] - for section in sections: + for membership_group in membership_groups: res.append( - self._get_section_membership_data_dict( - section, section_data, partner_data + self._get_membership_group_member_data_dict( + membership_group, membership_group_data, partner_data ) ) return res - def _get_all_sections(self, section_data): - return section_data["follow"] | section_data["collaborate"] + def _get_all_membership_groups(self, membership_group_data): + return membership_group_data["follow"] | membership_group_data["collaborate"] - def _get_section_membership_data_dict(self, section, section_data, partner_data): + def _get_membership_group_member_data_dict( + self, membership_group, membership_group_data, partner_data + ): return { - "start_date": partner_data["application_date"], - "section_id": section.id, - "on_mailing_list": section in section_data["follow"] and True or False, - "wants_to_collaborate": section in section_data["collaborate"] + "group_id": membership_group.id, + "on_mailing_list": membership_group in membership_group_data["follow"] + and True + or False, + "wants_to_collaborate": membership_group + in membership_group_data["collaborate"] and True or False, } @@ -359,77 +428,48 @@ def _get_membership_form_page_vals( ) ) - sections = request.env["membership.section"].search( + membership_groups = request.env["membership.group"].search( [("is_published", "=", True)] ) - sections_follow_checked = {} - sections_collaborate_checked = {} - for c in sections: - sections_follow_checked.update({c.id: False}) - sections_collaborate_checked.update({c.id: False}) + membership_groups_follow_checked = {} + membership_groups_collaborate_checked = {} + for c in membership_groups: + membership_groups_follow_checked.update({c.id: False}) + membership_groups_collaborate_checked.update({c.id: False}) if not old_data: old_data = {} - if "section_data" in old_data: - for c in sections: - if "section_%s_follow" % c.id in old_data["section_data"]: - sections_follow_checked.update({c.id: True}) - if "section_%s_collaborate" % c.id in old_data["section_data"]: - sections_collaborate_checked.update({c.id: True}) - old_data.pop("section_data") - - if request.website.membership_registration_page_background_type == "color": - background_style = ( - "background-color: %s !important;" - % request.website.membership_registration_page_background_color - ) - elif ( - request.website.membership_registration_page_background_type - == "gradient_radial" - ): - background_style = ( - "background-image: radial-gradient(circle farthest-side at 50%% 50%%, %s 0%%, %s 100%%) !important" - % ( - request.website.membership_registration_page_background_gradient_start, - request.website.membership_registration_page_background_gradient_end, - ) - ) - elif ( - request.website.membership_registration_page_background_type - == "gradient_linear" - ): - background_style = ( - "background-image: linear-gradient(135deg, %s 0%%, %s 100%%) !important" - % ( - request.website.membership_registration_page_background_gradient_start, - request.website.membership_registration_page_background_gradient_end, - ) - ) - elif request.website.membership_registration_page_background_type == "image": - background_style = ( - "background-image: url(data:image/jpg;base64,%s)" - % request.website.membership_registration_page_background_image.decode( - "utf-8" - ) - ) - else: - background_style = "" - section_style = request.website.membership_registration_page_section_style + if "membership_group_data" in old_data: + for c in membership_groups: + if ( + "membership_group_%s_follow" % c.id + in old_data["membership_group_data"] + ): + membership_groups_follow_checked.update({c.id: True}) + if ( + "membership_group_%s_collaborate" % c.id + in old_data["membership_group_data"] + ): + membership_groups_collaborate_checked.update({c.id: True}) + old_data.pop("membership_group_data") + membership_group_style = ( + request.website.membership_registration_page_membership_group_style + ) if not errors: errors = {} res = { - "background_style": background_style, "is_logged": is_logged, "member_name": "", "member_nickname": "", "member_email": "", "member_phone": "", - "section_style": section_style, + "membership_group_style": membership_group_style, "member_street": "", "member_street2": "", "member_zip": "", "member_city": "", "member_country_id": "", "member_state_id": "", + "website_description": "", "country_id": request.env["res.country"], "state_id": request.env["res.country.state"], "member_publish": False, @@ -442,11 +482,11 @@ def _get_membership_form_page_vals( or False ) or False, - "sections": sections, + "membership_groups": membership_groups, "countries": request.env["res.country"].sudo().search([]), "country_states": request.env["res.country.state"], - "sections_follow_checked": sections_follow_checked, - "sections_collaborate_checked": sections_collaborate_checked, + "membership_groups_follow_checked": membership_groups_follow_checked, + "membership_groups_collaborate_checked": membership_groups_collaborate_checked, "error_message": error_message, "error": errors, } @@ -552,8 +592,17 @@ def post_membership_registration_form(self, **post): partner = request.env["res.partner"].sudo().create(partner_vals) else: partner.write(partner_vals) - self._set_partner_membership_section(partner, partner_data) - + self._set_partner_membership_group(partner, partner_data) + if partner_data.get("member_cv"): + request.env["ir.attachment"].sudo().create( + { + "name": post["member_cv"].filename, + "res_model": "res.partner", + "res_id": partner.id, + "datas": base64.b64encode(partner_data.get("member_cv")), + "mimetype": "application/pdf", + } + ) sale_order = partner.create_membership_sale_order( product, product.list_price ) @@ -653,3 +702,38 @@ def apply_for_membership_verify(self, partner_id, token, email): return request.render( "website_membership_registration.membership_registration_verify_success_page" ) + + @http.route(["/membership-registration/config/website"], type="json", auth="user") + def _change_membership_registration_website_config(self, **options): + if not request.env.user.has_group("website.group_website_restricted_editor"): + raise NotFound() + + current_website = request.env["website"].get_current_website() + # Restrict options we can write to. + writable_fields = { + "membership_registration_page_membership_group_style", + "membership_registration_max_cv_file_size", + "membership_registration_cv_file_formats_supported", + } + # Default membership_group layout to list. + if ( + "membership_registration_page_membership_group_style" in options + and not options["membership_registration_page_membership_group_style"] + ): + options["membership_registration_page_membership_group_style"] = "list" + # Default max cv file size to 3. + if ( + "membership_registration_max_cv_file_size" in options + and not options["membership_registration_max_cv_file_size"] + ): + options["membership_registration_max_cv_file_size"] = 3 + # Default file format supported to '.pdf'. + if ( + "membership_registration_cv_file_formats_supported" in options + and not options["membership_registration_cv_file_formats_supported"] + ): + options["membership_registration_cv_file_formats_supported"] = ".pdf" + + write_vals = {k: v for k, v in options.items() if k in writable_fields} + if write_vals: + current_website.write(write_vals) diff --git a/website_membership_registration/controllers/portal.py b/website_membership_registration/controllers/portal.py index 0c1e4bc..3074646 100644 --- a/website_membership_registration/controllers/portal.py +++ b/website_membership_registration/controllers/portal.py @@ -1,9 +1,10 @@ +from odoo import _ from odoo.http import request, route from odoo.addons.portal.controllers.portal import CustomerPortal -class CustomerPortal(CustomerPortal): +class CustomerPortalMembership(CustomerPortal): CustomerPortal.OPTIONAL_BILLING_FIELDS += ["nickname", "website_published"] @route() @@ -18,3 +19,14 @@ def account(self, redirect=None, **post): else: post["website_published"] = True return super().account(redirect=redirect, **post) + + def details_form_validate(self, data, partner_creation=False): + error, error_message = super( + CustomerPortalMembership, self + ).details_form_validate(data, partner_creation=partner_creation) + if data.get("nickname") and not ( + all(c.isalnum() or c.isspace() for c in data.get("nickname")) + ): + error["nickname"] = "error" + error_message.append(_("Nickname is invalid.")) + return error, error_message diff --git a/website_membership_registration/data/res_partner_category_data.xml b/website_membership_registration/data/res_partner_category_data.xml new file mode 100644 index 0000000..830cfbc --- /dev/null +++ b/website_membership_registration/data/res_partner_category_data.xml @@ -0,0 +1,6 @@ + + + + Website Form + + diff --git a/website_membership_registration/data/res_partner_demo.xml b/website_membership_registration/data/res_partner_demo.xml index ff6af16..3960529 100644 --- a/website_membership_registration/data/res_partner_demo.xml +++ b/website_membership_registration/data/res_partner_demo.xml @@ -2,33 +2,33 @@ - + Spiderman - - + Isaac Newton - - + Singing in the Rain - diff --git a/website_membership_registration/i18n/nl.po b/website_membership_registration/i18n/nl.po index 2580dd1..cb02ef0 100644 --- a/website_membership_registration/i18n/nl.po +++ b/website_membership_registration/i18n/nl.po @@ -16,17 +16,17 @@ msgstr "" "Plural-Forms: \n" #. module: website_membership_registration -#: model:ir.model.fields,field_description:website_membership_registration.field_membership_section__applicant_partner_count +#: model:ir.model.fields,field_description:website_membership_registration.field_membership_group__applicant_partner_count msgid "# of Applicant Members" msgstr "# Aanvragende Leden" #. module: website_membership_registration -#: model:ir.model.fields,field_description:website_membership_registration.field_membership_section__collaborator_partner_count +#: model:ir.model.fields,field_description:website_membership_registration.field_membership_group__collaborator_partner_count msgid "# of Collaborating Members" msgstr "# Samenwerkende Leden" #. module: website_membership_registration -#: model:ir.model.fields,field_description:website_membership_registration.field_membership_section__follower_partner_count +#: model:ir.model.fields,field_description:website_membership_registration.field_membership_group__follower_partner_count msgid "# of Following Members" msgstr "# Volgende Leden" @@ -220,20 +220,20 @@ msgstr "Er bestaat al een andere gebruiker met e-mailadres %s" #. module: website_membership_registration #: model:ir.model.fields,field_description:website_membership_registration.field_res_partner__applicant_ids #: model:ir.model.fields,field_description:website_membership_registration.field_res_users__applicant_ids -#: model:ir.model.fields.selection,name:website_membership_registration.selection__membership_section_membership__type__applicant +#: model:ir.model.fields.selection,name:website_membership_registration.selection__membership_group_member__type__applicant msgid "Applicant" msgstr "Aanvrager" #. module: website_membership_registration -#: model:ir.model.fields.selection,name:website_membership_registration.selection__membership_section_membership__type__applicant_follower +#: model:ir.model.fields.selection,name:website_membership_registration.selection__membership_group_member__type__applicant_follower msgid "Applicant / Follower" msgstr "Aanvrager / Volger" #. module: website_membership_registration -#: model:ir.model.fields,field_description:website_membership_registration.field_res_partner__applicant_sections_count -#: model:ir.model.fields,field_description:website_membership_registration.field_res_users__applicant_sections_count -msgid "Applicant to # Sections" -msgstr "Aanvrager naar # Secties" +#: model:ir.model.fields,field_description:website_membership_registration.field_res_partner__applicant_membership_groups_count +#: model:ir.model.fields,field_description:website_membership_registration.field_res_users__applicant_membership_groups_count +msgid "Applicant to # Membership Groups" +msgstr "Aanvrager naar # Lidmaatschapsgroepen" #. module: website_membership_registration #: model:ir.model.fields,field_description:website_membership_registration.field_res_config_settings__membership_registration_page_background_type @@ -260,18 +260,18 @@ msgid "Collaborate" msgstr "Samenwerken" #. module: website_membership_registration -#: model:ir.model.fields,field_description:website_membership_registration.field_res_partner__collaborator_sections_count -#: model:ir.model.fields,field_description:website_membership_registration.field_res_users__collaborator_sections_count -msgid "Collaborating to # Sections" -msgstr "Samenwerken aan # Secties" +#: model:ir.model.fields,field_description:website_membership_registration.field_res_partner__collaborator_membership_groups_count +#: model:ir.model.fields,field_description:website_membership_registration.field_res_users__collaborator_membership_groups_count +msgid "Collaborating to # Membership Groups" +msgstr "Samenwerken aan # Lidmaatschapsgroepen" #. module: website_membership_registration -#: model:ir.model.fields.selection,name:website_membership_registration.selection__membership_section_membership__type__collaborator +#: model:ir.model.fields.selection,name:website_membership_registration.selection__membership_group_member__type__collaborator msgid "Collaborator" msgstr "Samenwerker" #. module: website_membership_registration -#: model:ir.model.fields.selection,name:website_membership_registration.selection__membership_section_membership__type__collaborator_follower +#: model:ir.model.fields.selection,name:website_membership_registration.selection__membership_group_member__type__collaborator_follower msgid "Collaborator / Follower" msgstr "Samenwerker / Volger" @@ -339,15 +339,15 @@ msgid "Follow" msgstr "Volgen" #. module: website_membership_registration -#: model:ir.model.fields.selection,name:website_membership_registration.selection__membership_section_membership__type__follower +#: model:ir.model.fields.selection,name:website_membership_registration.selection__membership_group_member__type__follower msgid "Follower" msgstr "Volger" #. module: website_membership_registration -#: model:ir.model.fields,field_description:website_membership_registration.field_res_partner__follower_sections_count -#: model:ir.model.fields,field_description:website_membership_registration.field_res_users__follower_sections_count -msgid "Following # Sections" -msgstr "# Secties volgen" +#: model:ir.model.fields,field_description:website_membership_registration.field_res_partner__follower_membership_groups_count +#: model:ir.model.fields,field_description:website_membership_registration.field_res_users__follower_membership_groups_count +msgid "Following # Membership Groups" +msgstr "# Lidmaatschapsgroepen volgen" #. module: website_membership_registration #: model:ir.model.fields,field_description:website_membership_registration.field_res_config_settings__membership_registration_page_background_gradient_end @@ -362,7 +362,7 @@ msgid "Gradient Color Start" msgstr "Kleurverloop start" #. module: website_membership_registration -#: model:ir.model.fields.selection,name:website_membership_registration.selection__website__membership_registration_page_section_style__grid +#: model:ir.model.fields.selection,name:website_membership_registration.selection__website__membership_registration_page_membership_group_style__grid msgid "Grid View" msgstr "Roosterweergave" @@ -387,7 +387,7 @@ msgid "Linear-Gradient" msgstr "Lineair-verloop" #. module: website_membership_registration -#: model:ir.model.fields.selection,name:website_membership_registration.selection__website__membership_registration_page_section_style__list +#: model:ir.model.fields.selection,name:website_membership_registration.selection__website__membership_registration_page_membership_group_style__list msgid "List View" msgstr "Lijstweergave" @@ -414,12 +414,6 @@ msgstr "Lidmaatschap e-mail verificatie status" msgid "Membership Job" msgstr "Lidmaatschap Functie" -#. module: website_membership_registration -#: model:ir.model.fields,field_description:website_membership_registration.field_res_partner__membership_origin -#: model:ir.model.fields,field_description:website_membership_registration.field_res_users__membership_origin -msgid "Membership Origin" -msgstr "" - #. module: website_membership_registration #: model:ir.model.fields,field_description:website_membership_registration.field_res_config_settings__membership_registration_page_background_image #: model:ir.model.fields,field_description:website_membership_registration.field_website__membership_registration_page_background_image @@ -427,9 +421,9 @@ msgid "Membership Registration Page Background Image" msgstr "Lidmaatschap Oorsprong" #. module: website_membership_registration -#: model:ir.model,name:website_membership_registration.model_membership_section -msgid "Membership Section" -msgstr "Lidmaatschap Sectie" +#: model:ir.model,name:website_membership_registration.model_membership_group +msgid "Membership group" +msgstr "Lidmaatschapsgroep" #. module: website_membership_registration #: model:ir.actions.server,name:website_membership_registration.cleanup_unverified_members_cron_ir_actions_server @@ -455,8 +449,8 @@ msgstr "Bijnaam" #. odoo-python #: code:addons/website_membership_registration/controllers/main.py:0 #, python-format -msgid "Nickname is empty or invalid." -msgstr "Bijnaam is leeg of ongeldig." +msgid "Nickname is invalid." +msgstr "Bijnaam is ongeldig." #. module: website_membership_registration #. odoo-python @@ -509,15 +503,15 @@ msgid "Radial-Gradient" msgstr "Radiaal-verloop" #. module: website_membership_registration -#: model:ir.model,name:website_membership_registration.model_membership_section_membership -msgid "Section Membership" -msgstr "Lidmaatschap van de sectie" +#: model:ir.model,name:website_membership_registration.model_membership_group_member +msgid "Membership Group Member" +msgstr "Lidmaatschap Groepslid" #. module: website_membership_registration -#: model:ir.model.fields,field_description:website_membership_registration.field_res_config_settings__membership_registration_page_section_style -#: model:ir.model.fields,field_description:website_membership_registration.field_website__membership_registration_page_section_style -msgid "Section View" -msgstr "Sectieweergave" +#: model:ir.model.fields,field_description:website_membership_registration.field_res_config_settings__membership_registration_page_membership_group_style +#: model:ir.model.fields,field_description:website_membership_registration.field_website__membership_registration_page_membership_group_style +msgid "Membership Group View" +msgstr "Lidmaatschapsgroep weergave" #. module: website_membership_registration #: model_terms:ir.ui.view,arch_db:website_membership_registration.membership_registration_form @@ -551,7 +545,7 @@ msgid "The selected membership level is not a valid product" msgstr "Het geselecteerde lidmaatschapsniveau is geen geldig product" #. module: website_membership_registration -#: model:ir.model.fields,field_description:website_membership_registration.field_membership_section_membership__type +#: model:ir.model.fields,field_description:website_membership_registration.field_membership_group_member__type msgid "Type" msgstr "Type" @@ -589,7 +583,7 @@ msgid "Visible On Membership Registration Page" msgstr "Zichtbaar op lidmaatschapsregistratiepagina" #. module: website_membership_registration -#: model:ir.model.fields,field_description:website_membership_registration.field_membership_section_membership__wants_to_collaborate +#: model:ir.model.fields,field_description:website_membership_registration.field_membership_group_member__wants_to_collaborate msgid "Wants To Collaborate" msgstr "Wil samenwerken" @@ -603,11 +597,6 @@ msgstr "We hebben je e-mailadres nodig om je registratie te verifiëren." msgid "Website" msgstr "Website -#. module: website_membership_registration -#: model:ir.model.fields.selection,name:website_membership_registration.selection__res_partner__membership_origin__website_form -msgid "Website Form" -msgstr "Website formulier" - #. module: website_membership_registration #: model_terms:ir.ui.view,arch_db:website_membership_registration.membership_registration_form msgid "Yes we also need you!" diff --git a/website_membership_registration/models/__init__.py b/website_membership_registration/models/__init__.py index bb7496f..52033b1 100644 --- a/website_membership_registration/models/__init__.py +++ b/website_membership_registration/models/__init__.py @@ -1,6 +1,5 @@ from . import account_move -from . import membership_section -from . import membership_section_membership +from . import membership_group from . import product_template from . import res_config_settings from . import res_partner diff --git a/website_membership_registration/models/membership_group.py b/website_membership_registration/models/membership_group.py new file mode 100644 index 0000000..c34bc44 --- /dev/null +++ b/website_membership_registration/models/membership_group.py @@ -0,0 +1,54 @@ +from odoo import api, fields, models + + +class MembershipGroup(models.Model): + _inherit = "membership.group" + + follower_partner_count = fields.Integer( + string="# of Following Members", + compute="_compute_partner_ids", + store=True, + compute_sudo=False, + ) + applicant_partner_count = fields.Integer( + string="# of Applicant Members", + compute="_compute_partner_ids", + store=True, + compute_sudo=False, + ) + collaborator_partner_count = fields.Integer( + string="# of Collaborating Members", + compute="_compute_partner_ids", + store=True, + compute_sudo=False, + ) + + @api.depends( + "membership_group_member_ids", + "membership_group_member_ids.type", + # "membership_group_member_ids.on_mailing_list", + # "membership_group_member_ids.wants_to_collaborate", + # "membership_group_member_ids.partner_id", + # "membership_group_member_ids.partner_id.employee_ids", + # "membership_group_member_ids.partner_id.applicant_ids", + ) + def _compute_partner_ids(self): + res = super(MembershipGroup, self)._compute_partner_ids() + for membership_group in self: + membership_group.follower_partner_count = len( + membership_group.membership_group_member_ids.filtered( + lambda x: x.type + in ("follower", "applicant_follower", "collaborator_follower") + ).mapped("partner_id") + ) + membership_group.applicant_partner_count = len( + membership_group.membership_group_member_ids.filtered( + lambda x: x.type in ("applicant", "applicant_follower") + ).mapped("partner_id") + ) + membership_group.collaborator_partner_count = len( + membership_group.membership_group_member_ids.filtered( + lambda x: x.type in ("collaborator", "collaborator_follower") + ).mapped("partner_id") + ) + return res diff --git a/website_membership_registration/models/res_config_settings.py b/website_membership_registration/models/res_config_settings.py index a00e91f..99a10dd 100644 --- a/website_membership_registration/models/res_config_settings.py +++ b/website_membership_registration/models/res_config_settings.py @@ -22,34 +22,17 @@ class ResConfigSetting(models.TransientModel): readonly=False, ) - membership_registration_page_background_type = fields.Selection( - related="website_id.membership_registration_page_background_type", + membership_registration_page_membership_group_style = fields.Selection( + related="website_id.membership_registration_page_membership_group_style", readonly=False, - string="Background Type", ) - membership_registration_page_background_color = fields.Char( - related="website_id.membership_registration_page_background_color", - readonly=False, - string="Color", - ) - membership_registration_page_background_gradient_start = fields.Char( - related="website_id.membership_registration_page_background_gradient_start", - readonly=False, - string="Gradient Color Start", - ) - membership_registration_page_background_gradient_end = fields.Char( - related="website_id.membership_registration_page_background_gradient_end", - readonly=False, - string="Gradient Color End", - ) - - membership_registration_page_background_image = fields.Binary( - related="website_id.membership_registration_page_background_image", + membership_registration_max_cv_file_size = fields.Integer( + related="website_id.membership_registration_max_cv_file_size", readonly=False, ) - membership_registration_page_section_style = fields.Selection( - related="website_id.membership_registration_page_section_style", + membership_registration_cv_file_formats_supported = fields.Char( + related="website_id.membership_registration_cv_file_formats_supported", readonly=False, ) diff --git a/website_membership_registration/models/res_partner.py b/website_membership_registration/models/res_partner.py index 928aed1..f0a8bbd 100644 --- a/website_membership_registration/models/res_partner.py +++ b/website_membership_registration/models/res_partner.py @@ -25,25 +25,22 @@ class ResPartner(models.Model): ) membership_application_date = fields.Date() - membership_origin = fields.Selection( - selection_add=[("website_form", "Website Form")] - ) applicant_ids = fields.One2many("hr.applicant", "partner_id") - follower_sections_count = fields.Integer( - string="Following # Sections", - compute="_compute_section_ids", + follower_membership_groups_count = fields.Integer( + string="Following # Membership Groups", + compute="_compute_membership_group_ids", store=True, ) - applicant_sections_count = fields.Integer( - string="Applicant to # Sections", - compute="_compute_section_ids", + applicant_membership_groups_count = fields.Integer( + string="Applicant to # Membership Groups", + compute="_compute_membership_group_ids", store=True, ) - collaborator_sections_count = fields.Integer( - string="Collaborating to # Sections", - compute="_compute_section_ids", + collaborator_membership_groups_count = fields.Integer( + string="Collaborating to # Membership Group", + compute="_compute_membership_group_ids", store=True, ) @@ -70,30 +67,28 @@ def _compute_display_name(self): # pylint: disable=missing-return super(ResPartner, partner)._compute_display_name() @api.depends( - "section_membership_ids", - "section_membership_ids.section_id", - "section_membership_ids.on_mailing_list", - "section_membership_ids.wants_to_collaborate", - "employee_ids", - "applicant_ids", + "membership_group_member_ids", + "membership_group_member_ids.group_id", + "membership_group_member_ids.type", ) - def _compute_section_ids(self): - res = super(ResPartner, self)._compute_section_ids() + def _compute_membership_group_ids(self): + res = super(ResPartner, self)._compute_membership_group_ids() for partner in self: - partner.follower_sections_count = len( - partner.section_membership_ids.filtered( - lambda x: x.on_mailing_list - ).mapped("section_id") + partner.follower_membership_groups_count = len( + partner.membership_group_member_ids.filtered( + lambda x: x.type + in ("follower", "applicant_follower", "collaborator_follower") + ).mapped("group_id") ) - partner.applicant_sections_count = len( - partner.section_membership_ids.filtered( - lambda x: x.type == "applicant" - ).mapped("section_id") + partner.applicant_membership_groups_count = len( + partner.membership_group_member_ids.filtered( + lambda x: x.type in ("applicant", "applicant_follower") + ).mapped("group_id") ) - partner.collaborator_sections_count = len( - partner.section_membership_ids.filtered( - lambda x: x.type == "collaborator" - ).mapped("section_id") + partner.collaborator_membership_groups_count = len( + partner.membership_group_member_ids.filtered( + lambda x: x.type in ("collaborator", "collaborator_follower") + ).mapped("group_id") ) return res @@ -143,7 +138,11 @@ def cleanup_unverified_members(self): ("email_verification_token", "!=", False), ] ) - partners.unlink() + partners_to_unlink = partners + for partner in partners: + if partner.invoice_ids: + partners_to_unlink -= partner + partners_to_unlink.unlink() @api.model def _generate_email_verification_token(self, partner_id, email): @@ -197,7 +196,7 @@ def verify_email(self, email, token): def create_member_applicant(self): self.ensure_one() if ( - self.section_membership_ids.filtered(lambda x: x.wants_to_collaborate) + self.membership_group_member_ids.filtered(lambda x: x.wants_to_collaborate) and self.website_id.membership_job_id ): self.env["hr.applicant"].create( diff --git a/website_membership_registration/models/website.py b/website_membership_registration/models/website.py index 33080c6..25acd6b 100644 --- a/website_membership_registration/models/website.py +++ b/website_membership_registration/models/website.py @@ -7,39 +7,25 @@ class Website(models.Model): _inherit = "website" - allow_membership_registration = fields.Boolean(default=False) + allow_membership_registration = fields.Boolean(default=True) cleanup_unverified_members_days = fields.Integer( string="Cleanup unverified members after (days)", default=7 ) - membership_registration_page_background_type = fields.Selection( - [ - ("color", "Color"), - ("gradient_linear", "Linear-Gradient"), - ("gradient_radial", "Radial-Gradient"), - ("image", "Image"), - ], - string="Background Type", - ) - - membership_registration_page_background_color = fields.Char(string="Color") - membership_registration_page_background_gradient_start = fields.Char( - string="Gradient Color Start" - ) - membership_registration_page_background_gradient_end = fields.Char( - string="Gradient Color End" - ) - - membership_registration_page_background_image = fields.Binary() - membership_job_id = fields.Many2one("hr.job") - membership_registration_page_section_style = fields.Selection( + membership_registration_page_membership_group_style = fields.Selection( [ ("list", "List View"), ("grid", "Grid View"), ], - string="Section View", + string="Membership Group View", default="list", ) + + allow_adding_bio_for_membership_registration = fields.Boolean(default=False) + + membership_registration_max_cv_file_size = fields.Integer(default=3) + + membership_registration_cv_file_formats_supported = fields.Char(default=".pdf") diff --git a/website_membership_registration/static/src/js/website_membership_registration.editor.js b/website_membership_registration/static/src/js/website_membership_registration.editor.js new file mode 100644 index 0000000..075dcc3 --- /dev/null +++ b/website_membership_registration/static/src/js/website_membership_registration.editor.js @@ -0,0 +1,86 @@ +odoo.define('website_membership_registration.editor', function (require) { +'use strict'; + +var options = require('web_editor.snippets.options'); +const FILE_EXTENSIONS = ['.txt','.csv','.tsv','.jpg', '.jpeg', '.jpe', '.png', '.svg', '.gif','.pdf','.xls','.xlsx','.doc','.docx','.ppt','.pptx']; + +options.registry.WebsiteMembershipRegistrationPage = options.Class.extend({ + /** + * @override + */ + start: function () { + this.max_cv_file_size = parseInt(this.$target.closest('[data-max-cv-file-size]').data('max-cv-file-size'), 10); + this.cv_file_formats = this.$target.closest('[data-cv-file-formats]').data('cv-file-formats'); + this.membership_group_style = this.$target.closest('[data-membership_group-style]').data('membership_group-style'); + return this._super.apply(this, arguments); + }, + + setMembershipGroupStyle: function (previewMode, widgetValue) { + this.membership_group_style = widgetValue; + this._rpc({ + route: '/membership-registration/config/website', + params: { + 'membership_registration_page_membership_group_style': this.membership_group_style, + }, + }); + }, + setMaxCvFileSize: function (previewMode, widgetValue) { + const max_cv_file_size = parseInt(widgetValue, 10); + if (!max_cv_file_size || max_cv_file_size < 1) { + return false; + } + return this._rpc({ + route: '/membership-registration/config/website', + params: { + 'membership_registration_max_cv_file_size': max_cv_file_size, + }, + }); + }, + setFileFormats: function (previewMode, widgetValue) { + if (widgetValue.trim() === "*") { + this.cv_file_formats = widgetValue; + } + else{ + var supported_file_formats=""; + var file_formats = widgetValue.split(","); + for (let i = 0; i < file_formats.length; i++) { + var file_format = file_formats[i].trim().toLowerCase(); + if (FILE_EXTENSIONS.includes(file_format)) + { + supported_file_formats += (file_format +','); + } + } + this.cv_file_formats = supported_file_formats.replace(/,\s*$/, ""); + } + this._rpc({ + route: '/membership-registration/config/website', + params: { + 'membership_registration_cv_file_formats_supported': this.cv_file_formats, + }, + }); + }, + /** + * @override + */ + _computeWidgetState: function (methodName) { + switch (methodName) { + case 'setMembershipGroupStyle': { + return this.membership_group_style; + } + case 'setMaxCvFileSize': { + return this.max_cv_file_size; + } + case 'setFileFormats': { + return this.cv_file_formats; + } + } + return this._super(...arguments); + }, + _computeWidgetVisibility: function (widgetName) { + if (widgetName === 'cv_options') { + return this.$target[0].querySelector('#div_cv') + } + return this._super.apply(this, arguments); + }, +}); +}); diff --git a/website_membership_registration/static/src/scss/website_membership_registration.scss b/website_membership_registration/static/src/scss/website_membership_registration.scss index fcdc698..1066d00 100644 --- a/website_membership_registration/static/src/scss/website_membership_registration.scss +++ b/website_membership_registration/static/src/scss/website_membership_registration.scss @@ -1,5 +1,5 @@ @media (max-width: 575.98px) { - .oe_website_membership_registration .table-borderless .section_td{ + .oe_website_membership_registration .table-borderless .membership_group_td{ text-align:center; } } diff --git a/website_membership_registration/templates/website.xml b/website_membership_registration/templates/website.xml index 941ceb9..94c60ed 100644 --- a/website_membership_registration/templates/website.xml +++ b/website_membership_registration/templates/website.xml @@ -2,17 +2,17 @@ +