Compare commits

...

42 Commits

Author SHA1 Message Date
7110810c8c fix shipcall query to include times eta/etd 2024-02-05 10:20:31 +01:00
4c73145857 Merge branch 'master' into release/1.1.1 2024-01-16 07:20:06 +01:00
a9f1de2637 Changes for (blue) release version 2024-01-15 18:13:04 +01:00
e659203364 Version bump 1.1.4 -> 1.1.5 2024-01-12 11:33:35 +01:00
3727bf266d Merge branch 'bugfix/tug_times_trouble' into release/1.1.1 2024-01-12 11:27:57 +01:00
3e17983f2d Removed spinner from IMO integerUpDown 2024-01-12 11:26:12 +01:00
126d74ec48 Changed validation rule 002 A-C so that the agency time is set as reference time allowing 15 minute deviation 2024-01-12 11:22:20 +01:00
b44620b0ad Version bump 1.1.3 -> 1.1.4 2024-01-05 10:55:48 +01:00
df5f88d3cf Fixed time comparison validation func. Now compares min/max value of array. 2024-01-05 10:51:13 +01:00
e5f5694d52 fixed filtering by berth id, also including outgoing and shifting moves 2024-01-05 08:09:54 +01:00
96b0d7aecf set appsettings correctly 2023-12-29 15:01:35 +01:00
6952fadbcb Version bump 1.1.2 -> 1.1.3 2023-12-29 14:51:38 +01:00
0f313e2c21 Merge branch 'bugfix/ui_fixes_1.1.2' into release/1.1.1 2023-12-29 14:49:58 +01:00
8d1415e33d Version bump 1.1.1 -> 1.1.2 2023-12-28 11:59:58 +01:00
5f01188541 merged fixes from correction branch 2023-12-28 11:55:03 +01:00
e7936b679c remaining stuff 2023-12-26 17:46:58 +01:00
f76bcf3cbb Changed strings labels and colors for test version 2023-12-26 17:43:54 +01:00
956ba2832a Merge branch 'bugfix/empty_times' 2023-12-01 10:02:40 +02:00
scopesorting
377ec85ce9 more concise evaluation messages for 0001. Adding newlines (works on Windows) when multiple evaluation messages are shown. Properly adding the ShipcallType filters for each rule (whether incoming, outgoing or shifting). Added a regular expression to abbreviate an evaluation message when 512 characters are exceeded. 2023-12-01 09:29:20 +02:00
scopesorting
a0785d012c changing the ParticipantType to an IntFlag, so multiple roles are possible. Adapting every validation rule (0001, 0003, 0004, 0005), which may be affected by this change. Changing the filter for a participant type to properly include the change. Changing the pier_side rule (0006B), which uses the shipcall and times_terminal. New shipcalls should now be evaluated properly, unless no participant is assigned at all. If the ladder case can occur, the validation rules 0001N+0001O will be added (held back for now). 2023-12-01 09:29:01 +02:00
scopesorting
efff2fdf82 removing verbosity in validation rule functions, and returning 'None', when a selected times dataframe is empty. In case of empty results, the function now properly computes the delta towards a query time and returns YELLOW, when a violation is observed. This should finally fix the bugs for 0001 A-M 2023-12-01 09:28:36 +02:00
scopesorting
d6a6cc00ff updating validation rules 0001 A-M. Instead of filtering by times_df (which may not exist), the rules make use of the shipcall_participant_map. When one of the participants in a rule is not assigned, no violation is observed. When there are multiple entries of a participant (due to an input bug), the function still verifies properly. When critical time is observed, and there is not yet an entry for the respective key time, there will be a 'yellow' state. 2023-12-01 09:28:11 +02:00
scopesorting
ecdf66bff2 updating check_time_delta_violation_query_time_to_now: no longer ignoring events of the past (delta<=0) 2023-11-28 16:48:20 +01:00
scopesorting
287224eeb4 ensuring that len(df_times) always works. Preventing 'None' from occuring 2023-11-28 14:49:40 +01:00
scopesorting
210252df22 minot adjustments & refactoring 2023-11-28 14:26:38 +01:00
scopesorting
c064556668 fixing the 'KeyError' when using an empty times dataframe. Returning 'green' 2023-11-28 14:17:07 +01:00
adaef94854 added trace output and fixed a bug when saving shipcalls without times 2023-11-28 11:23:46 +01:00
c3f8759c70 fixed error in publish xml 2023-11-26 18:08:38 +01:00
131528021d set everything to blue, meaning prod version 1.0.0 2023-11-26 17:37:31 +01:00
5b2d6db5d3 set everything to red, meaning test version 1.0.0 2023-11-26 17:05:32 +01:00
902cb9d90d Updated to Version 0.9.6 for public version 2023-11-15 14:59:23 +01:00
e77c9264b9 Merge branch 'release/pub_0.9.4' 2023-10-27 09:05:08 +02:00
79f6f26293 setup client to produce a producion release 2023-10-27 08:45:10 +02:00
1f355203f0 Version bump to 0.9.4.0 2023-10-27 07:41:06 +02:00
2917fb5b2a Merge branch 'release/0.6' 2023-09-21 10:51:37 +02:00
c104fcf9c0 updated test profile 2023-09-21 10:48:16 +02:00
ccf4ed0565 Merge branch 'release/0.5.0' 2023-09-04 07:55:29 +02:00
d0c0a62cfe Merge branch 'release/0.4.0' 2023-09-04 07:55:06 +02:00
ed0a337929 Increased version for release 2023-08-24 08:15:46 +02:00
4dd07da09b Release 0.4.0. 2023-08-21 19:27:14 +02:00
699552e23c Version 0.3.0 Client release 2023-08-18 16:44:06 +02:00
d09ca5bb8a updated version info 2023-08-16 10:27:13 +02:00
20 changed files with 229 additions and 197 deletions

View File

@ -3582,7 +3582,7 @@ namespace BreCalClient.misc.Client
{ {
Proxy = null; Proxy = null;
UserAgent = WebUtility.UrlEncode("OpenAPI-Generator/1.0.0/csharp"); UserAgent = WebUtility.UrlEncode("OpenAPI-Generator/1.0.0/csharp");
BasePath = "https://brecaldevel.bsmd-emswe.eu"; BasePath = "https://brecal.bsmd-emswe.eu";
DefaultHeaders = new ConcurrentDictionary<string, string>(); DefaultHeaders = new ConcurrentDictionary<string, string>();
ApiKey = new ConcurrentDictionary<string, string>(); ApiKey = new ConcurrentDictionary<string, string>();
ApiKeyPrefix = new ConcurrentDictionary<string, string>(); ApiKeyPrefix = new ConcurrentDictionary<string, string>();
@ -3590,7 +3590,7 @@ namespace BreCalClient.misc.Client
{ {
{ {
new Dictionary<string, object> { new Dictionary<string, object> {
{"url", "https://brecaldevel.bsmd-emswe.eu"}, {"url", "https://brecal.bsmd-emswe.eu"},
{"description", "Test server hosted on vcup"}, {"description", "Test server hosted on vcup"},
} }
} }
@ -3609,7 +3609,7 @@ namespace BreCalClient.misc.Client
IDictionary<string, string> defaultHeaders, IDictionary<string, string> defaultHeaders,
IDictionary<string, string> apiKey, IDictionary<string, string> apiKey,
IDictionary<string, string> apiKeyPrefix, IDictionary<string, string> apiKeyPrefix,
string basePath = "https://brecaldevel.bsmd-emswe.eu") : this() string basePath = "https://brecal.bsmd-emswe.eu") : this()
{ {
if (string.IsNullOrWhiteSpace(basePath)) if (string.IsNullOrWhiteSpace(basePath))
throw new ArgumentException("The provided basePath is invalid.", "basePath"); throw new ArgumentException("The provided basePath is invalid.", "basePath");

View File

@ -13,7 +13,7 @@ info:
url: "https://www.bsmd.de/license" url: "https://www.bsmd.de/license"
servers: servers:
- url: "https://brecaltest.bsmd-emswe.eu/" - url: "https://brecal.bsmd-emswe.eu/"
description: "Test server hosted on vcup" description: "Test server hosted on vcup"
paths: paths:

View File

@ -1 +1 @@
1.1.1.0 1.1.5.0

View File

@ -11,16 +11,16 @@
<applicationSettings> <applicationSettings>
<BreCalClient.Properties.Settings> <BreCalClient.Properties.Settings>
<setting name="BG_COLOR" serializeAs="String"> <setting name="BG_COLOR" serializeAs="String">
<value>#1D751F</value> <value>#203864</value>
</setting> </setting>
<setting name="APP_TITLE" serializeAs="String"> <setting name="APP_TITLE" serializeAs="String">
<value>!!Bremen calling Testversion!!</value> <value>Bremen calling</value>
</setting> </setting>
<setting name="LOGO_IMAGE_URL" serializeAs="String"> <setting name="LOGO_IMAGE_URL" serializeAs="String">
<value>https://www.textbausteine.net/</value> <value>https://www.textbausteine.net/</value>
</setting> </setting>
<setting name="API_URL" serializeAs="String"> <setting name="API_URL" serializeAs="String">
<value>https://brecaldevel.bsmd-emswe.eu</value> <value>https://brecal.bsmd-emswe.eu</value>
</setting> </setting>
</BreCalClient.Properties.Settings> </BreCalClient.Properties.Settings>
</applicationSettings> </applicationSettings>

View File

@ -8,12 +8,12 @@
<SignAssembly>True</SignAssembly> <SignAssembly>True</SignAssembly>
<StartupObject>BreCalClient.App</StartupObject> <StartupObject>BreCalClient.App</StartupObject>
<AssemblyOriginatorKeyFile>..\..\misc\brecal.snk</AssemblyOriginatorKeyFile> <AssemblyOriginatorKeyFile>..\..\misc\brecal.snk</AssemblyOriginatorKeyFile>
<AssemblyVersion>1.1.1.0</AssemblyVersion> <AssemblyVersion>1.1.5.0</AssemblyVersion>
<FileVersion>1.1.1.0</FileVersion> <FileVersion>1.1.5.0</FileVersion>
<Title>Bremen calling client</Title> <Title>Bremen calling client</Title>
<Description>A Windows WPF client for the Bremen calling API.</Description> <Description>A Windows WPF client for the Bremen calling API.</Description>
<ApplicationIcon>containership.ico</ApplicationIcon> <ApplicationIcon>containership.ico</ApplicationIcon>
<AssemblyName>BreCalDevelClient</AssemblyName> <AssemblyName>BreCalClient</AssemblyName>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -32,7 +32,7 @@
<Label Content="{x:Static p:Resources.textShip}" Grid.Column="0" Grid.Row="0" HorizontalContentAlignment="Right"/> <Label Content="{x:Static p:Resources.textShip}" Grid.Column="0" Grid.Row="0" HorizontalContentAlignment="Right"/>
<ComboBox x:Name="comboBoxShip" Margin="2" Grid.Column="1" Grid.Row="0" SelectionChanged="comboBoxShip_SelectionChanged" SelectedValuePath="Ship.Id" IsEditable="True" IsTextSearchEnabled="True" IsTextSearchCaseSensitive="False" /> <ComboBox x:Name="comboBoxShip" Margin="2" Grid.Column="1" Grid.Row="0" SelectionChanged="comboBoxShip_SelectionChanged" SelectedValuePath="Ship.Id" IsEditable="True" IsTextSearchEnabled="True" IsTextSearchCaseSensitive="False" />
<Label Content="IMO" Grid.Column="0" Grid.Row="1" HorizontalContentAlignment="Right"/> <Label Content="IMO" Grid.Column="0" Grid.Row="1" HorizontalContentAlignment="Right"/>
<xctk:IntegerUpDown x:Name="integerUpDownIMO" IsReadOnly="True" Margin="2" Grid.Column="1" Grid.Row="1" /> <xctk:IntegerUpDown x:Name="integerUpDownIMO" IsReadOnly="True" Margin="2" Grid.Column="1" Grid.Row="1" ShowButtonSpinner="False"/>
<Label Content="{x:Static p:Resources.textCallsign}" Grid.Column="0" Grid.Row="2" HorizontalContentAlignment="Right"/> <Label Content="{x:Static p:Resources.textCallsign}" Grid.Column="0" Grid.Row="2" HorizontalContentAlignment="Right"/>
<TextBox x:Name="textBoxCallsign" IsReadOnly="True" Grid.Column="1" Grid.Row="2" Margin="2" /> <TextBox x:Name="textBoxCallsign" IsReadOnly="True" Grid.Column="1" Grid.Row="2" Margin="2" />
<Label Content="{x:Static p:Resources.textLength}" Grid.Column="0" Grid.Row="3" HorizontalContentAlignment="Right"/> <Label Content="{x:Static p:Resources.textLength}" Grid.Column="0" Grid.Row="3" HorizontalContentAlignment="Right"/>

View File

@ -516,7 +516,8 @@ namespace BreCalClient
if(sfm.Berths.Count > 0 ) if(sfm.Berths.Count > 0 )
{ {
this._visibleControlModels.RemoveAll(x => !sfm.Berths.Contains((x.Shipcall?.ArrivalBerthId) ?? -1)); this._visibleControlModels.RemoveAll(x => (!sfm.Berths.Contains((x.Shipcall?.ArrivalBerthId) ?? -1) && (x.Shipcall?.Type == (int) Extensions.TypeEnum.Incoming)) ||
(!sfm.Berths.Contains((x.Shipcall?.DepartureBerthId) ?? -1) && (x.Shipcall?.Type != (int) Extensions.TypeEnum.Incoming)));
} }
if(sfm.Agencies.Count > 0 ) if(sfm.Agencies.Count > 0 )

View File

@ -5,7 +5,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
<Project> <Project>
<PropertyGroup> <PropertyGroup>
<ApplicationRevision>0</ApplicationRevision> <ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.1.1.0</ApplicationVersion> <ApplicationVersion>1.1.3.0</ApplicationVersion>
<BootstrapperEnabled>True</BootstrapperEnabled> <BootstrapperEnabled>True</BootstrapperEnabled>
<Configuration>Debug</Configuration> <Configuration>Debug</Configuration>
<CreateDesktopShortcut>True</CreateDesktopShortcut> <CreateDesktopShortcut>True</CreateDesktopShortcut>

View File

@ -5,7 +5,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
<Project> <Project>
<PropertyGroup> <PropertyGroup>
<ApplicationRevision>0</ApplicationRevision> <ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>6.0</ApplicationVersion> <ApplicationVersion>1.1.5.*</ApplicationVersion>
<BootstrapperEnabled>False</BootstrapperEnabled> <BootstrapperEnabled>False</BootstrapperEnabled>
<Configuration>Release</Configuration> <Configuration>Release</Configuration>
<CreateWebPageOnPublish>True</CreateWebPageOnPublish> <CreateWebPageOnPublish>True</CreateWebPageOnPublish>

View File

@ -5,7 +5,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
<Project> <Project>
<PropertyGroup> <PropertyGroup>
<ApplicationRevision>0</ApplicationRevision> <ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.1.0.*</ApplicationVersion> <ApplicationVersion>1.1.5.*</ApplicationVersion>
<BootstrapperEnabled>True</BootstrapperEnabled> <BootstrapperEnabled>True</BootstrapperEnabled>
<Configuration>Debug</Configuration> <Configuration>Debug</Configuration>
<CreateDesktopShortcut>True</CreateDesktopShortcut> <CreateDesktopShortcut>True</CreateDesktopShortcut>

View File

@ -9,38 +9,38 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
namespace BreCalClient.Properties { namespace BreCalClient.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.7.0.0")] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.5.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default { public static Settings Default {
get { get {
return defaultInstance; return defaultInstance;
} }
} }
[global::System.Configuration.ApplicationScopedSettingAttribute()] [global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("#1D751F")] [global::System.Configuration.DefaultSettingValueAttribute("#203864")]
public string BG_COLOR { public string BG_COLOR {
get { get {
return ((string)(this["BG_COLOR"])); return ((string)(this["BG_COLOR"]));
} }
} }
[global::System.Configuration.ApplicationScopedSettingAttribute()] [global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("!!Bremen calling Testversion!!")] [global::System.Configuration.DefaultSettingValueAttribute("Bremen calling")]
public string APP_TITLE { public string APP_TITLE {
get { get {
return ((string)(this["APP_TITLE"])); return ((string)(this["APP_TITLE"]));
} }
} }
[global::System.Configuration.ApplicationScopedSettingAttribute()] [global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("https://www.textbausteine.net/")] [global::System.Configuration.DefaultSettingValueAttribute("https://www.textbausteine.net/")]
@ -49,7 +49,7 @@ namespace BreCalClient.Properties {
return ((string)(this["LOGO_IMAGE_URL"])); return ((string)(this["LOGO_IMAGE_URL"]));
} }
} }
[global::System.Configuration.UserScopedSettingAttribute()] [global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("")] [global::System.Configuration.DefaultSettingValueAttribute("")]
@ -61,16 +61,16 @@ namespace BreCalClient.Properties {
this["FilterCriteria"] = value; this["FilterCriteria"] = value;
} }
} }
[global::System.Configuration.ApplicationScopedSettingAttribute()] [global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("https://brecaldevel.bsmd-emswe.eu")] [global::System.Configuration.DefaultSettingValueAttribute("https://brecal.bsmd-emswe.eu")]
public string API_URL { public string API_URL {
get { get {
return ((string)(this["API_URL"])); return ((string)(this["API_URL"]));
} }
} }
[global::System.Configuration.UserScopedSettingAttribute()] [global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("800")] [global::System.Configuration.DefaultSettingValueAttribute("800")]
@ -82,7 +82,7 @@ namespace BreCalClient.Properties {
this["Width"] = value; this["Width"] = value;
} }
} }
[global::System.Configuration.UserScopedSettingAttribute()] [global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("450")] [global::System.Configuration.DefaultSettingValueAttribute("450")]
@ -94,7 +94,7 @@ namespace BreCalClient.Properties {
this["Height"] = value; this["Height"] = value;
} }
} }
[global::System.Configuration.UserScopedSettingAttribute()] [global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("0")] [global::System.Configuration.DefaultSettingValueAttribute("0")]
@ -106,7 +106,7 @@ namespace BreCalClient.Properties {
this["Left"] = value; this["Left"] = value;
} }
} }
[global::System.Configuration.UserScopedSettingAttribute()] [global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("0")] [global::System.Configuration.DefaultSettingValueAttribute("0")]
@ -118,7 +118,7 @@ namespace BreCalClient.Properties {
this["Top"] = value; this["Top"] = value;
} }
} }
[global::System.Configuration.UserScopedSettingAttribute()] [global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("0")] [global::System.Configuration.DefaultSettingValueAttribute("0")]
@ -130,7 +130,7 @@ namespace BreCalClient.Properties {
this["W1Left"] = value; this["W1Left"] = value;
} }
} }
[global::System.Configuration.UserScopedSettingAttribute()] [global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("0")] [global::System.Configuration.DefaultSettingValueAttribute("0")]

View File

@ -3,10 +3,10 @@
<Profiles /> <Profiles />
<Settings> <Settings>
<Setting Name="BG_COLOR" Type="System.String" Scope="Application"> <Setting Name="BG_COLOR" Type="System.String" Scope="Application">
<Value Profile="(Default)">#1D751F</Value> <Value Profile="(Default)">#203864</Value>
</Setting> </Setting>
<Setting Name="APP_TITLE" Type="System.String" Scope="Application"> <Setting Name="APP_TITLE" Type="System.String" Scope="Application">
<Value Profile="(Default)">!!Bremen calling Testversion!!</Value> <Value Profile="(Default)">Bremen calling</Value>
</Setting> </Setting>
<Setting Name="LOGO_IMAGE_URL" Type="System.String" Scope="Application"> <Setting Name="LOGO_IMAGE_URL" Type="System.String" Scope="Application">
<Value Profile="(Default)">https://www.textbausteine.net/</Value> <Value Profile="(Default)">https://www.textbausteine.net/</Value>
@ -15,7 +15,7 @@
<Value Profile="(Default)" /> <Value Profile="(Default)" />
</Setting> </Setting>
<Setting Name="API_URL" Type="System.String" Scope="Application"> <Setting Name="API_URL" Type="System.String" Scope="Application">
<Value Profile="(Default)">https://brecaldevel.bsmd-emswe.eu</Value> <Value Profile="(Default)">https://brecal.bsmd-emswe.eu</Value>
</Setting> </Setting>
<Setting Name="Width" Type="System.Double" Scope="User"> <Setting Name="Width" Type="System.Double" Scope="User">
<Value Profile="(Default)">800</Value> <Value Profile="(Default)">800</Value>

View File

@ -1,12 +1,12 @@
<UserControl x:Class="BreCalClient.ShipcallControl" <UserControl x:Class="BreCalClient.ShipcallControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:p = "clr-namespace:BreCalClient.Resources" xmlns:p = "clr-namespace:BreCalClient.Resources"
xmlns:sets="clr-namespace:BreCalClient.Properties" xmlns:sets="clr-namespace:BreCalClient.Properties"
xmlns:db="clr-namespace:BreCalClient;assembly=BreCalDevelClient" xmlns:db="clr-namespace:BreCalClient;assembly=BreCalClient"
mc:Ignorable="d" mc:Ignorable="d"
d:DesignHeight="120" d:DesignWidth="800" Loaded="UserControl_Loaded"> d:DesignHeight="120" d:DesignWidth="800" Loaded="UserControl_Loaded">
<Border BorderBrush="LightGray" Margin="1" BorderThickness="1"> <Border BorderBrush="LightGray" Margin="1" BorderThickness="1">
<Grid> <Grid>
@ -45,7 +45,7 @@
<ColumnDefinition Width="32" /> <ColumnDefinition Width="32" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Image Margin="2" Grid.Column="0" PreviewMouseUp="Image_PreviewMouseUp" x:Name="imageShipcallType" /> <Image Margin="2" Grid.Column="0" PreviewMouseUp="Image_PreviewMouseUp" x:Name="imageShipcallType" />
<Label Grid.Column="1" FontSize="12" x:Name="labelShipName" Foreground="White" Background="{Binding Source={x:Static sets:Settings.Default}, Path=BG_COLOR}" VerticalAlignment="Stretch" <Label Grid.Column="1" FontSize="12" x:Name="labelShipName" Foreground="White" Background="{Binding Source={x:Static sets:Settings.Default}, Path=BG_COLOR}" VerticalAlignment="Stretch"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" PreviewMouseUp="Image_PreviewMouseUp"> HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" PreviewMouseUp="Image_PreviewMouseUp">
<TextBlock Name="textBlockShipName" /> <TextBlock Name="textBlockShipName" />
</Label> </Label>
@ -83,23 +83,23 @@
<Viewbox Grid.Row="6" Grid.Column="1" HorizontalAlignment="Left"> <Viewbox Grid.Row="6" Grid.Column="1" HorizontalAlignment="Left">
<TextBlock x:Name="textBlockBerth" Padding="0" FontWeight="DemiBold" /> <TextBlock x:Name="textBlockBerth" Padding="0" FontWeight="DemiBold" />
</Viewbox> </Viewbox>
</Grid> </Grid>
<Label Grid.Row="0" Grid.Column="1" Grid.RowSpan="1" FontSize="12" Content="- / -" Foreground="White" Background="{Binding Source={x:Static sets:Settings.Default}, Path=BG_COLOR}" VerticalAlignment="Stretch" <Label Grid.Row="0" Grid.Column="1" Grid.RowSpan="1" FontSize="12" Content="- / -" Foreground="White" Background="{Binding Source={x:Static sets:Settings.Default}, Path=BG_COLOR}" VerticalAlignment="Stretch"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Name="labelAgent" PreviewMouseUp="labelAgent_PreviewMouseUp"/> HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Name="labelAgent" PreviewMouseUp="labelAgent_PreviewMouseUp"/>
<Label Grid.Row="0" Grid.Column="2" Grid.RowSpan="1" FontSize="12" Content="- / -" Foreground="White" Background="{Binding Source={x:Static sets:Settings.Default}, Path=BG_COLOR}" VerticalAlignment="Stretch" <Label Grid.Row="0" Grid.Column="2" Grid.RowSpan="1" FontSize="12" Content="- / -" Foreground="White" Background="{Binding Source={x:Static sets:Settings.Default}, Path=BG_COLOR}" VerticalAlignment="Stretch"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Name="labelMooring" PreviewMouseUp="labelMooring_PreviewMouseUp"/> HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Name="labelMooring" PreviewMouseUp="labelMooring_PreviewMouseUp"/>
<Label Grid.Row="0" Grid.Column="3" Grid.RowSpan="1" FontSize="12" Content="- / -" Foreground="White" Background="{Binding Source={x:Static sets:Settings.Default}, Path=BG_COLOR}" VerticalAlignment="Stretch" <Label Grid.Row="0" Grid.Column="3" Grid.RowSpan="1" FontSize="12" Content="- / -" Foreground="White" Background="{Binding Source={x:Static sets:Settings.Default}, Path=BG_COLOR}" VerticalAlignment="Stretch"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Name="labelPortAuthority" PreviewMouseUp="labelPortAuthority_PreviewMouseUp" /> HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Name="labelPortAuthority" PreviewMouseUp="labelPortAuthority_PreviewMouseUp" />
<Label Grid.Row="0" Grid.Column="4" Grid.RowSpan="1" FontSize="12" Content="- / -" Foreground="White" Background="{Binding Source={x:Static sets:Settings.Default}, Path=BG_COLOR}" VerticalAlignment="Stretch" <Label Grid.Row="0" Grid.Column="4" Grid.RowSpan="1" FontSize="12" Content="- / -" Foreground="White" Background="{Binding Source={x:Static sets:Settings.Default}, Path=BG_COLOR}" VerticalAlignment="Stretch"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Name="labelPilot" PreviewMouseUp="labelPilot_PreviewMouseUp"/> HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Name="labelPilot" PreviewMouseUp="labelPilot_PreviewMouseUp"/>
<Label Grid.Row="0" Grid.Column="5" Grid.RowSpan="1" FontSize="12" Content="- / -" Foreground="White" Background="{Binding Source={x:Static sets:Settings.Default}, Path=BG_COLOR}" VerticalAlignment="Stretch" <Label Grid.Row="0" Grid.Column="5" Grid.RowSpan="1" FontSize="12" Content="- / -" Foreground="White" Background="{Binding Source={x:Static sets:Settings.Default}, Path=BG_COLOR}" VerticalAlignment="Stretch"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Name="labelTug" PreviewMouseUp="labelTug_PreviewMouseUp"/> HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Name="labelTug" PreviewMouseUp="labelTug_PreviewMouseUp"/>
<Label Grid.Row="0" Grid.Column="6" Grid.RowSpan="1" FontSize="12" Content="- / -" Foreground="White" Background="{Binding Source={x:Static sets:Settings.Default}, Path=BG_COLOR}" VerticalAlignment="Stretch" <Label Grid.Row="0" Grid.Column="6" Grid.RowSpan="1" FontSize="12" Content="- / -" Foreground="White" Background="{Binding Source={x:Static sets:Settings.Default}, Path=BG_COLOR}" VerticalAlignment="Stretch"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Name="labelTerminal" PreviewMouseUp="labelTerminal_PreviewMouseUp" /> HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Name="labelTerminal" PreviewMouseUp="labelTerminal_PreviewMouseUp" />
<!-- AGENCY --> <!-- AGENCY -->
<Border Grid.Row="2" Grid.Column="1" BorderThickness="1, 0, 0, 0" BorderBrush="{Binding Source={x:Static sets:Settings.Default}, Path=BG_COLOR}" Padding="3,0,0,0"> <Border Grid.Row="2" Grid.Column="1" BorderThickness="1, 0, 0, 0" BorderBrush="{Binding Source={x:Static sets:Settings.Default}, Path=BG_COLOR}" Padding="3,0,0,0">
<Grid Grid.Row="2" Grid.Column="1"> <Grid Grid.Row="2" Grid.Column="1">
@ -113,7 +113,7 @@
<RowDefinition Height="14" /> <RowDefinition Height="14" />
<RowDefinition Height=".5*" /> <RowDefinition Height=".5*" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content = "ETA" x:Name="labelETAETDAgent" Padding="0" VerticalContentAlignment="Center" /> <Label Grid.Row="0" Grid.Column="0" Content = "ETA" x:Name="labelETAETDAgent" Padding="0" VerticalContentAlignment="Center" />
<Label Grid.Row="1" Grid.Column="0" Content="{x:Static p:Resources.textRemarks}" Padding="0" VerticalContentAlignment="Center" FontSize="9"/> <Label Grid.Row="1" Grid.Column="0" Content="{x:Static p:Resources.textRemarks}" Padding="0" VerticalContentAlignment="Center" FontSize="9"/>
<Label Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" Content="{x:Static p:Resources.textBerth}" Padding="0" VerticalContentAlignment="Center" FontSize="9"/> <Label Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" Content="{x:Static p:Resources.textBerth}" Padding="0" VerticalContentAlignment="Center" FontSize="9"/>

View File

@ -1,6 +1,6 @@
// Copyright (c) 2023 schick Informatik // Copyright (c) 2023 schick Informatik
// Description: Show general shipcall info // Description: Show general shipcall info
// //
using BreCalClient.misc.Model; using BreCalClient.misc.Model;
using log4net; using log4net;
@ -53,7 +53,7 @@ namespace BreCalClient
/// <summary> /// <summary>
/// this is our datasource /// this is our datasource
/// </summary> /// </summary>
public ShipcallControlModel? ShipcallControlModel { get; set; } public ShipcallControlModel? ShipcallControlModel { get; set; }
#endregion #endregion
@ -131,7 +131,7 @@ namespace BreCalClient
{ {
this.labelTerminal.FontWeight = FontWeights.Bold; this.labelTerminal.FontWeight = FontWeights.Bold;
this.labelTerminal.Foreground = Brushes.LightYellow; this.labelTerminal.Foreground = Brushes.LightYellow;
} }
else else
{ {
this.labelTerminal.FontWeight = FontWeights.Normal; this.labelTerminal.FontWeight = FontWeights.Normal;
@ -210,13 +210,13 @@ namespace BreCalClient
switch (this.ShipcallControlModel?.Shipcall?.Type) switch (this.ShipcallControlModel?.Shipcall?.Type)
{ {
case 1: // incoming case 1: // incoming
this.imageShipcallType.Source = new BitmapImage(new Uri("pack://application:,,,/BreCalDevelClient;component/Resources/arrow_down_red.png")); this.imageShipcallType.Source = new BitmapImage(new Uri("pack://application:,,,/BreCalClient;component/Resources/arrow_down_red.png"));
break; break;
case 2: // outgoing case 2: // outgoing
this.imageShipcallType.Source = new BitmapImage(new Uri("pack://application:,,,/BreCalDevelClient;component/Resources/arrow_up_blue.png")); this.imageShipcallType.Source = new BitmapImage(new Uri("pack://application:,,,/BreCalClient;component/Resources/arrow_up_blue.png"));
break; break;
case 3: // shifting case 3: // shifting
this.imageShipcallType.Source = new BitmapImage(new Uri("pack://application:,,,/BreCalDevelClient;component/Resources/arrow_right_green.png")); this.imageShipcallType.Source = new BitmapImage(new Uri("pack://application:,,,/BreCalClient;component/Resources/arrow_right_green.png"));
break; break;
default: default:
break; break;
@ -225,13 +225,13 @@ namespace BreCalClient
switch(this.ShipcallControlModel?.LightMode) switch(this.ShipcallControlModel?.LightMode)
{ {
case ShipcallControlModel.TrafficLightMode.GREEN: case ShipcallControlModel.TrafficLightMode.GREEN:
this.imageEvaluation.Source = new BitmapImage(new Uri("pack://application:,,,/BreCalDevelClient;component/Resources/check.png")); this.imageEvaluation.Source = new BitmapImage(new Uri("pack://application:,,,/BreCalClient;component/Resources/check.png"));
break; break;
case ShipcallControlModel.TrafficLightMode.YELLOW: case ShipcallControlModel.TrafficLightMode.YELLOW:
this.imageEvaluation.Source = new BitmapImage(new Uri("pack://application:,,,/BreCalDevelClient;component/Resources/sign_warning.png")); this.imageEvaluation.Source = new BitmapImage(new Uri("pack://application:,,,/BreCalClient;component/Resources/sign_warning.png"));
break; break;
case ShipcallControlModel.TrafficLightMode.RED: case ShipcallControlModel.TrafficLightMode.RED:
this.imageEvaluation.Source = new BitmapImage(new Uri("pack://application:,,,/BreCalDevelClient;component/Resources/delete2.png")); this.imageEvaluation.Source = new BitmapImage(new Uri("pack://application:,,,/BreCalClient;component/Resources/delete2.png"));
break; break;
default: default:
break; break;
@ -274,7 +274,7 @@ namespace BreCalClient
this.textBlockBerth.Text = this.ShipcallControlModel?.Berth; this.textBlockBerth.Text = this.ShipcallControlModel?.Berth;
this.textBlockCallsign.Text = this.ShipcallControlModel?.Ship?.Callsign; this.textBlockCallsign.Text = this.ShipcallControlModel?.Ship?.Callsign;
if (this.ShipcallControlModel?.Shipcall?.Type == 1) if (this.ShipcallControlModel?.Shipcall?.Type == 1)
{ {
this.textBlockETA.Text = this.ShipcallControlModel?.Shipcall?.Eta?.ToString("dd.MM. HH:mm"); this.textBlockETA.Text = this.ShipcallControlModel?.Shipcall?.Eta?.ToString("dd.MM. HH:mm");
} }
@ -287,7 +287,7 @@ namespace BreCalClient
this.textBlockIMO.Text = this.ShipcallControlModel?.Ship?.Imo.ToString(); this.textBlockIMO.Text = this.ShipcallControlModel?.Ship?.Imo.ToString();
this.textBlockLengthWidth.Text = $"{this.ShipcallControlModel?.Ship?.Length} / {this.ShipcallControlModel?.Ship?.Width}"; this.textBlockLengthWidth.Text = $"{this.ShipcallControlModel?.Ship?.Length} / {this.ShipcallControlModel?.Ship?.Width}";
// rename labels if this is not an incoming // rename labels if this is not an incoming
// must be here because there may not be a times record for each participant (yet) // must be here because there may not be a times record for each participant (yet)
if (this.ShipcallControlModel?.Shipcall?.Type != 1) if (this.ShipcallControlModel?.Shipcall?.Type != 1)
@ -301,7 +301,7 @@ namespace BreCalClient
} }
if (this.ShipcallControlModel != null) if (this.ShipcallControlModel != null)
{ {
Times? agencyTimes = this.ShipcallControlModel?.GetTimesForParticipantType(Extensions.ParticipantType.AGENCY); Times? agencyTimes = this.ShipcallControlModel?.GetTimesForParticipantType(Extensions.ParticipantType.AGENCY);
if (agencyTimes != null) if (agencyTimes != null)
@ -314,7 +314,7 @@ namespace BreCalClient
{ {
this.labelAgencyETAETDValue.Content = agencyTimes.EtdBerth.HasValue ? agencyTimes.EtdBerth.Value.ToString("dd.MM.yyyy HH:mm") : "- / -"; this.labelAgencyETAETDValue.Content = agencyTimes.EtdBerth.HasValue ? agencyTimes.EtdBerth.Value.ToString("dd.MM.yyyy HH:mm") : "- / -";
} }
} }
else else
{ {
// no agency times set (yet) // no agency times set (yet)
@ -408,7 +408,7 @@ namespace BreCalClient
this.textBlockTerminalRemarks.Text = ""; this.textBlockTerminalRemarks.Text = "";
this.textBlockTerminalBerthRemarks.Text = ""; this.textBlockTerminalBerthRemarks.Text = "";
} }
} }
this.DataContext = this.ShipcallControlModel; this.DataContext = this.ShipcallControlModel;
} }
@ -432,7 +432,7 @@ namespace BreCalClient
{ {
if(App.Participant.IsTypeFlagSet(Extensions.ParticipantType.BSMD)) if(App.Participant.IsTypeFlagSet(Extensions.ParticipantType.BSMD))
this.EditRequested?.Invoke(this); this.EditRequested?.Invoke(this);
} }
private void Image_PreviewMouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e) private void Image_PreviewMouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{ {
@ -440,10 +440,10 @@ namespace BreCalClient
} }
private void labelAgent_PreviewMouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e) private void labelAgent_PreviewMouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{ {
Times? times = this.ShipcallControlModel?.GetTimesForParticipantType(Extensions.ParticipantType.AGENCY); Times? times = this.ShipcallControlModel?.GetTimesForParticipantType(Extensions.ParticipantType.AGENCY);
this.EditAgencyRequested?.Invoke(this, times); this.EditAgencyRequested?.Invoke(this, times);
} }
private void labelMooring_PreviewMouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e) private void labelMooring_PreviewMouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{ {
@ -453,7 +453,7 @@ namespace BreCalClient
private void labelPortAuthority_PreviewMouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e) private void labelPortAuthority_PreviewMouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{ {
Times? times = this.ShipcallControlModel?.GetTimesForParticipantType(Extensions.ParticipantType.PORT_ADMINISTRATION); Times? times = this.ShipcallControlModel?.GetTimesForParticipantType(Extensions.ParticipantType.PORT_ADMINISTRATION);
this.EditTimesRequested?.Invoke(this, times, Extensions.ParticipantType.PORT_ADMINISTRATION); this.EditTimesRequested?.Invoke(this, times, Extensions.ParticipantType.PORT_ADMINISTRATION);
} }

View File

@ -61,7 +61,7 @@ def create_app(test_config=None):
app.register_blueprint(user.bp) app.register_blueprint(user.bp)
logging.basicConfig(filename='brecaldevel.log', level=logging.DEBUG, format='%(asctime)s | %(name)s | %(levelname)s | %(message)s') logging.basicConfig(filename='brecal.log', level=logging.DEBUG, format='%(asctime)s | %(name)s | %(levelname)s | %(message)s')
local_db.initPool(os.path.dirname(app.instance_path)) local_db.initPool(os.path.dirname(app.instance_path))
logging.info('App started') logging.info('App started')
@ -73,8 +73,8 @@ def create_app(test_config=None):
return app return app
__all__ = [ __all__ = [
"get_project_root", "get_project_root",
"ensure_path", "ensure_path",
"execute_test_with_pytest", "execute_test_with_pytest",
"execute_coverage_test", "execute_coverage_test",
"difference_to_then", "difference_to_then",

View File

@ -19,11 +19,20 @@ def GetShipcalls(options):
pooledConnection = local_db.getPoolConnection() pooledConnection = local_db.getPoolConnection()
commands = pydapper.using(pooledConnection) commands = pydapper.using(pooledConnection)
query = ("SELECT id, ship_id, type, eta, voyage, etd, arrival_berth_id, departure_berth_id, tug_required, pilot_required, " query = ("SELECT s.id as id, ship_id, type, eta, voyage, etd, arrival_berth_id, departure_berth_id, tug_required, pilot_required, " +
"flags, pier_side, bunkering, replenishing_terminal, replenishing_lock, draft, tidal_window_from, tidal_window_to, rain_sensitive_cargo, recommended_tugs, " "flags, s.pier_side, bunkering, replenishing_terminal, replenishing_lock, draft, tidal_window_from, " +
"anchored, moored_lock, canceled, evaluation, evaluation_message, created, modified FROM shipcall WHERE ((type = 1 OR type = 3) AND eta >= DATE(NOW() - INTERVAL %d DAY)" "tidal_window_to, rain_sensitive_cargo, recommended_tugs, anchored, moored_lock, canceled, evaluation, " +
"OR (type = 2 AND etd >= DATE(NOW() - INTERVAL %d DAY))) " "evaluation_message, s.created as created, s.modified as modified " +
"ORDER BY eta") % (options["past_days"], options["past_days"]) "FROM shipcall s " +
"LEFT JOIN times t ON t.shipcall_id = s.id AND t.participant_type = 8 " +
"WHERE " +
"(type = 1 AND " +
"((t.id IS NOT NULL AND t.eta_berth >= DATE(NOW() - INTERVAL %d DAY)) OR " +
"(eta >= DATE(NOW() - INTERVAL %d DAY)))) OR " +
"((type = 2 OR type = 3) AND " +
"((t.id IS NOT NULL AND t.etd_berth >= DATE(NOW() - INTERVAL %d DAY)) OR " +
"(etd >= DATE(NOW() - INTERVAL %d DAY)))) " +
"ORDER BY eta") % (options["past_days"], options["past_days"], options["past_days"], options["past_days"])
data = commands.query(query, model=model.Shipcall) data = commands.query(query, model=model.Shipcall)
for shipcall in data: for shipcall in data:

View File

@ -11,7 +11,7 @@ def initPool(instancePath):
try: try:
global config_path global config_path
if(config_path == None): if(config_path == None):
config_path = os.path.join(instancePath,'../../../secure/connection_data_devel.json'); config_path = os.path.join(instancePath,'../../../secure/connection_data_prod.json');
print (config_path) print (config_path)

View File

@ -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,50 @@ 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]
agency_times = df_times.loc[df_times["participant_type"]==ParticipantType.AGENCY.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),:]
agency_time = [time_ for time_ in agency_times.loc[:,query].tolist() if isinstance(time_, pd.Timestamp)]
if not len(agency_time):
violation_state = False
return violation_state
# 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
# this (current) solution compares times to the reference (agency) time and checks if the difference is greater than 15 minutes
violation_state = ((np.max(estimated_times) - agency_time[0]) > pd.Timedelta("15min")) or ((agency_time[0] - np.min(estimated_times)) > pd.Timedelta("15min"))
# this solution to the rule compares all times to each other. When there is a total difference of more than 15 minutes, a violation occurs
# Consequently, it treats all times as equally important
# difference = np.max(estimated_times) - np.min(estimated_times)
# violation_state = difference > pd.Timedelta("15min")
# this solution clamps the times to 15 minute intervals and compares these values. When there is a single time difference, a violation occurs
# the drawback is that in some cases if there is a minimal difference say of 1 minute (:22 and :23 minutes after the hour) the violation is
# triggered even though the times are very close to each other
# 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 +204,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 +221,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 +235,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 +258,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 +267,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 +290,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 +299,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 +324,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 +333,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 +358,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 +367,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 +395,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 +404,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 +412,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 +433,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 +442,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 +461,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 +476,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 +495,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 +510,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 +529,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 +544,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 +563,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 +578,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 +597,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 +612,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 +631,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 +646,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 +669,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 +683,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 +692,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 +720,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 +732,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 +760,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 +772,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 +800,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 +812,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 +831,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 +843,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 +862,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 +883,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 +904,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 +917,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 +940,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 +953,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()

View File

@ -2,7 +2,7 @@ import os
import sys import sys
import logging import logging
sys.path.insert(0, '/var/www/brecal_devel/src/server') sys.path.insert(0, '/var/www/brecal/src/server')
sys.path.insert(0, '/var/www/venv/lib/python3.10/site-packages/') sys.path.insert(0, '/var/www/venv/lib/python3.10/site-packages/')
import schedule import schedule

View File

@ -2,7 +2,7 @@ from setuptools import find_packages, setup
setup( setup(
name='BreCal', name='BreCal',
version='1.1.1', version='1.1.5',
packages=find_packages(), packages=find_packages(),
include_package_data=True, include_package_data=True,
zip_safe=False, zip_safe=False,