Added validation rules regarding port_id (for berth and participant assignment)

This commit is contained in:
Daniel Schick 2024-10-23 09:55:56 +02:00
parent 0d7861ec36
commit 72d3ad05bf
4 changed files with 43 additions and 23 deletions

View File

@ -28,3 +28,9 @@ def get_shipcall_data_for_id(shipcall_id:int):
query = "SELECT * FROM shipcall where id = ?id?" query = "SELECT * FROM shipcall where id = ?id?"
pdata = execute_sql_query_standalone(query=query, param={"id":shipcall_id}, command_type="single_or_none") pdata = execute_sql_query_standalone(query=query, param={"id":shipcall_id}, command_type="single_or_none")
return pdata return pdata
def get_port_ids_for_participant_id(participant_id:int):
"""helper function to load all port ids for a participant"""
query = "SELECT port_id FROM participant_port_map where participant_id = ?participant_id?"
pdata = execute_sql_query_standalone(query=query, param={"participant_id":participant_id})
return pdata

View File

@ -237,21 +237,22 @@ class InputValidationShipcall():
ship_id = loadedModel.get("ship_id", None) ship_id = loadedModel.get("ship_id", None)
arrival_berth_id = loadedModel.get("arrival_berth_id", None) arrival_berth_id = loadedModel.get("arrival_berth_id", None)
departure_berth_id = loadedModel.get("departure_berth_id", None) departure_berth_id = loadedModel.get("departure_berth_id", None)
port_id = loadedModel.get("port_id", None)
participants = loadedModel.get("participants",[]) participants = loadedModel.get("participants",[])
valid_ship_id = check_if_ship_id_is_valid(ship_id=ship_id) valid_ship_id = check_if_ship_id_is_valid(ship_id=ship_id)
if not valid_ship_id: if not valid_ship_id:
raise ValidationError({"ship_id":f"provided an invalid ship id, which is not found in the database: {ship_id}"}) raise ValidationError({"ship_id":f"provided an invalid ship id, which is not found in the database: {ship_id}"})
valid_arrival_berth_id = check_if_berth_id_is_valid(berth_id=arrival_berth_id) valid_arrival_berth_id = check_if_berth_id_is_valid(berth_id=arrival_berth_id, port_id=port_id)
if not valid_arrival_berth_id: if not valid_arrival_berth_id:
raise ValidationError({"arrival_berth_id":f"provided an invalid arrival berth id, which is not found in the database: {arrival_berth_id}"}) raise ValidationError({"arrival_berth_id":f"provided an invalid arrival berth id, which is not found in the database: {arrival_berth_id}, or the berth is not assigned to the port: {port_id}"})
valid_departure_berth_id = check_if_berth_id_is_valid(berth_id=departure_berth_id) valid_departure_berth_id = check_if_berth_id_is_valid(berth_id=departure_berth_id, port_id=port_id)
if not valid_departure_berth_id: if not valid_departure_berth_id:
raise ValidationError({"departure_berth_id":f"provided an invalid departure berth id, which is not found in the database: {departure_berth_id}"}) raise ValidationError({"departure_berth_id":f"provided an invalid departure berth id, which is not found in the database: {departure_berth_id}, or the berth is not assigned to the port: {port_id}"})
valid_participant_ids = check_if_participant_ids_are_valid(participants=participants) valid_participant_ids = check_if_participant_ids_are_valid(participants=participants, port_id=port_id)
if not valid_participant_ids: if not valid_participant_ids:
raise ValidationError({"participants":f"one of the provided participant ids is invalid. Could not find one of these in the database: {participants}"}) raise ValidationError({"participants":f"one of the provided participant ids is invalid. Could not find one of these in the database: {participants}"})

View File

@ -199,10 +199,11 @@ class InputValidationTimes():
""" """
# extract the IDs # extract the IDs
berth_id, shipcall_id, participant_id = content.get("berth_id"), content.get("shipcall_id"), content.get("participant_id") berth_id, shipcall_id, participant_id = content.get("berth_id"), content.get("shipcall_id"), content.get("participant_id")
port_id = content.get("port_id", None)
valid_berth_id_reference = check_if_berth_id_is_valid(berth_id) valid_berth_id_reference = check_if_berth_id_is_valid(berth_id, port_id)
if not valid_berth_id_reference: if not valid_berth_id_reference:
raise ValidationError({"berth_id":f"The referenced berth_id '{berth_id}' does not exist in the database."}) raise ValidationError({"berth_id":f"The referenced berth_id '{berth_id}' does not exist in the database or is not assigned to the port '{port_id}'."})
valid_shipcall_id_reference = check_if_shipcall_id_is_valid(shipcall_id) valid_shipcall_id_reference = check_if_shipcall_id_is_valid(shipcall_id)
if not valid_shipcall_id_reference: if not valid_shipcall_id_reference:

View File

@ -8,6 +8,7 @@ from BreCal.impl.berths import GetBerths
from BreCal.impl.shipcalls import GetShipcalls from BreCal.impl.shipcalls import GetShipcalls
from BreCal.database.enums import ParticipantType from BreCal.database.enums import ParticipantType
from BreCal.database.sql_utils import get_port_ids_for_participant_id
from marshmallow import ValidationError from marshmallow import ValidationError
def get_participant_id_dictionary(): def get_participant_id_dictionary():
@ -120,7 +121,7 @@ def check_if_ship_id_is_valid(ship_id):
ship_id_is_valid = ship_id in list(ships.keys()) ship_id_is_valid = ship_id in list(ships.keys())
return ship_id_is_valid return ship_id_is_valid
def check_if_berth_id_is_valid(berth_id): def check_if_berth_id_is_valid(berth_id, port_id=None):
"""check, whether the provided ID is valid. If it is 'None', it will be considered valid. This is, because a shipcall POST-request, does not have to include all IDs at once""" """check, whether the provided ID is valid. If it is 'None', it will be considered valid. This is, because a shipcall POST-request, does not have to include all IDs at once"""
if berth_id is None: if berth_id is None:
return True return True
@ -130,6 +131,12 @@ def check_if_berth_id_is_valid(berth_id):
# boolean check # boolean check
berth_id_is_valid = berth_id in list(berths.keys()) berth_id_is_valid = berth_id in list(berths.keys())
if port_id is not None:
# check, whether the berth is assigned to the respective port
berth_is_assigned_to_port = berths.get(berth_id,{}).get("port_id") == port_id
berth_id_is_valid = berth_id_is_valid and berth_is_assigned_to_port
return berth_id_is_valid return berth_id_is_valid
def check_if_shipcall_id_is_valid(shipcall_id:int): def check_if_shipcall_id_is_valid(shipcall_id:int):
@ -173,7 +180,7 @@ def check_if_participant_id_is_valid_standalone(participant_id:int, participant_
# when the participant_type is not provided, only evaluate the ID # when the participant_type is not provided, only evaluate the ID
return participant_id_is_valid return participant_id_is_valid
def check_if_participant_id_is_valid(participant:dict): def check_if_participant_id_is_valid(participant:dict, port_id=None):
""" """
check, whether the provided ID is valid. If it is 'None', it will be considered valid. This is, because a shipcall POST-request, does not have to include all IDs at once check, whether the provided ID is valid. If it is 'None', it will be considered valid. This is, because a shipcall POST-request, does not have to include all IDs at once
@ -185,9 +192,14 @@ def check_if_participant_id_is_valid(participant:dict):
participant_id = participant.get("participant_id", None) participant_id = participant.get("participant_id", None)
participant_type = ParticipantType(int(participant.get("type", ParticipantType.undefined))) participant_type = ParticipantType(int(participant.get("type", ParticipantType.undefined)))
participant_id_is_valid = check_if_participant_id_is_valid_standalone(participant_id, participant_type) participant_id_is_valid = check_if_participant_id_is_valid_standalone(participant_id, participant_type)
if participant_id_is_valid and port_id is not None:
# check, whether the participant is assigned to the respective port
participant_is_assigned_to_port = any(p.get('port_id', None) == port_id for p in get_port_ids_for_participant_id(participant_id))
participant_id_is_valid &= participant_is_assigned_to_port
return participant_id_is_valid return participant_id_is_valid
def check_if_participant_ids_are_valid(participants:list[dict]): def check_if_participant_ids_are_valid(participants:list[dict], port_id=None):
""" """
args: args:
@ -201,7 +213,7 @@ def check_if_participant_ids_are_valid(participants:list[dict]):
return False return False
# check each participant id individually # check each participant id individually
valid_participant_ids = [check_if_participant_id_is_valid(participant) for participant in participants] valid_participant_ids = [check_if_participant_id_is_valid(participant, port_id) for participant in participants]
# boolean check, whether all participant ids are valid # boolean check, whether all participant ids are valid
return all(valid_participant_ids) return all(valid_participant_ids)