diff --git a/spp_idpass/views/id_pass_view.xml b/spp_idpass/views/id_pass_view.xml index 6c3b391b..cde2e832 100644 --- a/spp_idpass/views/id_pass_view.xml +++ b/spp_idpass/views/id_pass_view.xml @@ -49,12 +49,12 @@ - + /> --> diff --git a/spp_registrant_import/__init__.py b/spp_registrant_import/__init__.py index 1d43f16c..274282de 100644 --- a/spp_registrant_import/__init__.py +++ b/spp_registrant_import/__init__.py @@ -6,9 +6,7 @@ def post_init_hook(cr, registry): env = api.Environment(cr, SUPERUSER_ID, {}) contact_model = env.ref("base.model_res_partner") - registrant_id_field = env.ref( - "spp_registrant_import.field_res_partner__registrant_id" - ) + registrant_id_field = env.ref("spp_registrant_import.field_res_partner__spp_id") contact_import_match = env["spp.import.match"].search( [("model_id", "=", contact_model.id)] ) diff --git a/spp_registrant_import/__manifest__.py b/spp_registrant_import/__manifest__.py index caef4a37..27be4937 100644 --- a/spp_registrant_import/__manifest__.py +++ b/spp_registrant_import/__manifest__.py @@ -10,14 +10,13 @@ "development_status": "Alpha", "maintainers": ["jeremi", "gonzalesedwin1123", "nhatnm0612"], "depends": [ - "base", - "g2p_registry_base", - "g2p_registry_individual", - "g2p_registry_group", + "spp_base", "spp_import_match", ], "data": [ "views/res_partner_views.xml", + "views/spp_area_views.xml", + "views/spp_service_point_views.xml", ], "application": False, "installable": True, diff --git a/spp_registrant_import/models/__init__.py b/spp_registrant_import/models/__init__.py index 91fed54d..d35831fd 100644 --- a/spp_registrant_import/models/__init__.py +++ b/spp_registrant_import/models/__init__.py @@ -1 +1,3 @@ from . import res_partner +from . import spp_area +from . import spp_service_point diff --git a/spp_registrant_import/models/res_partner.py b/spp_registrant_import/models/res_partner.py index f4e2688d..1e502e00 100644 --- a/spp_registrant_import/models/res_partner.py +++ b/spp_registrant_import/models/res_partner.py @@ -1,79 +1,16 @@ -import random -import re -import string - -from odoo import _, api, fields, models -from odoo.exceptions import ValidationError +from odoo import api, models, fields class Registrant(models.Model): - _inherit = "res.partner" + _name = "res.partner" + _inherit = ["res.partner", "spp.unique.id"] name = fields.Char( compute="_compute_name", inverse="_inverse_name", store=True, ) - registrant_id = fields.Char( - string="Registrant ID", - compute="_compute_registrant_id", - store=True, - readonly=False, - index=True, - ) - - _sql_constraints = [ - ( - "registrant_id_uniq", - "UNIQUE(registrant_id)", - "registrant_id is an unique identifier!", - ) - ] - - @api.constrains("registrant_id") - def _check_registrant_id(self): - match_pattern = r"^(IND|GRP)_[0-9A-Z]{8}$" - not_correct_format = _("Registrant ID is not following correct format!") - for rec in self: - if not rec.is_registrant: - continue - if not re.match(match_pattern, rec.registrant_id): - raise ValidationError(not_correct_format) - if rec.is_group and rec.registrant_id.startswith("IND_"): - raise ValidationError(not_correct_format) - if not rec.is_group and rec.registrant_id.startswith("GRP_"): - raise ValidationError(not_correct_format) - if any( - [ - char in rec.registrant_id.split("_")[-1] - for char in ("0", "O", "1", "I") - ] - ): - raise ValidationError(not_correct_format) - - @api.depends("is_registrant", "is_group") - def _compute_registrant_id(self): - for rec in self: - if not rec.is_registrant: - rec.registrant_id = None - continue - prefix = "GRP" if rec.is_group else "IND" - unique_id = self._generate_unique_id() - rec.registrant_id = "_".join([prefix, unique_id]) - - def _generate_unique_id(self): - # Adjust the desired length of the unique identifier - length = 8 - # Define the characters allowed in the unique identifier - characters = string.digits + string.ascii_uppercase - # Exclude characters that can be confused - excluded_characters = ["0", "O", "1", "I"] - # Filter the characters to exclude - allowed_characters = [c for c in characters if c not in excluded_characters] - # Generate the unique identifier by randomly selecting characters - unique_id = "".join(random.choice(allowed_characters) for _ in range(length)) - - return unique_id + spp_id = fields.Char(readonly=False) @api.onchange("is_group", "family_name", "given_name", "addl_name") def name_change(self): @@ -113,3 +50,17 @@ def _inverse_name(self): rec.family_name = name[0] rec.given_name = name[1] rec.addl_name = name[2] + + def _get_spp_id_prefix(self): + if not self.is_registrant: + return "" + if self.is_group: + return "GRP" + return "IND" + + def _get_match_spp_id_pattern(self): + if not self.is_registrant: + return "" + if self.is_group: + return r"^GRP_[0-9A-Z]{8}$" + return r"^IND_[0-9A-Z]{8}$" diff --git a/spp_registrant_import/models/spp_area.py b/spp_registrant_import/models/spp_area.py new file mode 100644 index 00000000..72123f45 --- /dev/null +++ b/spp_registrant_import/models/spp_area.py @@ -0,0 +1,12 @@ +from odoo import models + + +class SppArea(models.Model): + _name = "spp.area" + _inherit = ["spp.area", "spp.unique.id"] + + def _get_spp_id_prefix(self): + return "LOC" + + def _get_match_spp_id_pattern(self): + return r"^LOC_[0-9A-Z]{8}$" diff --git a/spp_registrant_import/models/spp_service_point.py b/spp_registrant_import/models/spp_service_point.py new file mode 100644 index 00000000..74c76fb8 --- /dev/null +++ b/spp_registrant_import/models/spp_service_point.py @@ -0,0 +1,12 @@ +from odoo import models + + +class SppServicePoint(models.Model): + _name = "spp.service.point" + _inherit = ["spp.service.point", "spp.unique.id"] + + def _get_spp_id_prefix(self): + return "SVP" + + def _get_match_spp_id_pattern(self): + return r"^SVP_[0-9A-Z]{8}$" diff --git a/spp_registrant_import/tests/__init__.py b/spp_registrant_import/tests/__init__.py index dbaf412a..3b33b4eb 100644 --- a/spp_registrant_import/tests/__init__.py +++ b/spp_registrant_import/tests/__init__.py @@ -1 +1,3 @@ +from . import test_area from . import test_registrant +from . import test_service_point diff --git a/spp_registrant_import/tests/test_area.py b/spp_registrant_import/tests/test_area.py new file mode 100644 index 00000000..fea4ee99 --- /dev/null +++ b/spp_registrant_import/tests/test_area.py @@ -0,0 +1,58 @@ +from psycopg2.errors import UniqueViolation + +from odoo.exceptions import ValidationError +from odoo.tests import TransactionCase +from odoo.tools import mute_logger + +EXCLUDED_CHARACTERS = ["0", "O", "1", "I"] + + +class TestArea(TransactionCase): + def setUp(self): + super().setUp() + self.area_1, self.area_2 = self.env["spp.area"].create( + [ + {"draft_name": "Area 1"}, + {"draft_name": "Area 2"}, + ] + ) + + def test_01_compute_spp_id_uniq(self): + self.assertNotEqual(self.area_1.spp_id, self.area_2.spp_id) + + def test_02_compute_spp_id(self): + for area in [self.area_1, self.area_2]: + self.assertRegex( + area.spp_id, + r"^LOC_[a-zA-Z0-9]{8}$", + "Area should have unique id start with " + "`LOC_` and following by 8 characters.", + ) + for char in EXCLUDED_CHARACTERS: + self.assertNotIn( + char, + area.spp_id.split("_")[-1], + "Excluded characters should not be exist in spp_id", + ) + + @mute_logger("odoo.sql_db") + def test_03_spp_id_unique_violation(self): + with self.assertRaises(UniqueViolation): + self.area_1.write( + { + "spp_id": self.area_2.spp_id, + } + ) + + @mute_logger("py.warnings") + def test_04_check_spp_id(self): + with self.assertRaisesRegex( + ValidationError, "^.*not following correct format.{1}$" + ): + # 7 characters spp_id + self.area_1.write({"spp_id": "LOC_AaAaAa2"}) + with self.assertRaisesRegex( + ValidationError, "^.*not following correct format.{1}$" + ): + # '1' in spp_id + self.area_2.write({"spp_id": "LOC_AaAaAa21"}) diff --git a/spp_registrant_import/tests/test_registrant.py b/spp_registrant_import/tests/test_registrant.py index 984b553c..aeacc885 100644 --- a/spp_registrant_import/tests/test_registrant.py +++ b/spp_registrant_import/tests/test_registrant.py @@ -17,10 +17,10 @@ def setUp(self): "is_group": True, } ) - self._test_individuals = [ - self.create_registrant({"name": "TEST, INDIVIDUAL, 1"}), - self.create_registrant({"name": "TEST, INDIVIDUAL, 2"}), - ] + self._test_individuals = ( + self.create_registrant({"name": "TEST, INDIVIDUAL, 1"}) | + self.create_registrant({"name": "TEST, INDIVIDUAL, 2"}) + ) self._partner = self.env["res.partner"].create( { "name": "Partner 1", @@ -48,15 +48,15 @@ def create_registrant(self, vals): virtual_rec._compute_name() return model.create(virtual_rec._convert_to_write(virtual_rec._cache)) - def test_01_compute_registrant_id_normal_partner(self): + def test_01_compute_spp_id_normal_partner(self): self.assertFalse( - bool(self._partner.registrant_id), - "Normal Odoo contact should not have registrant_id", + bool(self._partner.spp_id), + "Normal Odoo contact should not have spp_id", ) - def test_02_compute_registrant_id_household(self): + def test_02_compute_spp_id_household(self): self.assertRegex( - self._test_household.registrant_id, + self._test_household.spp_id, r"^GRP_[a-zA-Z0-9]{8}$", "Household should have unique registrant id start with " "`GRP_` and following by 8 characters.", @@ -64,14 +64,14 @@ def test_02_compute_registrant_id_household(self): for char in EXCLUDED_CHARACTERS: self.assertNotIn( char, - self._test_household.registrant_id.split("_")[-1], - "Excluded characters should not be exist in unique registrant_id", + self._test_household.spp_id.split("_")[-1], + "Excluded characters should not be exist in unique spp_id", ) - def test_03_compute_registrant_id_individual(self): + def test_03_compute_spp_id_individual(self): for individual in self._test_individuals: self.assertRegex( - individual.registrant_id, + individual.spp_id, r"^IND_[a-zA-Z0-9]{8}$", "Individual should have unique registrant id start with " "`IND_` and following by 8 characters.", @@ -79,42 +79,42 @@ def test_03_compute_registrant_id_individual(self): for char in EXCLUDED_CHARACTERS: self.assertNotIn( char, - individual.registrant_id.split("_")[-1], - "Excluded characters should not be exist in unique registrant_id", + individual.spp_id.split("_")[-1], + "Excluded characters should not be exist in unique spp_id", ) @mute_logger("odoo.sql_db") - def test_04_compute_registrant_id_unique_violation(self): + def test_04_compute_spp_id_unique_violation(self): with (self.env.cr.savepoint(), self.assertRaises(UniqueViolation)): self._test_individuals[0].write( { - "registrant_id": self._test_individuals[1].registrant_id, + "spp_id": self._test_individuals[1].spp_id, } ) @mute_logger("py.warnings") - def test_05_check_registrant_id(self): + def test_05_check_spp_id(self): with self.assertRaisesRegex( ValidationError, "^.*not following correct format.{1}$" ): - # 7 characters registrant_id - self._test_household.write({"registrant_id": "GRP_AAAAAA2"}) + # 7 characters spp_id + self._test_household.write({"spp_id": "GRP_AAAAAA2"}) with self.assertRaisesRegex( ValidationError, "^.*not following correct format.{1}$" ): - # '1' in registrant_id - self._test_individuals[0].write({"registrant_id": "IND_AAAAAA21"}) + # '1' in spp_id + self._test_individuals[0].write({"spp_id": "IND_AAAAAA21"}) with self.assertRaisesRegex( ValidationError, "^.*not following correct format.{1}$" ): - # individual with registrant_id starts with GRP_ - self._test_individuals[0].write({"registrant_id": "GRP_AAAAAA22"}) + # individual with spp_id starts with GRP_ + self._test_individuals[0].write({"spp_id": "GRP_AAAAAA22"}) with self.assertRaisesRegex( ValidationError, "^.*not following correct format.{1}$" ): - # group with registrant_id starts with IND_ - self._test_household.write({"registrant_id": "IND_AAAAAA22"}) - self._partner.write({"registrant_id": "IND_AAAAAA21"}) + # group with spp_id starts with IND_ + self._test_household.write({"spp_id": "IND_AAAAAA22"}) + self._partner.write({"spp_id": "IND_AAAAAA21"}) def test_06__inverse_name(self): registrant_1 = self._test_individuals[0] diff --git a/spp_registrant_import/tests/test_service_point.py b/spp_registrant_import/tests/test_service_point.py new file mode 100644 index 00000000..e2878489 --- /dev/null +++ b/spp_registrant_import/tests/test_service_point.py @@ -0,0 +1,60 @@ +from psycopg2.errors import UniqueViolation + +from odoo.exceptions import ValidationError +from odoo.tests import TransactionCase +from odoo.tools import mute_logger + +EXCLUDED_CHARACTERS = ["0", "O", "1", "I"] + + +class TestServicePoint(TransactionCase): + def setUp(self): + super().setUp() + self.service_point_1, self.service_point_2 = self.env[ + "spp.service.point" + ].create( + [ + {"name": "Service Point 1"}, + {"name": "Service Point 2"}, + ] + ) + + def test_01_compute_spp_id_uniq(self): + self.assertNotEqual(self.service_point_1.spp_id, self.service_point_2.spp_id) + + def test_02_compute_spp_id(self): + for area in [self.service_point_1, self.service_point_2]: + self.assertRegex( + area.spp_id, + r"^SVP_[a-zA-Z0-9]{8}$", + "Area should have unique id start with " + "`SVP_` and following by 8 characters.", + ) + for char in EXCLUDED_CHARACTERS: + self.assertNotIn( + char, + area.spp_id.split("_")[-1], + "Excluded characters should not be exist in spp_id", + ) + + @mute_logger("odoo.sql_db") + def test_03_spp_id_unique_violation(self): + with self.assertRaises(UniqueViolation): + self.service_point_1.write( + { + "spp_id": self.service_point_2.spp_id, + } + ) + + @mute_logger("py.warnings") + def test_04_check_spp_id(self): + with self.assertRaisesRegex( + ValidationError, "^.*not following correct format.{1}$" + ): + # 7 characters spp_id + self.service_point_1.write({"spp_id": "SVP_AaAaAa2"}) + with self.assertRaisesRegex( + ValidationError, "^.*not following correct format.{1}$" + ): + # '1' in spp_id + self.service_point_2.write({"spp_id": "SVP_AaAaAa21"}) diff --git a/spp_registrant_import/views/res_partner_views.xml b/spp_registrant_import/views/res_partner_views.xml index d00559cb..651abee2 100644 --- a/spp_registrant_import/views/res_partner_views.xml +++ b/spp_registrant_import/views/res_partner_views.xml @@ -7,9 +7,9 @@ -
-