Fixed time comparison validation func. Now compares min/max value of array.
This commit is contained in:
parent
c24bc981b0
commit
d8fabe0f97
@ -60,13 +60,13 @@ class ValidationRuleBaseFunctions():
|
|||||||
|
|
||||||
def describe_error_message(self, key)->str:
|
def describe_error_message(self, key)->str:
|
||||||
"""
|
"""
|
||||||
Takes any error message, which typically is the validation rule's function name and returns a description of the error.
|
Takes any error message, which typically is the validation rule's function name and returns a description of the error.
|
||||||
In case that the error code is not defined in self.error_message_dict, return the cryptic error code instead
|
In case that the error code is not defined in self.error_message_dict, return the cryptic error code instead
|
||||||
|
|
||||||
returns: string
|
returns: string
|
||||||
"""
|
"""
|
||||||
return self.error_message_dict.get(key,key)
|
return self.error_message_dict.get(key,key)
|
||||||
|
|
||||||
def get_no_violation_default_output(self):
|
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 the default output of a validation function with no validation: a tuple of (GREEN state, None)"""
|
||||||
return (StatusFlags.GREEN, None)
|
return (StatusFlags.GREEN, None)
|
||||||
@ -75,7 +75,7 @@ class ValidationRuleBaseFunctions():
|
|||||||
"""
|
"""
|
||||||
# base function for all validation rules in the group {0001} A-L
|
# base function for all validation rules in the group {0001} A-L
|
||||||
|
|
||||||
measures the time between NOW and query_time.
|
measures the time between NOW and query_time.
|
||||||
When the query_time lays in the past, the delta is negative
|
When the query_time lays in the past, the delta is negative
|
||||||
when the query_time lays in the future, the delta is positive
|
when the query_time lays in the future, the delta is positive
|
||||||
|
|
||||||
@ -93,11 +93,11 @@ class ValidationRuleBaseFunctions():
|
|||||||
# rule is only applicable, when 'key_time' is not defined (neither None, nor pd.NaT)
|
# rule is only applicable, when 'key_time' is not defined (neither None, nor pd.NaT)
|
||||||
if (key_time is not None) and (key_time is not pd.NaT):
|
if (key_time is not None) and (key_time is not pd.NaT):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# when query_time is not valid, the rule cannot be applied
|
# when query_time is not valid, the rule cannot be applied
|
||||||
if self.check_is_not_a_time_or_is_none(query_time):
|
if self.check_is_not_a_time_or_is_none(query_time):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# otherwise, this rule applies and the difference between 'now' and the query time is measured
|
# otherwise, this rule applies and the difference between 'now' and the query time is measured
|
||||||
delta = self.time_logic.time_delta_from_now_to_tgt(tgt_time=query_time, unit="m")
|
delta = self.time_logic.time_delta_from_now_to_tgt(tgt_time=query_time, unit="m")
|
||||||
|
|
||||||
@ -105,7 +105,7 @@ class ValidationRuleBaseFunctions():
|
|||||||
# Violation, if delta <= threshold
|
# Violation, if delta <= threshold
|
||||||
violation_state = (delta<=threshold)
|
violation_state = (delta<=threshold)
|
||||||
return violation_state
|
return violation_state
|
||||||
|
|
||||||
def check_participants_agree_on_estimated_time(self, shipcall, query, df_times, applicable_shipcall_type)->bool:
|
def check_participants_agree_on_estimated_time(self, shipcall, query, df_times, applicable_shipcall_type)->bool:
|
||||||
"""
|
"""
|
||||||
# base function for all validation rules in the group {0002} A-C
|
# base function for all validation rules in the group {0002} A-C
|
||||||
@ -116,11 +116,11 @@ class ValidationRuleBaseFunctions():
|
|||||||
No violations are observed, when
|
No violations are observed, when
|
||||||
- the shipcall belongs to a different type than the rule expects
|
- the shipcall belongs to a different type than the rule expects
|
||||||
- there are no matching times for the provided {query} (e.g., "eta_berth")
|
- there are no matching times for the provided {query} (e.g., "eta_berth")
|
||||||
|
|
||||||
Instead of comparing each individual result, this function counts the amount of unique instances.
|
Instead of comparing each individual result, this function counts the amount of unique instances.
|
||||||
When there is not only one unique value, there are deviating time estimates, and a violation occurs
|
When there is not only one unique value, there are deviating time estimates, and a violation occurs
|
||||||
|
|
||||||
To reduce the potential of false violations, the agreement is rounded (e.g., by minute).
|
To reduce the potential of false violations, the agreement is rounded (e.g., by minute).
|
||||||
|
|
||||||
returns: violation_state (bool)
|
returns: violation_state (bool)
|
||||||
"""
|
"""
|
||||||
@ -133,28 +133,31 @@ class ValidationRuleBaseFunctions():
|
|||||||
if not self.ignore_port_administration_flag:
|
if not self.ignore_port_administration_flag:
|
||||||
participant_types = [ParticipantType.AGENCY.value, ParticipantType.MOORING.value, ParticipantType.PORT_ADMINISTRATION.value, ParticipantType.PILOT.value, ParticipantType.TUG.value]
|
participant_types = [ParticipantType.AGENCY.value, ParticipantType.MOORING.value, ParticipantType.PORT_ADMINISTRATION.value, ParticipantType.PILOT.value, ParticipantType.TUG.value]
|
||||||
else:
|
else:
|
||||||
participant_types = [ParticipantType.AGENCY.value, ParticipantType.MOORING.value, ParticipantType.PORT_ADMINISTRATION.value, ParticipantType.PILOT.value, ParticipantType.TUG.value]
|
participant_types = [ParticipantType.AGENCY.value, ParticipantType.MOORING.value, ParticipantType.PILOT.value, ParticipantType.TUG.value]
|
||||||
df_times = df_times.loc[df_times["participant_type"].isin(participant_types),:]
|
df_times = df_times.loc[df_times["participant_type"].isin(participant_types),:]
|
||||||
|
|
||||||
# exclude missing entries and consider only pd.Timestamp entries (which ignores pd.NaT/null entries)
|
# exclude missing entries and consider only pd.Timestamp entries (which ignores pd.NaT/null entries)
|
||||||
estimated_times = [time_ for time_ in df_times.loc[:,query].tolist() if isinstance(time_, pd.Timestamp)] # df_times = df_times.loc[~df_times[query].isnull(),:]
|
estimated_times = [time_ for time_ in df_times.loc[:,query].tolist() if isinstance(time_, pd.Timestamp)] # df_times = df_times.loc[~df_times[query].isnull(),:]
|
||||||
|
|
||||||
# apply rounding. For example, the agreement of different participants may be required to match minute-wise
|
|
||||||
# '15min' rounds to 'every 15 minutes'. E.g., '2023-09-22 08:18:49' becomes '2023-09-22 08:15:00'
|
|
||||||
estimated_times = [time_.round("15min") for time_ in estimated_times]
|
|
||||||
|
|
||||||
# when there are no entries left (no entries are provided), skip
|
# when there are no entries left (no entries are provided), skip
|
||||||
if len(estimated_times)==0:
|
if len(estimated_times)==0:
|
||||||
violation_state = False
|
violation_state = False
|
||||||
return violation_state
|
return violation_state
|
||||||
|
|
||||||
|
difference = np.max(estimated_times) - np.min(estimated_times)
|
||||||
|
violation_state = difference > pd.Timedelta("15min")
|
||||||
|
|
||||||
|
# apply rounding. For example, the agreement of different participants may be required to match minute-wise
|
||||||
|
# '15min' rounds to 'every 15 minutes'. E.g., '2023-09-22 08:18:49' becomes '2023-09-22 08:15:00'
|
||||||
|
# estimated_times = [time_.round("15min") for time_ in estimated_times]
|
||||||
|
|
||||||
# there should only be one eta_berth, when all participants have provided the same time
|
# there should only be one eta_berth, when all participants have provided the same time
|
||||||
# this equates to the same criteria as checking, whether
|
# this equates to the same criteria as checking, whether
|
||||||
# times_agency.eta_berth==times_mooring.eta_berth==times_portadministration.eta_berth==times_pilot.eta_berth==times_tug.eta_berth
|
# times_agency.eta_berth==times_mooring.eta_berth==times_portadministration.eta_berth==times_pilot.eta_berth==times_tug.eta_berth
|
||||||
n_unique_times = len(np.unique(estimated_times))
|
# n_unique_times = len(np.unique(estimated_times))
|
||||||
violation_state = n_unique_times!=1
|
# violation_state = n_unique_times!=1
|
||||||
return violation_state
|
return violation_state
|
||||||
|
|
||||||
def check_unique_shipcall_counts(self, query:str, times_agency:pd.DataFrame, rounding="min", maximum_threshold=3, all_times_agency=None)->bool:
|
def check_unique_shipcall_counts(self, query:str, times_agency:pd.DataFrame, rounding="min", maximum_threshold=3, all_times_agency=None)->bool:
|
||||||
"""
|
"""
|
||||||
# base function for all validation rules in the group {0005} A&B
|
# base function for all validation rules in the group {0005} A&B
|
||||||
@ -182,13 +185,13 @@ class ValidationRuleBaseFunctions():
|
|||||||
|
|
||||||
class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
||||||
"""
|
"""
|
||||||
an accumulation object that makes sure, that any validation rule is translated to a function with default naming convention and
|
an accumulation object that makes sure, that any validation rule is translated to a function with default naming convention and
|
||||||
return types. Each function should return a ValidationRuleState enumeration object and a description string to which validation rule
|
return types. Each function should return a ValidationRuleState enumeration object and a description string to which validation rule
|
||||||
the result belongs. These are returned as tuples (ValidationRuleState, validation_name)
|
the result belongs. These are returned as tuples (ValidationRuleState, validation_name)
|
||||||
Each rule should have the same input arguments (self, shipcall, df_times, *args, **kwargs)
|
Each rule should have the same input arguments (self, shipcall, df_times, *args, **kwargs)
|
||||||
|
|
||||||
The object makes heavy use of calls from an SQLHandler object, which provides functions for dataframe access and filtering.
|
The object makes heavy use of calls from an SQLHandler object, which provides functions for dataframe access and filtering.
|
||||||
|
|
||||||
each validation_name is generated by calling the function inside a method
|
each validation_name is generated by calling the function inside a method
|
||||||
validation_name = inspect.currentframe().f_code.co_name # validation_name then returns the name of the method from where 'currentframe()' was called.
|
validation_name = inspect.currentframe().f_code.co_name # validation_name then returns the name of the method from where 'currentframe()' was called.
|
||||||
|
|
||||||
@ -199,12 +202,12 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
"""
|
"""
|
||||||
def __init__(self, sql_handler):
|
def __init__(self, sql_handler):
|
||||||
super().__init__(sql_handler)
|
super().__init__(sql_handler)
|
||||||
return
|
return
|
||||||
|
|
||||||
def get_validation_rule_functions(self):
|
def get_validation_rule_functions(self):
|
||||||
"""return a list of all methods in this object, which are all validation rule functions."""
|
"""return a list of all methods in this object, which are all validation rule functions."""
|
||||||
return [self.__getattribute__(mthd_) for mthd_ in dir(self) if ('validation_rule_fct' in mthd_) and (isinstance(self.__getattribute__(mthd_), types.MethodType))]
|
return [self.__getattribute__(mthd_) for mthd_ in dir(self) if ('validation_rule_fct' in mthd_) and (isinstance(self.__getattribute__(mthd_), types.MethodType))]
|
||||||
|
|
||||||
def validation_rule_fct_missing_time_agency_berth_eta(self, shipcall, df_times, *args, **kwargs):
|
def validation_rule_fct_missing_time_agency_berth_eta(self, shipcall, df_times, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Code: #0001-A
|
Code: #0001-A
|
||||||
@ -213,17 +216,17 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
a certain threshold (e.g., 20 hours), a violation occurs
|
a certain threshold (e.g., 20 hours), a violation occurs
|
||||||
|
|
||||||
0001-A:
|
0001-A:
|
||||||
- Checks, if times_agency.eta_berth is filled in.
|
- Checks, if times_agency.eta_berth is filled in.
|
||||||
- Measures the difference between 'now' and 'shipcall.eta'.
|
- Measures the difference between 'now' and 'shipcall.eta'.
|
||||||
"""
|
"""
|
||||||
if not shipcall.type in [ShipcallType.INCOMING.value]:
|
if not shipcall.type in [ShipcallType.INCOMING.value]:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
# check, if the header is filled in
|
# check, if the header is filled in
|
||||||
unassigned = self.sql_handler.check_if_any_participant_of_type_is_unassigned(shipcall, *[ParticipantType.AGENCY])
|
unassigned = self.sql_handler.check_if_any_participant_of_type_is_unassigned(shipcall, *[ParticipantType.AGENCY])
|
||||||
if unassigned:
|
if unassigned:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
# preparation: obtain the correct times of the participant, define the query time and the key time
|
# 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_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value)
|
||||||
query_time = shipcall.eta
|
query_time = shipcall.eta
|
||||||
@ -236,7 +239,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
return (StatusFlags.YELLOW, validation_name)
|
return (StatusFlags.YELLOW, validation_name)
|
||||||
else:
|
else:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
def validation_rule_fct_missing_time_agency_berth_etd(self, shipcall, df_times, *args, **kwargs):
|
def validation_rule_fct_missing_time_agency_berth_etd(self, shipcall, df_times, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Code: #0001-B
|
Code: #0001-B
|
||||||
@ -245,17 +248,17 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
a certain threshold (e.g., 20 hours), a violation occurs
|
a certain threshold (e.g., 20 hours), a violation occurs
|
||||||
|
|
||||||
0001-B:
|
0001-B:
|
||||||
- Checks, if times_agency.etd_berth is filled in.
|
- Checks, if times_agency.etd_berth is filled in.
|
||||||
- Measures the difference between 'now' and 'shipcall.etd'.
|
- Measures the difference between 'now' and 'shipcall.etd'.
|
||||||
"""
|
"""
|
||||||
if not shipcall.type in [ShipcallType.OUTGOING.value, ShipcallType.SHIFTING.value]:
|
if not shipcall.type in [ShipcallType.OUTGOING.value, ShipcallType.SHIFTING.value]:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
# check, if the header is filled in
|
# check, if the header is filled in
|
||||||
unassigned = self.sql_handler.check_if_any_participant_of_type_is_unassigned(shipcall, *[ParticipantType.AGENCY])
|
unassigned = self.sql_handler.check_if_any_participant_of_type_is_unassigned(shipcall, *[ParticipantType.AGENCY])
|
||||||
if unassigned:
|
if unassigned:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
# preparation: obtain the correct times of the participant, define the query time and the key time
|
# 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_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value)
|
||||||
query_time = shipcall.etd
|
query_time = shipcall.etd
|
||||||
@ -268,7 +271,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
return (StatusFlags.YELLOW, validation_name)
|
return (StatusFlags.YELLOW, validation_name)
|
||||||
else:
|
else:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
def validation_rule_fct_missing_time_mooring_berth_eta(self, shipcall, df_times, *args, **kwargs):
|
def validation_rule_fct_missing_time_mooring_berth_eta(self, shipcall, df_times, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Code: #0001-C
|
Code: #0001-C
|
||||||
@ -277,12 +280,12 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
a certain threshold (e.g., 20 hours), a violation occurs
|
a certain threshold (e.g., 20 hours), a violation occurs
|
||||||
|
|
||||||
0001-C:
|
0001-C:
|
||||||
- Checks, if times_mooring.eta_berth is filled in.
|
- Checks, if times_mooring.eta_berth is filled in.
|
||||||
- Measures the difference between 'now' and 'times_agency.eta_berth'.
|
- Measures the difference between 'now' and 'times_agency.eta_berth'.
|
||||||
"""
|
"""
|
||||||
if not shipcall.type in [ShipcallType.INCOMING.value]:
|
if not shipcall.type in [ShipcallType.INCOMING.value]:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
# check, if the header is filled in
|
# check, if the header is filled in
|
||||||
unassigned = self.sql_handler.check_if_any_participant_of_type_is_unassigned(shipcall, *[ParticipantType.AGENCY, ParticipantType.MOORING])
|
unassigned = self.sql_handler.check_if_any_participant_of_type_is_unassigned(shipcall, *[ParticipantType.AGENCY, ParticipantType.MOORING])
|
||||||
if unassigned:
|
if unassigned:
|
||||||
@ -302,7 +305,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
return (StatusFlags.YELLOW, validation_name)
|
return (StatusFlags.YELLOW, validation_name)
|
||||||
else:
|
else:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
def validation_rule_fct_missing_time_mooring_berth_etd(self, shipcall, df_times, *args, **kwargs):
|
def validation_rule_fct_missing_time_mooring_berth_etd(self, shipcall, df_times, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Code: #0001-D
|
Code: #0001-D
|
||||||
@ -311,12 +314,12 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
a certain threshold (e.g., 20 hours), a violation occurs
|
a certain threshold (e.g., 20 hours), a violation occurs
|
||||||
|
|
||||||
0001-D:
|
0001-D:
|
||||||
- Checks, if times_mooring.etd_berth is filled in.
|
- Checks, if times_mooring.etd_berth is filled in.
|
||||||
- Measures the difference between 'now' and 'times_agency.etd_berth'.
|
- Measures the difference between 'now' and 'times_agency.etd_berth'.
|
||||||
"""
|
"""
|
||||||
if not shipcall.type in [ShipcallType.OUTGOING.value, ShipcallType.SHIFTING.value]:
|
if not shipcall.type in [ShipcallType.OUTGOING.value, ShipcallType.SHIFTING.value]:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
# check, if the header is filled in
|
# check, if the header is filled in
|
||||||
unassigned = self.sql_handler.check_if_any_participant_of_type_is_unassigned(shipcall, *[ParticipantType.AGENCY, ParticipantType.MOORING])
|
unassigned = self.sql_handler.check_if_any_participant_of_type_is_unassigned(shipcall, *[ParticipantType.AGENCY, ParticipantType.MOORING])
|
||||||
if unassigned:
|
if unassigned:
|
||||||
@ -336,7 +339,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
return (StatusFlags.YELLOW, validation_name)
|
return (StatusFlags.YELLOW, validation_name)
|
||||||
else:
|
else:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
def validation_rule_fct_missing_time_portadministration_berth_eta(self, shipcall, df_times, *args, **kwargs):
|
def validation_rule_fct_missing_time_portadministration_berth_eta(self, shipcall, df_times, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Code: #0001-F
|
Code: #0001-F
|
||||||
@ -345,20 +348,20 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
a certain threshold (e.g., 20 hours), a violation occurs
|
a certain threshold (e.g., 20 hours), a violation occurs
|
||||||
|
|
||||||
0001-F:
|
0001-F:
|
||||||
- Checks, if times_port_administration.eta_berth is filled in.
|
- Checks, if times_port_administration.eta_berth is filled in.
|
||||||
- Measures the difference between 'now' and 'times_agency.eta_berth'.
|
- Measures the difference between 'now' and 'times_agency.eta_berth'.
|
||||||
"""
|
"""
|
||||||
if self.ignore_port_administration_flag:
|
if self.ignore_port_administration_flag:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
if not shipcall.type in [ShipcallType.INCOMING.value]:
|
if not shipcall.type in [ShipcallType.INCOMING.value]:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
# check, if the header is filled in
|
# check, if the header is filled in
|
||||||
unassigned = self.sql_handler.check_if_any_participant_of_type_is_unassigned(shipcall, *[ParticipantType.AGENCY, ParticipantType.PORT_ADMINISTRATION])
|
unassigned = self.sql_handler.check_if_any_participant_of_type_is_unassigned(shipcall, *[ParticipantType.AGENCY, ParticipantType.PORT_ADMINISTRATION])
|
||||||
if unassigned:
|
if unassigned:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
# preparation: obtain the correct times of the participant, define the query time and the key time
|
# 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_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value)
|
||||||
times_port_administration = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.PORT_ADMINISTRATION.value)
|
times_port_administration = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.PORT_ADMINISTRATION.value)
|
||||||
@ -373,7 +376,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
return (StatusFlags.YELLOW, validation_name)
|
return (StatusFlags.YELLOW, validation_name)
|
||||||
else:
|
else:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
def validation_rule_fct_missing_time_portadministration_berth_etd(self, shipcall, df_times, *args, **kwargs):
|
def validation_rule_fct_missing_time_portadministration_berth_etd(self, shipcall, df_times, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Code: #0001-G
|
Code: #0001-G
|
||||||
@ -382,7 +385,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
a certain threshold (e.g., 20 hours), a violation occurs
|
a certain threshold (e.g., 20 hours), a violation occurs
|
||||||
|
|
||||||
0001-G:
|
0001-G:
|
||||||
- Checks, if times_port_administration.etd_berth is filled in.
|
- Checks, if times_port_administration.etd_berth is filled in.
|
||||||
- Measures the difference between 'now' and 'times_agency.etd_berth'.
|
- Measures the difference between 'now' and 'times_agency.etd_berth'.
|
||||||
"""
|
"""
|
||||||
if self.ignore_port_administration_flag:
|
if self.ignore_port_administration_flag:
|
||||||
@ -390,12 +393,12 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
|
|
||||||
if not shipcall.type in [ShipcallType.OUTGOING.value, ShipcallType.SHIFTING.value]:
|
if not shipcall.type in [ShipcallType.OUTGOING.value, ShipcallType.SHIFTING.value]:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
# check, if the header is filled in
|
# check, if the header is filled in
|
||||||
unassigned = self.sql_handler.check_if_any_participant_of_type_is_unassigned(shipcall, *[ParticipantType.AGENCY, ParticipantType.PORT_ADMINISTRATION])
|
unassigned = self.sql_handler.check_if_any_participant_of_type_is_unassigned(shipcall, *[ParticipantType.AGENCY, ParticipantType.PORT_ADMINISTRATION])
|
||||||
if unassigned:
|
if unassigned:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
# preparation: obtain the correct times of the participant, define the query time and the key time
|
# preparation: obtain the correct times of the participant, define the query time and the key time
|
||||||
# when there are no times, the function returns None
|
# when there are no times, the function returns None
|
||||||
times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value)
|
times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value)
|
||||||
@ -411,7 +414,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
return (StatusFlags.YELLOW, validation_name)
|
return (StatusFlags.YELLOW, validation_name)
|
||||||
else:
|
else:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
def validation_rule_fct_missing_time_pilot_berth_eta(self, shipcall, df_times, *args, **kwargs):
|
def validation_rule_fct_missing_time_pilot_berth_eta(self, shipcall, df_times, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Code: #0001-H
|
Code: #0001-H
|
||||||
@ -420,17 +423,17 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
a certain threshold (e.g., 20 hours), a violation occurs
|
a certain threshold (e.g., 20 hours), a violation occurs
|
||||||
|
|
||||||
0001-H:
|
0001-H:
|
||||||
- Checks, if times_pilot.eta_berth is filled in.
|
- Checks, if times_pilot.eta_berth is filled in.
|
||||||
- Measures the difference between 'now' and 'times_agency.eta_berth'.
|
- Measures the difference between 'now' and 'times_agency.eta_berth'.
|
||||||
"""
|
"""
|
||||||
if not shipcall.type in [ShipcallType.INCOMING.value]:
|
if not shipcall.type in [ShipcallType.INCOMING.value]:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
# check, if the header is filled in
|
# check, if the header is filled in
|
||||||
unassigned = self.sql_handler.check_if_any_participant_of_type_is_unassigned(shipcall, *[ParticipantType.AGENCY, ParticipantType.PILOT])
|
unassigned = self.sql_handler.check_if_any_participant_of_type_is_unassigned(shipcall, *[ParticipantType.AGENCY, ParticipantType.PILOT])
|
||||||
if unassigned:
|
if unassigned:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
# preparation: obtain the correct times of the participant, define the query time and the key time
|
# 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_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value)
|
||||||
times_pilot = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.PILOT.value)
|
times_pilot = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.PILOT.value)
|
||||||
@ -439,13 +442,13 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
key_time = times_pilot.eta_berth if times_pilot is not None else None
|
key_time = times_pilot.eta_berth if times_pilot is not None else None
|
||||||
threshold = ParticipantwiseTimeDelta.PILOT
|
threshold = ParticipantwiseTimeDelta.PILOT
|
||||||
violation_state = self.check_time_delta_violation_query_time_to_now(query_time=query_time, key_time=key_time, threshold=threshold)
|
violation_state = self.check_time_delta_violation_query_time_to_now(query_time=query_time, key_time=key_time, threshold=threshold)
|
||||||
|
|
||||||
if violation_state:
|
if violation_state:
|
||||||
validation_name = "validation_rule_fct_missing_time_pilot_berth_eta"
|
validation_name = "validation_rule_fct_missing_time_pilot_berth_eta"
|
||||||
return (StatusFlags.YELLOW, validation_name)
|
return (StatusFlags.YELLOW, validation_name)
|
||||||
else:
|
else:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
def validation_rule_fct_missing_time_pilot_berth_etd(self, shipcall, df_times, *args, **kwargs):
|
def validation_rule_fct_missing_time_pilot_berth_etd(self, shipcall, df_times, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Code: #0001-I
|
Code: #0001-I
|
||||||
@ -454,17 +457,17 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
a certain threshold (e.g., 20 hours), a violation occurs
|
a certain threshold (e.g., 20 hours), a violation occurs
|
||||||
|
|
||||||
0001-I:
|
0001-I:
|
||||||
- Checks, if times_pilot.etd_berth is filled in.
|
- Checks, if times_pilot.etd_berth is filled in.
|
||||||
- Measures the difference between 'now' and 'times_agency.etd_berth'.
|
- Measures the difference between 'now' and 'times_agency.etd_berth'.
|
||||||
"""
|
"""
|
||||||
if not shipcall.type in [ShipcallType.OUTGOING.value, ShipcallType.SHIFTING.value]:
|
if not shipcall.type in [ShipcallType.OUTGOING.value, ShipcallType.SHIFTING.value]:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
# check, if the header is filled in
|
# check, if the header is filled in
|
||||||
unassigned = self.sql_handler.check_if_any_participant_of_type_is_unassigned(shipcall, *[ParticipantType.AGENCY, ParticipantType.PILOT])
|
unassigned = self.sql_handler.check_if_any_participant_of_type_is_unassigned(shipcall, *[ParticipantType.AGENCY, ParticipantType.PILOT])
|
||||||
if unassigned:
|
if unassigned:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
# preparation: obtain the correct times of the participant, define the query time and the key time
|
# 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_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value)
|
||||||
times_pilot = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.PILOT.value)
|
times_pilot = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.PILOT.value)
|
||||||
@ -473,13 +476,13 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
key_time = times_pilot.etd_berth if times_pilot is not None else None
|
key_time = times_pilot.etd_berth if times_pilot is not None else None
|
||||||
threshold = ParticipantwiseTimeDelta.PILOT
|
threshold = ParticipantwiseTimeDelta.PILOT
|
||||||
violation_state = self.check_time_delta_violation_query_time_to_now(query_time=query_time, key_time=key_time, threshold=threshold)
|
violation_state = self.check_time_delta_violation_query_time_to_now(query_time=query_time, key_time=key_time, threshold=threshold)
|
||||||
|
|
||||||
if violation_state:
|
if violation_state:
|
||||||
validation_name = "validation_rule_fct_missing_time_pilot_berth_etd"
|
validation_name = "validation_rule_fct_missing_time_pilot_berth_etd"
|
||||||
return (StatusFlags.YELLOW, validation_name)
|
return (StatusFlags.YELLOW, validation_name)
|
||||||
else:
|
else:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
def validation_rule_fct_missing_time_tug_berth_eta(self, shipcall, df_times, *args, **kwargs):
|
def validation_rule_fct_missing_time_tug_berth_eta(self, shipcall, df_times, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Code: #0001-J
|
Code: #0001-J
|
||||||
@ -488,17 +491,17 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
a certain threshold (e.g., 20 hours), a violation occurs
|
a certain threshold (e.g., 20 hours), a violation occurs
|
||||||
|
|
||||||
0001-J:
|
0001-J:
|
||||||
- Checks, if times_tug.eta_berth is filled in.
|
- Checks, if times_tug.eta_berth is filled in.
|
||||||
- Measures the difference between 'now' and 'times_agency.eta_berth'.
|
- Measures the difference between 'now' and 'times_agency.eta_berth'.
|
||||||
"""
|
"""
|
||||||
if not shipcall.type in [ShipcallType.INCOMING.value]:
|
if not shipcall.type in [ShipcallType.INCOMING.value]:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
# check, if the header is filled in
|
# check, if the header is filled in
|
||||||
unassigned = self.sql_handler.check_if_any_participant_of_type_is_unassigned(shipcall, *[ParticipantType.AGENCY, ParticipantType.TUG])
|
unassigned = self.sql_handler.check_if_any_participant_of_type_is_unassigned(shipcall, *[ParticipantType.AGENCY, ParticipantType.TUG])
|
||||||
if unassigned:
|
if unassigned:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
# preparation: obtain the correct times of the participant, define the query time and the key time
|
# 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_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value)
|
||||||
times_tug = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.TUG.value)
|
times_tug = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.TUG.value)
|
||||||
@ -507,13 +510,13 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
key_time = times_tug.eta_berth if times_tug is not None else None
|
key_time = times_tug.eta_berth if times_tug is not None else None
|
||||||
threshold = ParticipantwiseTimeDelta.TUG
|
threshold = ParticipantwiseTimeDelta.TUG
|
||||||
violation_state = self.check_time_delta_violation_query_time_to_now(query_time=query_time, key_time=key_time, threshold=threshold)
|
violation_state = self.check_time_delta_violation_query_time_to_now(query_time=query_time, key_time=key_time, threshold=threshold)
|
||||||
|
|
||||||
if violation_state:
|
if violation_state:
|
||||||
validation_name = "validation_rule_fct_missing_time_tug_berth_eta"
|
validation_name = "validation_rule_fct_missing_time_tug_berth_eta"
|
||||||
return (StatusFlags.YELLOW, validation_name)
|
return (StatusFlags.YELLOW, validation_name)
|
||||||
else:
|
else:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
def validation_rule_fct_missing_time_tug_berth_etd(self, shipcall, df_times, *args, **kwargs):
|
def validation_rule_fct_missing_time_tug_berth_etd(self, shipcall, df_times, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Code: #0001-K
|
Code: #0001-K
|
||||||
@ -522,17 +525,17 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
a certain threshold (e.g., 20 hours), a violation occurs
|
a certain threshold (e.g., 20 hours), a violation occurs
|
||||||
|
|
||||||
0001-K:
|
0001-K:
|
||||||
- Checks, if times_tug.etd_berth is filled in.
|
- Checks, if times_tug.etd_berth is filled in.
|
||||||
- Measures the difference between 'now' and 'times_agency.etd_berth'.
|
- Measures the difference between 'now' and 'times_agency.etd_berth'.
|
||||||
"""
|
"""
|
||||||
if not shipcall.type in [ShipcallType.OUTGOING.value, ShipcallType.SHIFTING.value]:
|
if not shipcall.type in [ShipcallType.OUTGOING.value, ShipcallType.SHIFTING.value]:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
# check, if the header is filled in
|
# check, if the header is filled in
|
||||||
unassigned = self.sql_handler.check_if_any_participant_of_type_is_unassigned(shipcall, *[ParticipantType.AGENCY, ParticipantType.TUG])
|
unassigned = self.sql_handler.check_if_any_participant_of_type_is_unassigned(shipcall, *[ParticipantType.AGENCY, ParticipantType.TUG])
|
||||||
if unassigned:
|
if unassigned:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
# preparation: obtain the correct times of the participant, define the query time and the key time
|
# 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_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value)
|
||||||
times_tug = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.TUG.value)
|
times_tug = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.TUG.value)
|
||||||
@ -541,13 +544,13 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
key_time = times_tug.etd_berth if times_tug is not None else None
|
key_time = times_tug.etd_berth if times_tug is not None else None
|
||||||
threshold = ParticipantwiseTimeDelta.TUG
|
threshold = ParticipantwiseTimeDelta.TUG
|
||||||
violation_state = self.check_time_delta_violation_query_time_to_now(query_time=query_time, key_time=key_time, threshold=threshold)
|
violation_state = self.check_time_delta_violation_query_time_to_now(query_time=query_time, key_time=key_time, threshold=threshold)
|
||||||
|
|
||||||
if violation_state:
|
if violation_state:
|
||||||
validation_name = "validation_rule_fct_missing_time_tug_berth_etd"
|
validation_name = "validation_rule_fct_missing_time_tug_berth_etd"
|
||||||
return (StatusFlags.YELLOW, validation_name)
|
return (StatusFlags.YELLOW, validation_name)
|
||||||
else:
|
else:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
def validation_rule_fct_missing_time_terminal_berth_eta(self, shipcall, df_times, *args, **kwargs):
|
def validation_rule_fct_missing_time_terminal_berth_eta(self, shipcall, df_times, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Code: #0001-L
|
Code: #0001-L
|
||||||
@ -556,17 +559,17 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
a certain threshold (e.g., 20 hours), a violation occurs
|
a certain threshold (e.g., 20 hours), a violation occurs
|
||||||
|
|
||||||
0001-L:
|
0001-L:
|
||||||
- Checks, if times_terminal.operations_start is filled in.
|
- Checks, if times_terminal.operations_start is filled in.
|
||||||
- Measures the difference between 'now' and 'times_agency.eta_berth'.
|
- Measures the difference between 'now' and 'times_agency.eta_berth'.
|
||||||
"""
|
"""
|
||||||
if not shipcall.type in [ShipcallType.INCOMING.value]:
|
if not shipcall.type in [ShipcallType.INCOMING.value]:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
# check, if the header is filled in
|
# check, if the header is filled in
|
||||||
unassigned = self.sql_handler.check_if_any_participant_of_type_is_unassigned(shipcall, *[ParticipantType.AGENCY, ParticipantType.TERMINAL])
|
unassigned = self.sql_handler.check_if_any_participant_of_type_is_unassigned(shipcall, *[ParticipantType.AGENCY, ParticipantType.TERMINAL])
|
||||||
if unassigned:
|
if unassigned:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
# preparation: obtain the correct times of the participant, define the query time and the key time
|
# 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_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)
|
times_terminal = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.TERMINAL.value)
|
||||||
@ -575,13 +578,13 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
key_time = times_terminal.operations_start if times_terminal is not None else None # eta_berth does not exist in times_terminal! Instead, it is called operations_start
|
key_time = times_terminal.operations_start if times_terminal is not None else None # eta_berth does not exist in times_terminal! Instead, it is called operations_start
|
||||||
threshold = ParticipantwiseTimeDelta.TERMINAL
|
threshold = ParticipantwiseTimeDelta.TERMINAL
|
||||||
violation_state = self.check_time_delta_violation_query_time_to_now(query_time=query_time, key_time=key_time, threshold=threshold)
|
violation_state = self.check_time_delta_violation_query_time_to_now(query_time=query_time, key_time=key_time, threshold=threshold)
|
||||||
|
|
||||||
if violation_state:
|
if violation_state:
|
||||||
validation_name = "validation_rule_fct_missing_time_terminal_berth_eta"
|
validation_name = "validation_rule_fct_missing_time_terminal_berth_eta"
|
||||||
return (StatusFlags.YELLOW, validation_name)
|
return (StatusFlags.YELLOW, validation_name)
|
||||||
else:
|
else:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
def validation_rule_fct_missing_time_terminal_berth_etd(self, shipcall, df_times, *args, **kwargs):
|
def validation_rule_fct_missing_time_terminal_berth_etd(self, shipcall, df_times, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Code: #0001-M
|
Code: #0001-M
|
||||||
@ -590,17 +593,17 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
a certain threshold (e.g., 20 hours), a violation occurs
|
a certain threshold (e.g., 20 hours), a violation occurs
|
||||||
|
|
||||||
0001-M:
|
0001-M:
|
||||||
- Checks, if times_terminal.operations_end is filled in.
|
- Checks, if times_terminal.operations_end is filled in.
|
||||||
- Measures the difference between 'now' and 'times_agency.etd_berth'.
|
- Measures the difference between 'now' and 'times_agency.etd_berth'.
|
||||||
"""
|
"""
|
||||||
if not shipcall.type in [ShipcallType.OUTGOING.value, ShipcallType.SHIFTING.value]:
|
if not shipcall.type in [ShipcallType.OUTGOING.value, ShipcallType.SHIFTING.value]:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
# check, if the header is filled in
|
# check, if the header is filled in
|
||||||
unassigned = self.sql_handler.check_if_any_participant_of_type_is_unassigned(shipcall, *[ParticipantType.AGENCY, ParticipantType.TERMINAL])
|
unassigned = self.sql_handler.check_if_any_participant_of_type_is_unassigned(shipcall, *[ParticipantType.AGENCY, ParticipantType.TERMINAL])
|
||||||
if unassigned:
|
if unassigned:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
# preparation: obtain the correct times of the participant, define the query time and the key time
|
# 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_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)
|
times_terminal = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.TERMINAL.value)
|
||||||
@ -609,13 +612,13 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
key_time = times_terminal.operations_end if times_terminal is not None else None # etd_berth does not exist in times_terminal! Instead, it is called operations_end
|
key_time = times_terminal.operations_end if times_terminal is not None else None # etd_berth does not exist in times_terminal! Instead, it is called operations_end
|
||||||
threshold = ParticipantwiseTimeDelta.TERMINAL
|
threshold = ParticipantwiseTimeDelta.TERMINAL
|
||||||
violation_state = self.check_time_delta_violation_query_time_to_now(query_time=query_time, key_time=key_time, threshold=threshold)
|
violation_state = self.check_time_delta_violation_query_time_to_now(query_time=query_time, key_time=key_time, threshold=threshold)
|
||||||
|
|
||||||
if violation_state:
|
if violation_state:
|
||||||
validation_name = "validation_rule_fct_missing_time_terminal_berth_etd"
|
validation_name = "validation_rule_fct_missing_time_terminal_berth_etd"
|
||||||
return (StatusFlags.YELLOW, validation_name)
|
return (StatusFlags.YELLOW, validation_name)
|
||||||
else:
|
else:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
def validation_rule_fct_shipcall_incoming_participants_disagree_on_eta(self, shipcall, df_times, *args, **kwargs):
|
def validation_rule_fct_shipcall_incoming_participants_disagree_on_eta(self, shipcall, df_times, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Code: #0002-A
|
Code: #0002-A
|
||||||
@ -624,21 +627,21 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
Filter: only applies to incoming shipcalls
|
Filter: only applies to incoming shipcalls
|
||||||
"""
|
"""
|
||||||
query = "eta_berth"
|
query = "eta_berth"
|
||||||
|
|
||||||
violation_state = self.check_participants_agree_on_estimated_time(
|
|
||||||
shipcall = shipcall,
|
|
||||||
|
|
||||||
query=query,
|
violation_state = self.check_participants_agree_on_estimated_time(
|
||||||
df_times=df_times,
|
shipcall = shipcall,
|
||||||
|
|
||||||
|
query=query,
|
||||||
|
df_times=df_times,
|
||||||
applicable_shipcall_type=ShipcallType.INCOMING
|
applicable_shipcall_type=ShipcallType.INCOMING
|
||||||
)
|
)
|
||||||
|
|
||||||
if violation_state:
|
if violation_state:
|
||||||
validation_name = "validation_rule_fct_shipcall_incoming_participants_disagree_on_eta"
|
validation_name = "validation_rule_fct_shipcall_incoming_participants_disagree_on_eta"
|
||||||
return (StatusFlags.RED, validation_name)
|
return (StatusFlags.RED, validation_name)
|
||||||
else:
|
else:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
def validation_rule_fct_shipcall_outgoing_participants_disagree_on_etd(self, shipcall, df_times, *args, **kwargs):
|
def validation_rule_fct_shipcall_outgoing_participants_disagree_on_etd(self, shipcall, df_times, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Code: #0002-B
|
Code: #0002-B
|
||||||
@ -647,12 +650,12 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
Filter: only applies to outgoing shipcalls
|
Filter: only applies to outgoing shipcalls
|
||||||
"""
|
"""
|
||||||
query = "etd_berth"
|
query = "etd_berth"
|
||||||
|
|
||||||
violation_state = self.check_participants_agree_on_estimated_time(
|
|
||||||
shipcall = shipcall,
|
|
||||||
|
|
||||||
query=query,
|
violation_state = self.check_participants_agree_on_estimated_time(
|
||||||
df_times=df_times,
|
shipcall = shipcall,
|
||||||
|
|
||||||
|
query=query,
|
||||||
|
df_times=df_times,
|
||||||
applicable_shipcall_type=ShipcallType.OUTGOING
|
applicable_shipcall_type=ShipcallType.OUTGOING
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -661,7 +664,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
return (StatusFlags.RED, validation_name)
|
return (StatusFlags.RED, validation_name)
|
||||||
else:
|
else:
|
||||||
return self.get_no_violation_default_output()
|
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):
|
def validation_rule_fct_shipcall_shifting_participants_disagree_on_eta_or_etd(self, shipcall, df_times, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Code: #0002-C
|
Code: #0002-C
|
||||||
@ -670,21 +673,21 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
Filter: only applies to shifting shipcalls
|
Filter: only applies to shifting shipcalls
|
||||||
"""
|
"""
|
||||||
violation_state_eta = self.check_participants_agree_on_estimated_time(
|
violation_state_eta = self.check_participants_agree_on_estimated_time(
|
||||||
shipcall = shipcall,
|
shipcall = shipcall,
|
||||||
|
|
||||||
query="eta_berth",
|
query="eta_berth",
|
||||||
df_times=df_times,
|
df_times=df_times,
|
||||||
applicable_shipcall_type=ShipcallType.SHIFTING
|
applicable_shipcall_type=ShipcallType.SHIFTING
|
||||||
)
|
)
|
||||||
|
|
||||||
violation_state_etd = self.check_participants_agree_on_estimated_time(
|
violation_state_etd = self.check_participants_agree_on_estimated_time(
|
||||||
shipcall = shipcall,
|
shipcall = shipcall,
|
||||||
|
|
||||||
query="etd_berth",
|
query="etd_berth",
|
||||||
df_times=df_times,
|
df_times=df_times,
|
||||||
applicable_shipcall_type=ShipcallType.SHIFTING
|
applicable_shipcall_type=ShipcallType.SHIFTING
|
||||||
)
|
)
|
||||||
|
|
||||||
# apply 'eta_berth' check
|
# apply 'eta_berth' check
|
||||||
# apply 'etd_berth'
|
# apply 'etd_berth'
|
||||||
# violation: if either 'eta_berth' or 'etd_berth' is violated
|
# violation: if either 'eta_berth' or 'etd_berth' is violated
|
||||||
@ -698,7 +701,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
return (StatusFlags.RED, validation_name)
|
return (StatusFlags.RED, validation_name)
|
||||||
else:
|
else:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
def validation_rule_fct_eta_time_not_in_operation_window(self, shipcall, df_times, *args, **kwargs):
|
def validation_rule_fct_eta_time_not_in_operation_window(self, shipcall, df_times, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Code: #0003-A
|
Code: #0003-A
|
||||||
@ -710,14 +713,14 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
"""
|
"""
|
||||||
if not shipcall.type in [ShipcallType.INCOMING.value]:
|
if not shipcall.type in [ShipcallType.INCOMING.value]:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
# check, if the header is filled in (agency & terminal)
|
# check, if the header is filled in (agency & terminal)
|
||||||
if len(df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]) != 1:
|
if len(df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]) != 1:
|
||||||
return self.get_no_violation_default_output() # rule not applicable
|
return self.get_no_violation_default_output() # rule not applicable
|
||||||
|
|
||||||
if len(df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value]) != 1:
|
if len(df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value]) != 1:
|
||||||
return self.get_no_violation_default_output() # rule not applicable
|
return self.get_no_violation_default_output() # rule not applicable
|
||||||
|
|
||||||
# get agency & terminal times
|
# get agency & terminal times
|
||||||
times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value)
|
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)
|
times_terminal = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.TERMINAL.value)
|
||||||
@ -738,7 +741,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
return (StatusFlags.RED, validation_name)
|
return (StatusFlags.RED, validation_name)
|
||||||
else:
|
else:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
def validation_rule_fct_etd_time_not_in_operation_window(self, shipcall, df_times, *args, **kwargs):
|
def validation_rule_fct_etd_time_not_in_operation_window(self, shipcall, df_times, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Code: #0003-B
|
Code: #0003-B
|
||||||
@ -750,14 +753,14 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
"""
|
"""
|
||||||
if not shipcall.type in [ShipcallType.OUTGOING.value, ShipcallType.SHIFTING.value]:
|
if not shipcall.type in [ShipcallType.OUTGOING.value, ShipcallType.SHIFTING.value]:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
# check, if the header is filled in (agency & terminal)
|
# check, if the header is filled in (agency & terminal)
|
||||||
if len(df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]) != 1:
|
if len(df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.value]) != 1:
|
||||||
return self.get_no_violation_default_output() # rule not applicable
|
return self.get_no_violation_default_output() # rule not applicable
|
||||||
|
|
||||||
if len(df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value]) != 1:
|
if len(df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value]) != 1:
|
||||||
return self.get_no_violation_default_output() # rule not applicable
|
return self.get_no_violation_default_output() # rule not applicable
|
||||||
|
|
||||||
# get agency & terminal times
|
# get agency & terminal times
|
||||||
times_agency = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.AGENCY.value)
|
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)
|
times_terminal = self.sql_handler.get_times_for_participant_type(df_times, participant_type=ParticipantType.TERMINAL.value)
|
||||||
@ -778,7 +781,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
return (StatusFlags.RED, validation_name)
|
return (StatusFlags.RED, validation_name)
|
||||||
else:
|
else:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
def validation_rule_fct_eta_time_not_in_tidal_window(self, shipcall, df_times, *args, **kwargs):
|
def validation_rule_fct_eta_time_not_in_tidal_window(self, shipcall, df_times, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Code: #0004-A
|
Code: #0004-A
|
||||||
@ -790,7 +793,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
"""
|
"""
|
||||||
if not shipcall.type in [ShipcallType.INCOMING.value]:
|
if not shipcall.type in [ShipcallType.INCOMING.value]:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
# check, if the header is filled in (agency)
|
# check, if the header is filled in (agency)
|
||||||
if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value])]) != 1:
|
if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value])]) != 1:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
@ -809,7 +812,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
return (StatusFlags.RED, validation_name)
|
return (StatusFlags.RED, validation_name)
|
||||||
else:
|
else:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
def validation_rule_fct_etd_time_not_in_tidal_window(self, shipcall, df_times, *args, **kwargs):
|
def validation_rule_fct_etd_time_not_in_tidal_window(self, shipcall, df_times, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Code: #0004-B
|
Code: #0004-B
|
||||||
@ -821,7 +824,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
"""
|
"""
|
||||||
if not shipcall.type in [ShipcallType.OUTGOING.value, ShipcallType.SHIFTING.value]:
|
if not shipcall.type in [ShipcallType.OUTGOING.value, ShipcallType.SHIFTING.value]:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
# check, if the header is filled in (agency)
|
# check, if the header is filled in (agency)
|
||||||
if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value])]) != 1:
|
if len(df_times.loc[df_times["participant_type"].isin([ParticipantType.AGENCY.value])]) != 1:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
@ -840,7 +843,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
return (StatusFlags.RED, validation_name)
|
return (StatusFlags.RED, validation_name)
|
||||||
else:
|
else:
|
||||||
return self.get_no_violation_default_output()
|
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):
|
def validation_rule_fct_too_many_identical_eta_times(self, shipcall, df_times, rounding = "min", maximum_threshold = 3, all_times_agency=None, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Code: #0005-A
|
Code: #0005-A
|
||||||
@ -861,7 +864,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
return (StatusFlags.YELLOW, validation_name)
|
return (StatusFlags.YELLOW, validation_name)
|
||||||
else:
|
else:
|
||||||
return self.get_no_violation_default_output()
|
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):
|
def validation_rule_fct_too_many_identical_etd_times(self, shipcall, df_times, rounding = "min", maximum_threshold = 3, all_times_agency=None, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Code: #0005-B
|
Code: #0005-B
|
||||||
@ -882,7 +885,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
return (StatusFlags.YELLOW, validation_name)
|
return (StatusFlags.YELLOW, validation_name)
|
||||||
else:
|
else:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
def validation_rule_fct_agency_and_terminal_berth_id_disagreement(self, shipcall, df_times, *args, **kwargs):
|
def validation_rule_fct_agency_and_terminal_berth_id_disagreement(self, shipcall, df_times, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Code: #0006-A
|
Code: #0006-A
|
||||||
@ -895,18 +898,18 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
|
|
||||||
if len(df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value]) == 0:
|
if len(df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value]) == 0:
|
||||||
return self.get_no_violation_default_output() # rule not applicable
|
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_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)
|
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
|
# 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):
|
if (times_agency.berth_id is None) or (times_terminal.berth_id is None):
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
# when one of the two values is null, the state is GREEN
|
# 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)):
|
if (pd.isnull(times_agency.berth_id)) or (pd.isnull(times_terminal.berth_id)):
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
if shipcall.type in [ShipcallType.OUTGOING.value, ShipcallType.SHIFTING.value]:
|
if shipcall.type in [ShipcallType.OUTGOING.value, ShipcallType.SHIFTING.value]:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
@ -918,7 +921,7 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
return (StatusFlags.YELLOW, validation_name)
|
return (StatusFlags.YELLOW, validation_name)
|
||||||
else:
|
else:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
def validation_rule_fct_agency_and_terminal_pier_side_disagreement(self, shipcall, df_times, *args, **kwargs):
|
def validation_rule_fct_agency_and_terminal_pier_side_disagreement(self, shipcall, df_times, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Code: #0006-B
|
Code: #0006-B
|
||||||
@ -931,18 +934,18 @@ class ValidationRuleFunctions(ValidationRuleBaseFunctions):
|
|||||||
|
|
||||||
if len(df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value]) == 0:
|
if len(df_times.loc[df_times["participant_type"]==ParticipantType.TERMINAL.value]) == 0:
|
||||||
return self.get_no_violation_default_output() # rule not applicable
|
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_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)
|
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
|
# when one of the two values is null, the state is GREEN
|
||||||
if (shipcall.pier_side is None) or (times_terminal.pier_side is None):
|
if (shipcall.pier_side is None) or (times_terminal.pier_side is None):
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
# when one of the two values is null, the state is GREEN
|
# when one of the two values is null, the state is GREEN
|
||||||
if (pd.isnull(shipcall.pier_side)) or (pd.isnull(times_terminal.pier_side)):
|
if (pd.isnull(shipcall.pier_side)) or (pd.isnull(times_terminal.pier_side)):
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|
||||||
# only incoming shipcalls matter. The other ones are not relevant for the pier_side selection
|
# 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]:
|
if shipcall.type in [ShipcallType.OUTGOING.value, ShipcallType.SHIFTING.value]:
|
||||||
return self.get_no_violation_default_output()
|
return self.get_no_violation_default_output()
|
||||||
|
|||||||
Reference in New Issue
Block a user