Skip to content

Commit

Permalink
Merge pull request #153 from dibik96/17.0-develop
Browse files Browse the repository at this point in the history
G2P-2555: Status & description update and error handling with empty d…
  • Loading branch information
shibu-narayanan authored Jul 30, 2024
2 parents 7961b05 + 25dc54f commit c371ad3
Show file tree
Hide file tree
Showing 10 changed files with 211 additions and 30 deletions.
4 changes: 4 additions & 0 deletions g2p_registry_base/models/reg_id.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ class G2PRegistrantID(models.Model):
expiry_date = fields.Date()
id_type_as_str = fields.Char(related="id_type.name")

status = fields.Selection([("invalid", "Invalid"), ("valid", "Valid")], required=True)

description = fields.Char()

def _compute_display_name(self):
res = super()._compute_display_name()
for rec in self:
Expand Down
34 changes: 30 additions & 4 deletions g2p_registry_base/tests/test_reg_id.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,13 @@ def test_01_display_name(self):
id_type = self.id_type_model.create({"name": "Test ID Type", "id_validation": "[0-9]+"})

reg_id = self.reg_id_model.create(
{"partner_id": partner.id, "id_type": id_type.id, "value": "123456"}
{
"partner_id": partner.id,
"id_type": id_type.id,
"value": "123456",
"status": "valid",
"description": "Due to API",
}
)

# Call the _compute_display_name method
Expand All @@ -35,7 +41,13 @@ def test_02_create_registrant_id(self):
id_type = self.id_type_model.create({"name": "Test ID Type", "id_validation": "[0-9]+"})

reg_id = self.reg_id_model.create(
{"partner_id": partner.id, "id_type": id_type.id, "value": "123456"}
{
"partner_id": partner.id,
"id_type": id_type.id,
"value": "123456",
"status": "valid",
"description": "Due to API",
}
)
self.assertEqual(reg_id.value, "123456", "Registrant ID value is not as expected.")

Expand All @@ -44,15 +56,29 @@ def test_03_invalid_id_value(self):
id_type = self.id_type_model.create({"name": "Test ID Type", "id_validation": "[0-9]+"})

with self.assertRaises(ValidationError) as context:
self.reg_id_model.create({"partner_id": partner.id, "id_type": id_type.id, "value": "abc"})
self.reg_id_model.create(
{
"partner_id": partner.id,
"id_type": id_type.id,
"value": "abc",
"status": "valid",
"description": "Due to API",
}
)

self.assertIn("The provided Test ID Type ID 'abc' is invalid.", str(context.exception))

def test_04_name_search(self):
partner = self.partner_model.create({"name": "Test Partner", "is_registrant": True})
id_type = self.id_type_model.create({"name": "Test ID Type"})
reg_id = self.reg_id_model.create(
{"partner_id": partner.id, "id_type": id_type.id, "value": "Test Value"}
{
"partner_id": partner.id,
"id_type": id_type.id,
"value": "Test Value",
"status": "valid",
"description": "Due to API",
}
)
search_result = self.reg_id_model._name_search("Test Partner")
self.assertIn(reg_id.id, search_result, "Expected record not found in search result")
Expand Down
4 changes: 4 additions & 0 deletions g2p_registry_base/views/reg_id_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
<field name="partner_id" options="{'no_open':True,'no_create_edit':True,'no_create':True}" />
<field name="id_type" options="{'no_open':True,'no_create_edit':True,'no_create':True}" />
<field name="value" />
<field name="status" />
<field name="description" />
</tree>
</field>
</record>
Expand All @@ -24,6 +26,8 @@
<search string="Search Registrant IDs">
<field name="partner_id" />
<field name="value" />
<field name="status" />
<field name="description" />
<group expand="0" string="Group By">
<filter string="Registrant" name="grp_registrant" context="{'group_by': 'partner_id'}" />
</group>
Expand Down
7 changes: 6 additions & 1 deletion g2p_registry_group/tests/test_groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,12 @@ def test_02_add_id(self):
"name": "Testing ID Type",
}
)
vals = {"id_type": id_type.id, "value": "112233445566778899"}
vals = {
"id_type": id_type.id,
"value": "112233445566778899",
"status": "valid",
"description": "Due to API",
}

self.group_1.write({"reg_ids": [(0, 0, vals)]})
expected_value = "112233445566778899"
Expand Down
7 changes: 6 additions & 1 deletion g2p_registry_individual/tests/test_individuals.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,12 @@ def test_04_add_id(self):
"name": "Testing ID Type",
}
)
vals = {"id_type": id_type.id, "value": "112233445566778899"}
vals = {
"id_type": id_type.id,
"value": "112233445566778899",
"status": "valid",
"description": "Due to API",
}

self.registrant_1.write({"reg_ids": [(0, 0, vals)]})
expected_value = "112233445566778899"
Expand Down
7 changes: 7 additions & 0 deletions g2p_registry_individual/views/individuals_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,13 @@
/>
<field name="value" string="ID Number" />
<field name="expiry_date" />
<field name="status" readonly="1" widget="badge" decoration-info="1" />
<field
name="description"
readonly="1"
widget="badge"
decoration-warning="1"
/>
</tree>
</field>
</page>
Expand Down
80 changes: 73 additions & 7 deletions g2p_registry_rest_api/routers/individual.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,19 @@

from fastapi import APIRouter, Depends

from odoo import fields
from odoo.api import Environment

from odoo.addons.fastapi.dependencies import odoo_env

from ..exceptions.base_exception import G2PApiValidationError
from ..exceptions.error_codes import G2PErrorCodes
from ..schemas.individual import IndividualInfoRequest, IndividualInfoResponse, UpdateIndividualInfoRequest
from ..schemas.individual import (
IndividualInfoRequest,
IndividualInfoResponse,
UpdateIndividualInfoRequest,
UpdateIndividualInfoResponse,
)

individual_router = APIRouter(tags=["individual"])

Expand Down Expand Up @@ -92,7 +98,7 @@ async def get_ids(
if not include_id_type:
_handle_error(G2PErrorCodes.G2P_REQ_010, "Record is not present in the database.")

domain = [("is_registrant", "=", True), ("is_group", "=", False)]
domain = [("is_registrant", "=", True), ("is_group", "=", False), ("active", "=", True)]
if include_id_type:
domain.append(("reg_ids.id_type", "=", include_id_type))

Expand All @@ -115,12 +121,12 @@ async def get_ids(
_handle_error(G2PErrorCodes.G2P_REQ_010, "An error occurred while getting IDs.")


@individual_router.put("/update_individual", responses={200: {"model": IndividualInfoResponse}})
@individual_router.put("/update_individual", responses={200: {"model": UpdateIndividualInfoResponse}})
async def update_individual(
requests: list[UpdateIndividualInfoRequest],
env: Annotated[Environment, Depends(odoo_env)],
id_type: str | None = "",
) -> list[IndividualInfoResponse]:
) -> list[UpdateIndividualInfoResponse]:
"""
Update an individual
"""
Expand All @@ -134,7 +140,14 @@ async def update_individual(
partner_rec = (
env["res.partner"]
.sudo()
.search([("reg_ids.value", "=", _id), ("reg_ids.id_type", "=", id_type)], limit=1)
.search(
[
("reg_ids.value", "=", _id),
("reg_ids.id_type", "=", id_type),
("active", "=", True),
],
limit=1,
)
)
if not partner_rec:
_handle_error(
Expand All @@ -144,12 +157,65 @@ async def update_individual(

# Update the individual
indv_rec = env["process_individual.rest.mixin"]._process_individual(request)

logging.info("Individual Api: Updating Individual Record", indv_rec)

for reg_id in indv_rec["reg_ids"]:
id_type = reg_id[2].get("id_type")
value = reg_id[2].get("value")
status = reg_id[2].get("status")
description = reg_id[2].get("description")

id_rec = (
env["g2p.reg.id"]
.sudo()
.search(
[
("value", "=", value),
("id_type", "=", id_type),
],
limit=1,
)
)
if id_rec:
# Search for the partner
partner_rec = (
env["res.partner"]
.sudo()
.search(
[
("reg_ids.value", "=", value),
("reg_ids.id_type", "=", id_type),
("active", "=", True),
],
limit=1,
)
)

indv_rec.pop("reg_ids")

if partner_rec:
partner_rec.update(
{
"reg_ids": [
(
fields.Command.update(
id_rec.id,
{
"partner_id": partner_rec.id,
"id_type": id_type,
"value": value,
"status": status,
"description": description,
},
)
)
]
}
)

partner_rec.write(indv_rec)

results.append(IndividualInfoResponse.model_validate(partner_rec))
results.append(UpdateIndividualInfoResponse.model_validate(partner_rec))

else:
logging.error("ID & ID type is required for update individual")
Expand Down
22 changes: 14 additions & 8 deletions g2p_registry_rest_api/routers/process_individual_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,24 @@ class ProcessIndividualMixin(models.AbstractModel):

def _process_individual(self, individual):
indv_rec = {
"name": individual.name,
"registration_date": individual.registration_date,
"name": individual.name if individual.name else None,
"registration_date": individual.registration_date if individual.registration_date else None,
"is_registrant": True,
"is_group": False,
"email": individual.email,
"given_name": individual.given_name,
"family_name": individual.family_name,
"addl_name": individual.addl_name,
"birthdate": individual.birthdate or False,
"birth_place": individual.birth_place or False,
"email": individual.email if individual.email else None,
"given_name": individual.given_name if individual.given_name else None,
"family_name": individual.family_name if individual.family_name else None,
"addl_name": individual.addl_name if individual.addl_name else None,
"birthdate": individual.birthdate if individual.birthdate else None,
"birth_place": individual.birth_place if individual.birth_place else None,
"address": individual.address if individual.address else None,
"image_1920": individual.image_1920 if individual.image_1920 else None,
}

filtered_none = {key: value for key, value in indv_rec.items() if value is not None}
indv_rec.clear()
indv_rec.update(filtered_none)

ids = []
ids_info = individual
ids = ProcessIndividualMixin._process_ids(self, ids_info)
Expand Down Expand Up @@ -61,6 +65,8 @@ def _process_ids(self, ids_info):
"id_type": id_type_id[0].id,
"value": rec.value,
"expiry_date": rec.expiry_date,
"status": rec.status if rec.status else None,
"description": rec.description if rec.description else None,
},
)
)
Expand Down
24 changes: 21 additions & 3 deletions g2p_registry_rest_api/schemas/individual.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from datetime import date
from datetime import date, datetime

from pydantic import field_validator
from pydantic import Field, field_validator

from .registrant import RegistrantInfoRequest, RegistrantInfoResponse

Expand All @@ -27,11 +27,29 @@ class IndividualInfoRequest(RegistrantInfoRequest):
addl_name: str | None = None
family_name: str | None = None
gender: str | None
birthdate: date | None
birthdate: str = Field(
None, description="Date of birth in YYYY-MM-DD format", json_schema_extra={"examples": ["2000-01-01"]}
)
birth_place: str | None
is_group: bool = False

@field_validator("birthdate")
@classmethod
def parse_dob(cls, v):
if v is None or v == "":
return None
return datetime.strptime(v, "%Y-%m-%d").date()


class UpdateIndividualInfoRequest(IndividualInfoRequest):
updateId: str
image_1920: bytes | None = None
given_name: str | None
name: str | None


class UpdateIndividualInfoResponse(IndividualInfoResponse):
id: int | None = None
given_name: str | None = None
name: str | None = None
family_name: str | None = None
Loading

0 comments on commit c371ad3

Please sign in to comment.