Merge pull request #16 from puls200/feature/hotfix_20231114
Feature/hotfix 20231114
This commit is contained in:
commit
9b5206572a
@ -159,7 +159,10 @@ class SQLHandler():
|
||||
return all_data
|
||||
|
||||
def df_loc_to_data_model(self, df, id, model_str, loc_type:str="loc"):
|
||||
assert len(df)>0, f"empty dataframe"
|
||||
if not len(df)>0:
|
||||
import warnings
|
||||
warnings.warn(f"empty dataframe in SQLHandler.df_loc_to_data_model for model type: {model_str}\n")
|
||||
return df
|
||||
|
||||
# get a pandas series from the dataframe
|
||||
series = df.loc[id] if loc_type=="loc" else df.iloc[id]
|
||||
@ -176,7 +179,13 @@ class SQLHandler():
|
||||
|
||||
def get_times_for_participant_type(self, df_times, participant_type:int):
|
||||
filtered_series = df_times.loc[df_times["participant_type"]==participant_type]
|
||||
assert len(filtered_series)<=1, f"found multiple results"
|
||||
|
||||
if not len(filtered_series)<=1:
|
||||
# correcting the error: ERROR:root:found multiple results
|
||||
# however, a warning will still be issued
|
||||
import warnings
|
||||
warnings.warn(f"found multiple results in function SQLHandler.get_times_for_participant_type\nConsidering only the first match!\nAffected Times Indexes: {filtered_series.index}")
|
||||
|
||||
times = self.df_loc_to_data_model(filtered_series, id=0, model_str='times', loc_type="iloc") # use iloc! to retrieve the first result
|
||||
return times
|
||||
|
||||
@ -198,10 +207,13 @@ class SQLHandler():
|
||||
returns: participant_id_list, where every element is an int
|
||||
"""
|
||||
df = self.df_dict.get("shipcall_participant_map")
|
||||
df = df.set_index('shipcall_id', inplace=False)
|
||||
if 'shipcall_id' in list(df.columns):
|
||||
df = df.set_index('shipcall_id', inplace=False)
|
||||
|
||||
# the 'if' call is needed to ensure, that no Exception is raised, when the shipcall_id is not present in the df
|
||||
participant_id_list = df.loc[shipcall_id, "participant_id"].to_list() if shipcall_id in list(df.index) else []
|
||||
participant_id_list = df.loc[shipcall_id, "participant_id"].tolist() if shipcall_id in list(df.index) else []
|
||||
if not isinstance(participant_id_list,list):
|
||||
participant_id_list = [participant_id_list]
|
||||
return participant_id_list
|
||||
|
||||
def get_times_of_shipcall(self, shipcall)->pd.DataFrame:
|
||||
@ -237,8 +249,8 @@ class SQLHandler():
|
||||
"""given a dataframe of all agency times, get all unique ship counts, their values (datetime) and the string tags. returns a tuple (values,unique,counts)"""
|
||||
# optional: rounding
|
||||
if rounding is not None:
|
||||
all_df_times.loc[:, query] = all_df_times.loc[:, query].dt.round(rounding) # e.g., 'min'
|
||||
query_time_agency = times_agency[query].iloc[0].round(rounding)# e.g., 'min'
|
||||
all_df_times.loc[:, query] = pd.to_datetime(all_df_times.loc[:, query]).dt.round(rounding) # e.g., 'min' --- # correcting the error: 'AttributeError: Can only use .dt accessor with datetimelike values'
|
||||
query_time_agency = pd.to_datetime(times_agency[query]).iloc[0].round(rounding)# e.g., 'min'
|
||||
|
||||
# after rounding, filter {all_df_times}, so only those, which match the current query are of interest
|
||||
# takes 'times_agency' to sample, which value should match
|
||||
|
||||
@ -63,6 +63,10 @@ class ValidationRuleBaseFunctions():
|
||||
returns: string
|
||||
"""
|
||||
return self.error_message_dict.get(key,key)
|
||||
|
||||
def get_no_violation_default_output(self):
|
||||
"""return the default output of a validation function with no validation: a tuple of (GREEN state, None)"""
|
||||
return (StatusFlags.GREEN, None)
|
||||
|
||||
def check_time_delta_violation_query_time_to_now(self, query_time:pd.Timestamp, key_time:pd.Timestamp, threshold:float)->bool:
|
||||
"""
|
||||
@ -209,7 +213,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||
"""
|
||||
# check, if the header is filled in (agency)
|
||||
if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value])]) != 1:
|
||||
return (StatusFlags.GREEN, None)
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
# preparation: obtain the correct times of the participant, define the query time and the key time
|
||||
times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value)
|
||||
@ -219,10 +223,10 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||
violation_state = self.check_time_delta_violation_query_time_to_now(query_time=query_time, key_time=key_time, threshold=threshold)
|
||||
|
||||
if violation_state:
|
||||
validation_name = inspect.currentframe().f_code.co_name
|
||||
validation_name = "validation_rule_fct_missing_time_agency_berth_eta"
|
||||
return (StatusFlags.YELLOW, validation_name)
|
||||
else:
|
||||
return (StatusFlags.GREEN, None)
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
def validation_rule_fct_missing_time_agency_berth_etd(self, shipcall, df_times, *args, **kwargs):
|
||||
"""
|
||||
@ -237,7 +241,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||
"""
|
||||
# check, if the header is filled in (agency)
|
||||
if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value])]) != 1:
|
||||
return (StatusFlags.GREEN, None)
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
# preparation: obtain the correct times of the participant, define the query time and the key time
|
||||
times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value)
|
||||
@ -247,10 +251,10 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||
violation_state = self.check_time_delta_violation_query_time_to_now(query_time=query_time, key_time=key_time, threshold=threshold)
|
||||
|
||||
if violation_state:
|
||||
validation_name = inspect.currentframe().f_code.co_name
|
||||
validation_name = "validation_rule_fct_missing_time_agency_berth_etd"
|
||||
return (StatusFlags.YELLOW, validation_name)
|
||||
else:
|
||||
return (StatusFlags.GREEN, None)
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
def validation_rule_fct_missing_time_mooring_berth_eta(self, shipcall, df_times, *args, **kwargs):
|
||||
"""
|
||||
@ -264,8 +268,8 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||
- Measures the difference between 'now' and 'times_agency.eta_berth'.
|
||||
"""
|
||||
# check, if the header is filled in (agency & MOORING)
|
||||
if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value, ParticipantType.MOORING.value])]) != 2:
|
||||
return (StatusFlags.GREEN, None)
|
||||
if (len(df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]) != 1) or (len(df_times.loc[df_times["participant_type"]==ParticipantType.MOORING.value]) != 1):
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
# preparation: obtain the correct times of the participant, define the query time and the key time
|
||||
times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value)
|
||||
@ -277,10 +281,10 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||
violation_state = self.check_time_delta_violation_query_time_to_now(query_time=query_time, key_time=key_time, threshold=threshold)
|
||||
|
||||
if violation_state:
|
||||
validation_name = inspect.currentframe().f_code.co_name
|
||||
validation_name = "validation_rule_fct_missing_time_mooring_berth_eta"
|
||||
return (StatusFlags.YELLOW, validation_name)
|
||||
else:
|
||||
return (StatusFlags.GREEN, None)
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
def validation_rule_fct_missing_time_mooring_berth_etd(self, shipcall, df_times, *args, **kwargs):
|
||||
"""
|
||||
@ -294,8 +298,8 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||
- Measures the difference between 'now' and 'times_agency.etd_berth'.
|
||||
"""
|
||||
# check, if the header is filled in (agency & MOORING)
|
||||
if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value, ParticipantType.MOORING.value])]) != 2:
|
||||
return (StatusFlags.GREEN, None)
|
||||
if (len(df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]) != 1) or (len(df_times.loc[df_times["participant_type"]==ParticipantType.MOORING.value]) != 1):
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
# preparation: obtain the correct times of the participant, define the query time and the key time
|
||||
times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value)
|
||||
@ -307,10 +311,10 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||
violation_state = self.check_time_delta_violation_query_time_to_now(query_time=query_time, key_time=key_time, threshold=threshold)
|
||||
|
||||
if violation_state:
|
||||
validation_name = inspect.currentframe().f_code.co_name
|
||||
validation_name = "validation_rule_fct_missing_time_mooring_berth_etd"
|
||||
return (StatusFlags.YELLOW, validation_name)
|
||||
else:
|
||||
return (StatusFlags.GREEN, None)
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
def validation_rule_fct_missing_time_portadministration_berth_eta(self, shipcall, df_times, *args, **kwargs):
|
||||
"""
|
||||
@ -324,8 +328,8 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||
- Measures the difference between 'now' and 'times_agency.eta_berth'.
|
||||
"""
|
||||
# check, if the header is filled in (agency & PORT_ADMINISTRATION)
|
||||
if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value, ParticipantType.PORT_ADMINISTRATION.value])]) != 2:
|
||||
return (StatusFlags.GREEN, None)
|
||||
if (len(df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]) != 1) or (len(df_times.loc[df_times["participant_type"]==ParticipantType.PORT_ADMINISTRATION.value]) != 1):
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
# preparation: obtain the correct times of the participant, define the query time and the key time
|
||||
times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value)
|
||||
@ -337,10 +341,10 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||
violation_state = self.check_time_delta_violation_query_time_to_now(query_time=query_time, key_time=key_time, threshold=threshold)
|
||||
|
||||
if violation_state:
|
||||
validation_name = inspect.currentframe().f_code.co_name
|
||||
validation_name = "validation_rule_fct_missing_time_portadministration_berth_eta"
|
||||
return (StatusFlags.YELLOW, validation_name)
|
||||
else:
|
||||
return (StatusFlags.GREEN, None)
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
def validation_rule_fct_missing_time_portadministration_berth_etd(self, shipcall, df_times, *args, **kwargs):
|
||||
"""
|
||||
@ -354,8 +358,8 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||
- Measures the difference between 'now' and 'times_agency.etd_berth'.
|
||||
"""
|
||||
# check, if the header is filled in (agency & PORT_ADMINISTRATION)
|
||||
if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value, ParticipantType.PORT_ADMINISTRATION.value])]) != 2:
|
||||
return (StatusFlags.GREEN, None)
|
||||
if (len(df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]) != 1) or (len(df_times.loc[df_times["participant_type"]==ParticipantType.PORT_ADMINISTRATION.value]) != 1):
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
# preparation: obtain the correct times of the participant, define the query time and the key time
|
||||
times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value)
|
||||
@ -367,10 +371,10 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||
violation_state = self.check_time_delta_violation_query_time_to_now(query_time=query_time, key_time=key_time, threshold=threshold)
|
||||
|
||||
if violation_state:
|
||||
validation_name = inspect.currentframe().f_code.co_name
|
||||
validation_name = "validation_rule_fct_missing_time_portadministration_berth_etd"
|
||||
return (StatusFlags.YELLOW, validation_name)
|
||||
else:
|
||||
return (StatusFlags.GREEN, None)
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
def validation_rule_fct_missing_time_pilot_berth_eta(self, shipcall, df_times, *args, **kwargs):
|
||||
"""
|
||||
@ -384,8 +388,8 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||
- Measures the difference between 'now' and 'times_agency.eta_berth'.
|
||||
"""
|
||||
# check, if the header is filled in (agency & PILOT)
|
||||
if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value, ParticipantType.PILOT.value])]) != 2:
|
||||
return (StatusFlags.GREEN, None)
|
||||
if (len(df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]) != 1) or (len(df_times.loc[df_times["participant_type"]==ParticipantType.PILOT.value]) != 1):
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
# preparation: obtain the correct times of the participant, define the query time and the key time
|
||||
times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value)
|
||||
@ -397,10 +401,10 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||
violation_state = self.check_time_delta_violation_query_time_to_now(query_time=query_time, key_time=key_time, threshold=threshold)
|
||||
|
||||
if violation_state:
|
||||
validation_name = inspect.currentframe().f_code.co_name
|
||||
validation_name = "validation_rule_fct_missing_time_pilot_berth_eta"
|
||||
return (StatusFlags.YELLOW, validation_name)
|
||||
else:
|
||||
return (StatusFlags.GREEN, None)
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
def validation_rule_fct_missing_time_pilot_berth_etd(self, shipcall, df_times, *args, **kwargs):
|
||||
"""
|
||||
@ -414,8 +418,8 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||
- Measures the difference between 'now' and 'times_agency.etd_berth'.
|
||||
"""
|
||||
# check, if the header is filled in (agency & PILOT)
|
||||
if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value, ParticipantType.PILOT.value])]) != 2:
|
||||
return (StatusFlags.GREEN, None)
|
||||
if (len(df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]) != 1) or (len(df_times.loc[df_times["participant_type"]==ParticipantType.PILOT.value]) != 1):
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
# preparation: obtain the correct times of the participant, define the query time and the key time
|
||||
times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value)
|
||||
@ -427,10 +431,10 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||
violation_state = self.check_time_delta_violation_query_time_to_now(query_time=query_time, key_time=key_time, threshold=threshold)
|
||||
|
||||
if violation_state:
|
||||
validation_name = inspect.currentframe().f_code.co_name
|
||||
validation_name = "validation_rule_fct_missing_time_pilot_berth_etd"
|
||||
return (StatusFlags.YELLOW, validation_name)
|
||||
else:
|
||||
return (StatusFlags.GREEN, None)
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
def validation_rule_fct_missing_time_tug_berth_eta(self, shipcall, df_times, *args, **kwargs):
|
||||
"""
|
||||
@ -444,8 +448,8 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||
- Measures the difference between 'now' and 'times_agency.eta_berth'.
|
||||
"""
|
||||
# check, if the header is filled in (agency & TUG)
|
||||
if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value, ParticipantType.TUG.value])]) != 2:
|
||||
return (StatusFlags.GREEN, None)
|
||||
if (len(df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]) != 1) or (len(df_times.loc[df_times["participant_type"]==ParticipantType.TUG.value]) != 1):
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
# preparation: obtain the correct times of the participant, define the query time and the key time
|
||||
times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value)
|
||||
@ -457,10 +461,10 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||
violation_state = self.check_time_delta_violation_query_time_to_now(query_time=query_time, key_time=key_time, threshold=threshold)
|
||||
|
||||
if violation_state:
|
||||
validation_name = inspect.currentframe().f_code.co_name
|
||||
validation_name = "validation_rule_fct_missing_time_tug_berth_eta"
|
||||
return (StatusFlags.YELLOW, validation_name)
|
||||
else:
|
||||
return (StatusFlags.GREEN, None)
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
def validation_rule_fct_missing_time_tug_berth_etd(self, shipcall, df_times, *args, **kwargs):
|
||||
"""
|
||||
@ -474,8 +478,8 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||
- Measures the difference between 'now' and 'times_agency.etd_berth'.
|
||||
"""
|
||||
# check, if the header is filled in (agency & TUG)
|
||||
if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value, ParticipantType.TUG.value])]) != 2:
|
||||
return (StatusFlags.GREEN, None)
|
||||
if (len(df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]) != 1) or (len(df_times.loc[df_times["participant_type"]==ParticipantType.TUG.value]) != 1):
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
# preparation: obtain the correct times of the participant, define the query time and the key time
|
||||
times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value)
|
||||
@ -487,10 +491,10 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||
violation_state = self.check_time_delta_violation_query_time_to_now(query_time=query_time, key_time=key_time, threshold=threshold)
|
||||
|
||||
if violation_state:
|
||||
validation_name = inspect.currentframe().f_code.co_name
|
||||
validation_name = "validation_rule_fct_missing_time_tug_berth_etd"
|
||||
return (StatusFlags.YELLOW, validation_name)
|
||||
else:
|
||||
return (StatusFlags.GREEN, None)
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
def validation_rule_fct_missing_time_terminal_berth_eta(self, shipcall, df_times, *args, **kwargs):
|
||||
"""
|
||||
@ -500,27 +504,27 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||
a certain threshold (e.g., 20 hours), a violation occurs
|
||||
|
||||
0001-L:
|
||||
- Checks, if times_terminal.eta_berth is filled in.
|
||||
- Checks, if times_terminal.operations_start is filled in.
|
||||
- Measures the difference between 'now' and 'times_agency.eta_berth'.
|
||||
"""
|
||||
# check, if the header is filled in (agency & terminal)
|
||||
if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value, ParticipantType.TERMINAL.value])]) != 2:
|
||||
return (StatusFlags.GREEN, None)
|
||||
if (len(df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]) != 1) or (len(df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value]) != 1):
|
||||
return self.get_no_violation_default_output() # rule not applicable
|
||||
|
||||
# preparation: obtain the correct times of the participant, define the query time and the key time
|
||||
times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value)
|
||||
times_terminal = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.TERMINAL.value)
|
||||
|
||||
query_time = times_agency.eta_berth
|
||||
key_time = times_terminal.eta_berth
|
||||
key_time = times_terminal.operations_start # eta_berth does not exist in times_terminal! Instead, it is called operations_start
|
||||
threshold = ParticipantwiseTimeDelta.TERMINAL
|
||||
violation_state = self.check_time_delta_violation_query_time_to_now(query_time=query_time, key_time=key_time, threshold=threshold)
|
||||
|
||||
if violation_state:
|
||||
validation_name = inspect.currentframe().f_code.co_name
|
||||
validation_name = "validation_rule_fct_missing_time_terminal_berth_eta"
|
||||
return (StatusFlags.YELLOW, validation_name)
|
||||
else:
|
||||
return (StatusFlags.GREEN, None)
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
def validation_rule_fct_missing_time_terminal_berth_etd(self, shipcall, df_times, *args, **kwargs):
|
||||
"""
|
||||
@ -530,28 +534,30 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||
a certain threshold (e.g., 20 hours), a violation occurs
|
||||
|
||||
0001-M:
|
||||
- Checks, if times_terminal.etd_berth is filled in.
|
||||
- Checks, if times_terminal.operations_end is filled in.
|
||||
- Measures the difference between 'now' and 'times_agency.etd_berth'.
|
||||
"""
|
||||
# check, if the header is filled in (agency & terminal)
|
||||
if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value, ParticipantType.TERMINAL.value])]) != 2:
|
||||
return (StatusFlags.GREEN, None)
|
||||
if len(df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]) != 1:
|
||||
return self.get_no_violation_default_output() # rule not applicable
|
||||
|
||||
if len(df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value]) != 1:
|
||||
return self.get_no_violation_default_output() # rule not applicable
|
||||
|
||||
# preparation: obtain the correct times of the participant, define the query time and the key time
|
||||
times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value)
|
||||
times_terminal = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.TERMINAL.value)
|
||||
|
||||
query_time = times_agency.etd_berth
|
||||
key_time = times_terminal.etd_berth
|
||||
key_time = times_terminal.operations_end # etd_berth does not exist in times_terminal! Instead, it is called operations_end
|
||||
threshold = ParticipantwiseTimeDelta.TERMINAL
|
||||
violation_state = self.check_time_delta_violation_query_time_to_now(query_time=query_time, key_time=key_time, threshold=threshold)
|
||||
|
||||
if violation_state:
|
||||
validation_name = inspect.currentframe().f_code.co_name
|
||||
validation_name = "validation_rule_fct_missing_time_terminal_berth_etd"
|
||||
return (StatusFlags.YELLOW, validation_name)
|
||||
else:
|
||||
return (StatusFlags.GREEN, None)
|
||||
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
def validation_rule_fct_shipcall_incoming_participants_disagree_on_eta(self, shipcall, df_times, *args, **kwargs):
|
||||
"""
|
||||
@ -571,10 +577,10 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||
)
|
||||
|
||||
if violation_state:
|
||||
validation_name = inspect.currentframe().f_code.co_name
|
||||
validation_name = "validation_rule_fct_shipcall_incoming_participants_disagree_on_eta"
|
||||
return (StatusFlags.RED, validation_name)
|
||||
else:
|
||||
return (StatusFlags.GREEN, None)
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
def validation_rule_fct_shipcall_outgoing_participants_disagree_on_etd(self, shipcall, df_times, *args, **kwargs):
|
||||
"""
|
||||
@ -594,10 +600,10 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||
)
|
||||
|
||||
if violation_state:
|
||||
validation_name = inspect.currentframe().f_code.co_name
|
||||
validation_name = "validation_rule_fct_shipcall_outgoing_participants_disagree_on_etd"
|
||||
return (StatusFlags.RED, validation_name)
|
||||
else:
|
||||
return (StatusFlags.GREEN, None)
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
def validation_rule_fct_shipcall_shifting_participants_disagree_on_eta_or_etd(self, shipcall, df_times, *args, **kwargs):
|
||||
"""
|
||||
@ -631,10 +637,10 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||
violation_state = (violation_state_eta) or (violation_state_etd)
|
||||
|
||||
if violation_state:
|
||||
validation_name = inspect.currentframe().f_code.co_name
|
||||
validation_name = "validation_rule_fct_shipcall_shifting_participants_disagree_on_eta_or_etd"
|
||||
return (StatusFlags.RED, validation_name)
|
||||
else:
|
||||
return (StatusFlags.GREEN, None)
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
def validation_rule_fct_eta_time_not_in_operation_window(self, shipcall, df_times, *args, **kwargs):
|
||||
"""
|
||||
@ -646,24 +652,27 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||
start_time & end_time: operations_start & operations_end (times_terminal)
|
||||
"""
|
||||
# check, if the header is filled in (agency & terminal)
|
||||
if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value, ParticipantType.TERMINAL.value])]) != 2:
|
||||
return (StatusFlags.GREEN, None)
|
||||
if len(df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]) != 1:
|
||||
return self.get_no_violation_default_output() # rule not applicable
|
||||
|
||||
if len(df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value]) != 1:
|
||||
return self.get_no_violation_default_output() # rule not applicable
|
||||
|
||||
# get agency & terminal times
|
||||
times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value)
|
||||
times_terminal = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.TERMINAL.value)
|
||||
|
||||
if self.check_is_not_a_time_or_is_none(times_terminal.operations_start) or self.check_is_not_a_time_or_is_none(times_agency.eta_berth):
|
||||
return (StatusFlags.GREEN, None)
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
# check, whether the start of operations is AFTER the estimated arrival time
|
||||
violation_state = times_terminal.operations_start < times_agency.eta_berth
|
||||
|
||||
if violation_state:
|
||||
validation_name = inspect.currentframe().f_code.co_name
|
||||
validation_name = "validation_rule_fct_eta_time_not_in_operation_window"
|
||||
return (StatusFlags.RED, validation_name)
|
||||
else:
|
||||
return (StatusFlags.GREEN, None)
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
def validation_rule_fct_etd_time_not_in_operation_window(self, shipcall, df_times, *args, **kwargs):
|
||||
"""
|
||||
@ -675,24 +684,27 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||
start_time & end_time: operations_start & operations_end (times_terminal)
|
||||
"""
|
||||
# check, if the header is filled in (agency & terminal)
|
||||
if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value, ParticipantType.TERMINAL.value])]) != 2:
|
||||
return (StatusFlags.GREEN, None)
|
||||
if len(df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]) != 1:
|
||||
return self.get_no_violation_default_output() # rule not applicable
|
||||
|
||||
if len(df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value]) != 1:
|
||||
return self.get_no_violation_default_output() # rule not applicable
|
||||
|
||||
# get agency & terminal times
|
||||
times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value)
|
||||
times_terminal = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.TERMINAL.value)
|
||||
|
||||
if self.check_is_not_a_time_or_is_none(times_terminal.operations_end) or self.check_is_not_a_time_or_is_none(times_agency.etd_berth):
|
||||
return (StatusFlags.GREEN, None)
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
# check, whether the end of operations is AFTER the estimated departure time
|
||||
violation_state = times_terminal.operations_end > times_agency.etd_berth
|
||||
|
||||
if violation_state:
|
||||
validation_name = inspect.currentframe().f_code.co_name
|
||||
validation_name = "validation_rule_fct_etd_time_not_in_operation_window"
|
||||
return (StatusFlags.RED, validation_name)
|
||||
else:
|
||||
return (StatusFlags.GREEN, None)
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
def validation_rule_fct_eta_time_not_in_tidal_window(self, shipcall, df_times, *args, **kwargs):
|
||||
"""
|
||||
@ -705,22 +717,22 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||
"""
|
||||
# check, if the header is filled in (agency)
|
||||
if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value])]) != 1:
|
||||
return (StatusFlags.GREEN, None)
|
||||
return self.get_no_violation_default_output()
|
||||
times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value)
|
||||
|
||||
# requirements: tidal window (from & to) is filled in
|
||||
if self.check_is_not_a_time_or_is_none(shipcall.tidal_window_from) or self.check_is_not_a_time_or_is_none(shipcall.tidal_window_to) or self.check_is_not_a_time_or_is_none(times_agency.eta_berth): # 202310310: note: this should check times_agency, shouldn't it?
|
||||
return (StatusFlags.GREEN, None)
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
# check, whether the query time is between start & end time
|
||||
# a violation is observed, when the time is NOT between start & end
|
||||
violation_state = not self.time_logic.time_inbetween(query_time=times_agency.eta_berth, start_time=shipcall.tidal_window_from, end_time=shipcall.tidal_window_to)
|
||||
|
||||
if violation_state:
|
||||
validation_name = inspect.currentframe().f_code.co_name
|
||||
validation_name = "validation_rule_fct_eta_time_not_in_tidal_window"
|
||||
return (StatusFlags.RED, validation_name)
|
||||
else:
|
||||
return (StatusFlags.GREEN, None)
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
def validation_rule_fct_etd_time_not_in_tidal_window(self, shipcall, df_times, *args, **kwargs):
|
||||
"""
|
||||
@ -733,22 +745,22 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||
"""
|
||||
# check, if the header is filled in (agency)
|
||||
if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value])]) != 1:
|
||||
return (StatusFlags.GREEN, None)
|
||||
return self.get_no_violation_default_output()
|
||||
times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value)
|
||||
|
||||
# requirements: tidal window (from & to) is filled in
|
||||
if self.check_is_not_a_time_or_is_none(shipcall.tidal_window_from) or self.check_is_not_a_time_or_is_none(shipcall.tidal_window_to) or self.check_is_not_a_time_or_is_none(times_agency.etd_berth): # 202310310: note: this should check times_agency, shouldn't it?
|
||||
return (StatusFlags.GREEN, None)
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
# check, whether the query time is between start & end time
|
||||
# a violation is observed, when the time is NOT between start & end
|
||||
violation_state = not self.time_logic.time_inbetween(query_time=times_agency.etd_berth, start_time=shipcall.tidal_window_from, end_time=shipcall.tidal_window_to)
|
||||
|
||||
if violation_state:
|
||||
validation_name = inspect.currentframe().f_code.co_name
|
||||
validation_name = "validation_rule_fct_etd_time_not_in_tidal_window"
|
||||
return (StatusFlags.RED, validation_name)
|
||||
else:
|
||||
return (StatusFlags.GREEN, None)
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
def validation_rule_fct_too_many_identical_eta_times(self, shipcall, df_times, rounding = "min", maximum_threshold = 3, all_times_agency=None, *args, **kwargs):
|
||||
"""
|
||||
@ -759,17 +771,17 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||
times_agency = df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]
|
||||
# check, if the header is filled in (agency)
|
||||
if len(times_agency) != 1:
|
||||
return (StatusFlags.GREEN, None)
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
# when ANY of the unique values exceeds the threshold, a violation is observed
|
||||
query = "eta_berth"
|
||||
violation_state = self.check_unique_shipcall_counts(query, times_agency=times_agency, rounding=rounding, maximum_threshold=maximum_threshold, all_times_agency=all_times_agency)
|
||||
|
||||
if violation_state:
|
||||
validation_name = inspect.currentframe().f_code.co_name
|
||||
validation_name = "validation_rule_fct_too_many_identical_eta_times"
|
||||
return (StatusFlags.YELLOW, validation_name)
|
||||
else:
|
||||
return (StatusFlags.GREEN, None)
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
def validation_rule_fct_too_many_identical_etd_times(self, shipcall, df_times, rounding = "min", maximum_threshold = 3, all_times_agency=None, *args, **kwargs):
|
||||
"""
|
||||
@ -780,17 +792,17 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||
times_agency = df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]
|
||||
# check, if the header is filled in (agency)
|
||||
if len(times_agency) != 1:
|
||||
return (StatusFlags.GREEN, None)
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
# when ANY of the unique values exceeds the threshold, a violation is observed
|
||||
query = "etd_berth"
|
||||
violation_state = self.check_unique_shipcall_counts(query, times_agency=times_agency, rounding=rounding, maximum_threshold=maximum_threshold, all_times_agency=all_times_agency)
|
||||
|
||||
if violation_state:
|
||||
validation_name = inspect.currentframe().f_code.co_name
|
||||
validation_name = "validation_rule_fct_too_many_identical_etd_times"
|
||||
return (StatusFlags.YELLOW, validation_name)
|
||||
else:
|
||||
return (StatusFlags.GREEN, None)
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
def validation_rule_fct_agency_and_terminal_berth_id_disagreement(self, shipcall, df_times, *args, **kwargs):
|
||||
"""
|
||||
@ -799,31 +811,34 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||
Description: This validation rule checks, whether agency and terminal agree with their designated berth place by checking berth_id.
|
||||
"""
|
||||
# check, if the header is filled in (agency & terminal)
|
||||
if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value, ParticipantType.TERMINAL.value])]) != 2:
|
||||
return (StatusFlags.GREEN, None)
|
||||
if len(df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]) == 0:
|
||||
return self.get_no_violation_default_output() # rule not applicable
|
||||
|
||||
if len(df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value]) == 0:
|
||||
return self.get_no_violation_default_output() # rule not applicable
|
||||
|
||||
times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value)
|
||||
times_terminal = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.TERMINAL.value)
|
||||
|
||||
# when one of the two values is null, the state is GREEN
|
||||
if (times_agency.berth_id is None) or (times_terminal.berth_id is None):
|
||||
return (StatusFlags.GREEN, None)
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
# when one of the two values is null, the state is GREEN
|
||||
if (pd.isnull(times_agency.berth_id)) or (pd.isnull(times_terminal.berth_id)):
|
||||
return (StatusFlags.GREEN, None)
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
if shipcall.type in [ShipcallType.OUTGOING.value, ShipcallType.SHIFTING.value]:
|
||||
return (StatusFlags.GREEN, None)
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
# only incoming shipcalls matter. The other ones are not relevant for the berth selection
|
||||
violation_state = times_agency.berth_id!=times_terminal.berth_id
|
||||
|
||||
if violation_state:
|
||||
validation_name = inspect.currentframe().f_code.co_name
|
||||
validation_name = "validation_rule_fct_agency_and_terminal_berth_id_disagreement"
|
||||
return (StatusFlags.YELLOW, validation_name)
|
||||
else:
|
||||
return (StatusFlags.GREEN, None)
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
def validation_rule_fct_agency_and_terminal_pier_side_disagreement(self, shipcall, df_times, *args, **kwargs):
|
||||
"""
|
||||
@ -832,30 +847,33 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||
Description: This validation rule checks, whether agency and terminal agree with their designated pier side by checking pier_side.
|
||||
"""
|
||||
# check, if the header is filled in (agency & terminal)
|
||||
if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value, ParticipantType.TERMINAL.value])]) != 2:
|
||||
return (StatusFlags.GREEN, None)
|
||||
if len(df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]) == 0:
|
||||
return self.get_no_violation_default_output() # rule not applicable
|
||||
|
||||
if len(df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value]) == 0:
|
||||
return self.get_no_violation_default_output() # rule not applicable
|
||||
|
||||
times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value)
|
||||
times_terminal = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.TERMINAL.value)
|
||||
|
||||
# when one of the two values is null, the state is GREEN
|
||||
if (times_agency.pier_side is None) or (times_terminal.pier_side is None):
|
||||
return (StatusFlags.GREEN, None)
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
# when one of the two values is null, the state is GREEN
|
||||
if (pd.isnull(times_agency.pier_side)) or (pd.isnull(times_terminal.pier_side)):
|
||||
return (StatusFlags.GREEN, None)
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
# only incoming shipcalls matter. The other ones are not relevant for the pier_side selection
|
||||
if shipcall.type in [ShipcallType.OUTGOING.value, ShipcallType.SHIFTING.value]:
|
||||
return (StatusFlags.GREEN, None)
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
violation_state = times_agency.pier_side!=times_terminal.pier_side
|
||||
violation_state = bool(times_agency.pier_side)!=bool(times_terminal.pier_side)
|
||||
|
||||
if violation_state:
|
||||
validation_name = inspect.currentframe().f_code.co_name
|
||||
validation_name = "validation_rule_fct_agency_and_terminal_pier_side_disagreement"
|
||||
return (StatusFlags.YELLOW, validation_name)
|
||||
else:
|
||||
return (StatusFlags.GREEN, None)
|
||||
return self.get_no_violation_default_output()
|
||||
|
||||
|
||||
|
||||
@ -367,7 +367,7 @@ def test_validation_rule_fct_missing_time_terminal_berth_eta__shipcall_soon_but_
|
||||
df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value, "eta_berth"] = datetime.datetime.now() + datetime.timedelta(minutes=ParticipantwiseTimeDelta.TERMINAL-10)
|
||||
|
||||
# set times agency to be undetermined
|
||||
df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value, "eta_berth"] = None
|
||||
df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value, "operations_start"] = None # previously: eta_berth, which does not exist in times_terminal
|
||||
|
||||
# apply the validation rule
|
||||
(state, msg) = vr.validation_rule_fct_missing_time_terminal_berth_eta(shipcall=shipcall, df_times=df_times)
|
||||
@ -389,7 +389,7 @@ def test_validation_rule_fct_missing_time_terminal_berth_etd__shipcall_soon_but_
|
||||
df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value, "etd_berth"] = datetime.datetime.now() + datetime.timedelta(minutes=ParticipantwiseTimeDelta.TERMINAL-10)
|
||||
|
||||
# set times agency to be undetermined
|
||||
df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value, "etd_berth"] = None
|
||||
df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value, "operations_end"] = None # previously: etd_berth, which does not exist in times_terminal
|
||||
|
||||
# apply the validation rule
|
||||
(state, msg) = vr.validation_rule_fct_missing_time_terminal_berth_etd(shipcall=shipcall, df_times=df_times)
|
||||
@ -820,6 +820,30 @@ def test_validation_rule_fct_agency_and_terminal_pier_side_disagreement__agency_
|
||||
assert code==StatusFlags.YELLOW, f"status should be 'yellow', because agency and terminal do not agree on the selected pier side"
|
||||
return
|
||||
|
||||
def test_validation_rule_fct_agency_and_terminal_pier_side_disagreement__agency_and_terminal_disagree_terminal_is_none(build_sql_proxy_connection):
|
||||
"""0006-B validation_rule_fct_agency_and_terminal_pier_side_disagreement"""
|
||||
vr = build_sql_proxy_connection['vr']
|
||||
shipcall = get_shipcall_simple()
|
||||
df_times = get_df_times(shipcall)
|
||||
df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value, "pier_side"] = True
|
||||
df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value, "pier_side"] = None
|
||||
|
||||
(code, msg) = vr.validation_rule_fct_agency_and_terminal_pier_side_disagreement(shipcall=shipcall, df_times=df_times)
|
||||
assert code==StatusFlags.GREEN, f"status should be 'green', because the terminal's pier_side is not provided"
|
||||
return
|
||||
|
||||
def test_validation_rule_fct_agency_and_terminal_pier_side_disagreement__agency_and_terminal_disagree_terminal_is_nan(build_sql_proxy_connection):
|
||||
"""0006-B validation_rule_fct_agency_and_terminal_pier_side_disagreement"""
|
||||
vr = build_sql_proxy_connection['vr']
|
||||
shipcall = get_shipcall_simple()
|
||||
df_times = get_df_times(shipcall)
|
||||
df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value, "pier_side"] = True
|
||||
df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value, "pier_side"] = float("nan")
|
||||
|
||||
(code, msg) = vr.validation_rule_fct_agency_and_terminal_pier_side_disagreement(shipcall=shipcall, df_times=df_times)
|
||||
assert code==StatusFlags.GREEN, f"status should be 'green', because the terminal's pier_side is not provided"
|
||||
return
|
||||
|
||||
|
||||
|
||||
def test_validation_rule_fct_agency_and_terminal_pier_side_agreement(build_sql_proxy_connection):
|
||||
|
||||
Loading…
Reference in New Issue
Block a user