Skip to content

Commit

Permalink
Issue #229: Rework Inspection model & controller
Browse files Browse the repository at this point in the history
  • Loading branch information
Francois-Werbrouck committed Feb 7, 2025
1 parent d809ad8 commit c919ea0
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 166 deletions.
261 changes: 137 additions & 124 deletions fertiscan/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,112 +30,177 @@
if FERTISCAN_STORAGE_URL is None or FERTISCAN_STORAGE_URL == "":
print("Warning: FERTISCAN_STORAGE_URL not set")

class Inspection(BaseModel):
id: UUID
user_id: UUID
folder_id : UUID
label_id: Optional[UUID] = None
verified: Optional[bool] = None

class InspectionController:
def __init__(self,inspection_model: Inspection):
self.model:Inspection = inspection_model


def register_analysis(
def __init__(self,inspection_model:data_inspection.Inspection):
self.model:data_inspection.Inspection = inspection_model
self.id:UUID = inspection_model.inspection_id
return

def get_inspection_image_location_data(
self,
cursor: Cursor,
analysis_dict,
):
cursor: Cursor
)->tuple[UUID,UUID]:
"""
Register an analysis in the database
Retrieve the relevant information regarding where the Inspection Images are stored
This is usefull to perform Container_Controller.get_folder_pictures()
Parameters:
- cursor: The cursor object to interact with the database.
- container_client: The container client of the user.
- analysis_dict (dict): The analysis to register in a dict string
- cursor (Cursor): Database cursor for executing queries.
Returns:
- The analysis_dict with the analysis_id added.
- tuple (container_id: UUID, folder: UUID): The id necessary to locate the images
"""
if not user.is_a_user_id(cursor=cursor, user_id=self.model.user_id):
raise user.UserNotFoundError(f"User not found based on the given id: {self.model.user_id}")
# Register analysis in the database
formatted_analysis = data_inspection.build_inspection_import(analysis_dict,user_id)
if not inspection.is_a_inspection_id(cursor=cursor, inspection_id=self.id):
raise inspection.InspectionNotFoundError(
f"Inspection not found based on the given id: {self.id}"
)
picture_set_id = inspection.get_inspection_fk(cursor,self.id)[2]

analysis_db = inspection.new_inspection_with_label_info(
cursor, self.model.user_id, self.model.folder_id, formatted_analysis
)
self.model.id = analysis_db["inspection_id"]
return analysis_db
container_id = picture.get_picture_set_container_id(
cursor=cursor,
picture_set_id=picture_set_id
)
return (container_id,picture_set_id)

def update_inspection(
self,
cursor: Cursor,
user_id: UUID,
updated_data: dict | data_inspection.Inspection,
):
)->data_inspection.Inspection:
"""
Update an existing inspection record in the database.
Update an existing inspection record in the database.
Parameters:
- cursor (Cursor): Database cursor for executing queries.
- inspection_id (str | UUID): UUID of the inspection to update.
- user_id (str | UUID): UUID of the user performing the update.
- updated_data (dict | data_inspection.Inspection): Dictionary or Inspection model containing updated inspection data.
Parameters:
- cursor (Cursor): Database cursor for executing queries.
- inspection_id (str | UUID): UUID of the inspection to update.
- user_id (str | UUID): UUID of the user performing the update.
- updated_data (dict | data_inspection.Inspection): Dictionary or Inspection model containing updated inspection data.
Returns:
- data_inspection.Inspection: Updated inspection data from the database.
Returns:
- data_inspection.Inspection: Updated inspection data from the database.
Raises:
- InspectionUpdateError: If an error occurs during the update.
"""
Raises:
- InspectionUpdateError: If an error occurs during the update.
"""
if not user.is_a_user_id(cursor=cursor, user_id=self.model.user_id):
raise user.UserNotFoundError(f"User not found based on the given id: {self.model.user_id}")

raise user.UserNotFoundError(f"User not found based on the given id: {self.model.user_id}")
if not isinstance(updated_data, data_inspection.Inspection):
updated_data = data_inspection.Inspection.model_validate(updated_data)

updated_data = data_inspection.Inspection.model_validate(updated_data)
# The inspection record must exist before updating it
if not inspection.is_a_inspection_id(cursor, str(self.model.id)):
raise inspection.InspectionNotFoundError(
f"Inspection not found based on the given id: {self.model.id}"
)

raise inspection.InspectionNotFoundError(
f"Inspection not found based on the given id: {self.model.id}"
)
if self.model.container_id != updated_data.container_id or self.model.folder_id != updated_data.folder_id:
raise Warning("You should not update an Inspection picture location. This does not cause issues in the DB but could result in errors when attempting to fetch the pictures")
if not datastore.container_db.is_a_container(cursor=cursor,container_id=updated_data.container_id):
raise datastore.ContainerCreationError(f"Container not found based on the given id: {updated_data.container_id}")
# Make sure the user can verify this inspection
if not datastore.verify_user_can_write(cursor=cursor,container_id=updated_data.container_id,user_id=user_id):
raise datastore.PermissionNotHighEnough(f"The user {user_id} does not have the write permission or higher which mean he cannot upload an inspection in the container {container_id}")

Check failure on line 101 in fertiscan/__init__.py

View workflow job for this annotation

GitHub Actions / datastore-lint-test-python / lint-test

Ruff (F821)

fertiscan/__init__.py:101:179: F821 Undefined name `container_id`

updated_result = inspection.update_inspection(
cursor, self.model.id, self.model.user_id, updated_data.model_dump()
)
return data_inspection.Inspection.model_validate(updated_result)

def get_full_inspection_analysis(
def delete_inspection(
self,
cursor:Cursor,
):
user_id: UUID,
)-> data_inspection.DBInspection:
"""
Get the full inspection json from the database
Delete an existing inspection record and its associated picture set from the database.
Parameters:
- cursor (Cursor): Database cursor for executing queries.
- inspection_id (str | UUID): UUID of the inspection to delete.
- user_id (str | UUID): UUID of the user performing the deletion.
Returns:
- data_inspection.Inspection: The deleted inspection data from the database.
"""
if not user.is_a_user_id(cursor=cursor, user_id=user_id):
raise user.UserNotFoundError(f"User not found based on the given id: {user_id}")
if not datastore.container_db.is_a_container(cursor=cursor,container_id=self.id):
raise datastore.ContainerCreationError(f"Container not found based on the given id: {self.id}")
if not datastore.verify_user_can_write(cursor=cursor,container_id=self.id,user_id=user_id):
raise datastore.PermissionNotHighEnough(f"The user {user_id} does not have the write permission or higher which mean he cannot upload an inspection in the container {container_id}")

Check failure on line 130 in fertiscan/__init__.py

View workflow job for this annotation

GitHub Actions / datastore-lint-test-python / lint-test

Ruff (F821)

fertiscan/__init__.py:130:179: F821 Undefined name `container_id`

# Delete the inspection and get the returned data
deleted_inspection = inspection.delete_inspection(cursor, self.id, user_id)
deleted_inspection = data_inspection.DBInspection.model_validate(deleted_inspection)
container_controller:ContainerController = datastore.get_container_controller(cursor,self.id)

container_controller.delete_folder_permanently(cursor,user_id,self.model.folder_id)
return deleted_inspection

def new_inspection(cursor:Cursor, user_id:UUID, analysis_dict, container_id:UUID, folder_id:UUID)->InspectionController:
"""
Register an analysis in the database
Parameters:
- cursor: The cursor object to interact with the database.
- container_client: The container client of the user.
- analysis_dict (dict): The analysis to register in a dict string
Returns:
- The analysis_dict with the analysis_id added.
"""
if not user.is_a_user_id(cursor=cursor, user_id=user_id):
raise user.UserNotFoundError(f"User not found based on the given id: {user_id}")
if not datastore.container_db.is_a_container(cursor=cursor,container_id=container_id):
raise datastore.ContainerCreationError(f"Container not found based on the given id: {container_id}")
if not datastore.verify_user_can_write(cursor=cursor,container_id=container_id,user_id=user_id):
raise datastore.PermissionNotHighEnough(f"The user {user_id} does not have the write permission or higher which mean he cannot upload an inspection in the container {container_id}")

formatted_analysis = data_inspection.build_inspection_import(
analysis_form=analysis_dict,
user_id=user_id,
folder_id=folder_id,
container_id=container_id)

analysis_db = inspection.new_inspection_with_label_info(
cursor, user_id, folder_id, formatted_analysis
)
analysis_db = data_inspection.Inspection.model_validate(analysis_db)
inspection_controller = InspectionController(analysis_db)

return inspection_controller

def get_inspection(
cursor:Cursor,
inspection_id:UUID,
)->InspectionController:
"""
Get the full inspection json from the database and return a controller for it
Parameters:
- cursor: The cursor object to interact with the database.
Returns:
- The inspection json.
"""
if not inspection.is_a_inspection_id(cursor=cursor, inspection_id=self.model.id):
raise inspection.InspectionNotFoundError(
if not inspection.is_a_inspection_id(cursor=cursor, inspection_id=inspection_id):
raise inspection.InspectionNotFoundError(
f"Inspection not found based on the given id: {self.model.id}"

Check failure on line 188 in fertiscan/__init__.py

View workflow job for this annotation

GitHub Actions / datastore-lint-test-python / lint-test

Ruff (F821)

fertiscan/__init__.py:188:64: F821 Undefined name `self`
)

# Retrieve label_info
inspection_metadata = data_inspection.build_inspection_export(
cursor, self.model.id
)
return inspection_metadata

def get_user_analysis_by_verified(
self,
cursor:Cursor,
verified : bool
):
"""

# Retrieve label_info
inspection_metadata = data_inspection.build_inspection_export(
cursor, inspection_id
)
inspection_controller = InspectionController(inspection_model=inspection_metadata)
return inspection_controller

def get_user_analysis_by_verified(
cursor:Cursor,
user_id:UUID,
verified : bool
):
"""
This function fetch all the inspection of a user
Parameters:
- cursor: The cursor object to interact with the database.
Expand All @@ -156,59 +221,7 @@ def get_user_analysis_by_verified(
company_info.company_name
]
"""
if not user.is_a_user_id(cursor=cursor, user_id=self.model.user_id):
raise user.UserNotFoundError(f"User not found based on the given id: {self.model.user_id}")
return inspection.get_all_user_inspection_filter_verified(cursor, self.model.user_id, verified)

def delete_inspection(
self,
cursor:Cursor,
container_id: UUID,
)-> data_inspection.DBInspection:
"""
Delete an existing inspection record and its associated picture set from the database.
Parameters:
- cursor (Cursor): Database cursor for executing queries.
- inspection_id (str | UUID): UUID of the inspection to delete.
- user_id (str | UUID): UUID of the user performing the deletion.
Returns:
- data_inspection.Inspection: The deleted inspection data from the database.
"""

# Delete the inspection and get the returned data
deleted_inspection = inspection.delete_inspection(cursor, self.model.id, self.model.user_id)
deleted_inspection = data_inspection.DBInspection.model_validate(deleted_inspection)
container_controller:ContainerController = datastore.get_container_controller(cursor,container_id)

container_controller.delete_folder_permanently(cursor,self.model.user_id,self.model.folder_id)
if not user.is_a_user_id(cursor=cursor, user_id=user_id):
raise user.UserNotFoundError(f"User not found based on the given id: {user_id}")
return inspection.get_all_user_inspection_filter_verified(cursor, user_id, verified)

return deleted_inspection

def get_inspection_image_location_data(
self,
cursor: Cursor,
)->tuple[UUID,UUID]:
"""
Retrieve the relevant information regarding where the Inspection Images are stored
This is usefull to perform Container_Controller.get_folder_pictures()
Parameters:
- cursor (Cursor): Database cursor for executing queries.
Returns:
- tuple (container_id: UUID, folder: UUID): The id necessary to locate the images
"""
if not inspection.is_a_inspection_id(cursor=cursor, inspection_id=self.model.id):
raise inspection.InspectionNotFoundError(
f"Inspection not found based on the given id: {self.model.id}"
)
picture_set_id = inspection.get_inspection_fk(cursor,self.model.id)[2]

container_id = picture.get_picture_set_container_id(
cursor=cursor,
picture_set_id=picture_set_id
)
return (container_id,picture_set_id)
16 changes: 10 additions & 6 deletions fertiscan/db/metadata/inspection/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from datetime import datetime
from typing import List, Optional
from uuid import UUID

from pydantic import UUID4, BaseModel, ValidationError, model_validator

Expand Down Expand Up @@ -145,9 +146,12 @@ class Inspection(ValidatedModel):
instructions: SubLabel
guaranteed_analysis: GuaranteedAnalysis
ingredients: ValuesObjects
folder_id: UUID4
container_id: UUID4



def build_inspection_import(analysis_form: dict, user_id) -> str:
def build_inspection_import(analysis_form: dict, user_id:UUID,folder_id:UUID,container_id:UUID) -> Inspection:
"""
This funtion build an inspection json object from the pipeline of digitalization analysis.
This serves as the metadata for the inspection object in the database.
Expand Down Expand Up @@ -349,9 +353,10 @@ def build_inspection_import(analysis_form: dict, user_id) -> str:
guaranteed_analysis=guaranteed,
registration_numbers=reg_numbers,
ingredients=ingredients,
folder_id=folder_id,
container_id=container_id
)
Inspection(**inspection_formatted.model_dump())
return inspection_formatted.model_dump_json()
return inspection_formatted
except MetadataError:
raise
except ValidationError as e:
Expand All @@ -360,7 +365,7 @@ def build_inspection_import(analysis_form: dict, user_id) -> str:
raise BuildInspectionImportError(f"Unexpected error: {e}") from e


def build_inspection_export(cursor, inspection_id) -> str:
def build_inspection_export(cursor, inspection_id) -> Inspection:
"""
This funtion build an inspection json object from the database.
"""
Expand Down Expand Up @@ -429,8 +434,7 @@ def build_inspection_export(cursor, inspection_id) -> str:
verified=db_inspection.verified,
ingredients=ingredients,
)

return inspection_formatted.model_dump_json()
return inspection_formatted
except QueryError as e:
raise BuildInspectionExportError(f"Error fetching data: {e}") from e
except Exception as e:
Expand Down
2 changes: 2 additions & 0 deletions fertiscan/doc/inspection-view.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ object representing it.
```JSON
{
"inspection_id": "inspection uuid",
"container_id": "container_uuid",
"folder_id": "folder_uuid",
"owner_id": "Organization uuid",
"organizations": [
{
Expand Down
Loading

0 comments on commit c919ea0

Please sign in to comment.