Merge branch 'feature/1.6_database_changes' into develop

This commit is contained in:
Daniel Schick 2024-09-12 11:48:56 +02:00
commit cc17e6c33a
20 changed files with 525 additions and 44 deletions

View File

@ -2,7 +2,7 @@ openapi: 3.0.0
x-stoplight: x-stoplight:
id: mwv4y8vcnopwr id: mwv4y8vcnopwr
info: info:
version: 1.4.1 version: 1.6.0
title: Bremen calling API title: Bremen calling API
description: 'Administer DEBRE ship calls, times and notifications' description: 'Administer DEBRE ship calls, times and notifications'
termsOfService: 'https://www.bsmd.de/' termsOfService: 'https://www.bsmd.de/'

View File

@ -0,0 +1,57 @@
CREATE TABLE `port` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(128) NOT NULL COMMENT 'Name of port',
`locode` char(5) DEFAULT NULL COMMENT 'UNECE locode',
`created` datetime DEFAULT CURRENT_TIMESTAMP,
`modified` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
`deleted` bit(1) DEFAULT b'0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='Port as reference for shipcalls and berths';
-- Add default port to table
INSERT INTO port (id, name, locode) VALUES (1, 'Bremen', 'DEBRE');
-- Adding new ref column to berth
ALTER TABLE `bremen_calling_devel`.`berth`
ADD COLUMN `port_id` INT UNSIGNED DEFAULT NULL AFTER `authority_id`;
ALTER TABLE `bremen_calling_devel`.`berth` ALTER INDEX `FK_AUTHORITY_PART_idx` INVISIBLE;
-- adding a foreign key berth.port_id -> port.id
ALTER TABLE `bremen_calling_devel`.`berth`
ADD INDEX `FK_PORT_PART_idx` (`port_id` ASC) VISIBLE;
ALTER TABLE `bremen_calling_devel`.`berth`
ADD CONSTRAINT `FK_PORT`
FOREIGN KEY (`port_id`)
REFERENCES `bremen_calling_devel`.`port` (`id`)
ON DELETE RESTRICT
ON UPDATE RESTRICT;
-- adding new ref column to shipcall incl. foreign key
ALTER TABLE `bremen_calling_devel`.`shipcall`
ADD COLUMN `port_id` INT UNSIGNED NOT NULL DEFAULT 1 COMMENT 'Selected port for this shipcall' AFTER `evaluation_notifications_sent`,
CHANGE COLUMN `time_ref_point` `time_ref_point` INT NULL DEFAULT '0' COMMENT 'Index of a location which is the reference point for all time value entries, e.g. berth or Geeste' AFTER `port_id`,
ADD INDEX `FK_SHIPCALL_PORT_idx` (`port_id` ASC) VISIBLE;
;
ALTER TABLE `bremen_calling_devel`.`shipcall`
ADD CONSTRAINT `FK_SHIPCALL_PORT`
FOREIGN KEY (`port_id`)
REFERENCES `bremen_calling_devel`.`port` (`id`)
ON DELETE RESTRICT
ON UPDATE RESTRICT;
CREATE TABLE `participant_port_map` (
`id` int NOT NULL AUTO_INCREMENT,
`participant_id` int unsigned NOT NULL COMMENT 'Ref to participant',
`port_id` int unsigned NOT NULL COMMENT 'Ref to port',
`created` datetime DEFAULT CURRENT_TIMESTAMP,
`modified` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `FK_PP_PARTICIPANT` (`participant_id`),
KEY `FK_PP_PORT` (`port_id`),
CONSTRAINT `FK_PP_PARTICIPANT` FOREIGN KEY (`participant_id`) REFERENCES `participant` (`id`),
CONSTRAINT `FK_PP_PORT` FOREIGN KEY (`port_id`) REFERENCES `port` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='Mapping table that assigns participants to a port';
-- all existing berths shall default to "bremen"
UPDATE berth SET port_id = 1;

View File

@ -1 +1 @@
1.4.1.0 1.6.0.0

View File

@ -8,8 +8,8 @@
<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.5.0.4</AssemblyVersion> <AssemblyVersion>1.6.0.0</AssemblyVersion>
<FileVersion>1.5.0.4</FileVersion> <FileVersion>1.6.0.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>

View File

@ -5,7 +5,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
<Project> <Project>
<PropertyGroup> <PropertyGroup>
<ApplicationRevision>1</ApplicationRevision> <ApplicationRevision>1</ApplicationRevision>
<ApplicationVersion>1.4.1.0</ApplicationVersion> <ApplicationVersion>1.6.0.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>1.5.0.4</ApplicationVersion> <ApplicationVersion>1.6.0.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 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:RoleEditor" xmlns:local="clr-namespace:RoleEditor"
mc:Ignorable="d" mc:Ignorable="d"
Title="Edit berth" Height="188" Width="450" Loaded="Window_Loaded"> Title="Edit berth" Height="216" Width="450" Loaded="Window_Loaded">
<Grid x:Name="berthGrid"> <Grid x:Name="berthGrid">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width=".3*" /> <ColumnDefinition Width=".3*" />
@ -16,6 +16,7 @@
<RowDefinition Height="28" /> <RowDefinition Height="28" />
<RowDefinition Height="28" /> <RowDefinition Height="28" />
<RowDefinition Height="28" /> <RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="*" /> <RowDefinition Height="*" />
<RowDefinition Height="28" /> <RowDefinition Height="28" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
@ -45,7 +46,9 @@
</Grid> </Grid>
<Label Content="Uses lock" HorizontalAlignment="Right" Grid.Row="3" /> <Label Content="Uses lock" HorizontalAlignment="Right" Grid.Row="3" />
<CheckBox x:Name="checkBoxLock" Grid.Row="3" Grid.Column="1" VerticalAlignment="Center" Margin="2" IsChecked="{Binding Path=Lock, Mode=OneWay}"/> <CheckBox x:Name="checkBoxLock" Grid.Row="3" Grid.Column="1" VerticalAlignment="Center" Margin="2" IsChecked="{Binding Path=Lock, Mode=OneWay}"/>
<StackPanel Grid.Column="1" Grid.Row="5" Orientation="Horizontal" FlowDirection="RightToLeft"> <Label Content="Port" HorizontalAlignment="Right" Grid.Row="4" />
<ComboBox Name="comboBoxPorts" Margin="2" Grid.Column="1" Grid.Row="4" SelectedItem="{Binding Port, Mode=OneWay}" />
<StackPanel Grid.Column="1" Grid.Row="6" Orientation="Horizontal" FlowDirection="RightToLeft">
<Button x:Name="buttonCancel" Width="80" Content="Cancel" Margin="2" Click="buttonCancel_Click" /> <Button x:Name="buttonCancel" Width="80" Content="Cancel" Margin="2" Click="buttonCancel_Click" />
<Button x:Name="buttonOK" Width="80" Content="OK" Margin="2" Click="buttonOK_Click"/> <Button x:Name="buttonOK" Width="80" Content="OK" Margin="2" Click="buttonOK_Click"/>
</StackPanel> </StackPanel>

View File

@ -20,6 +20,8 @@ namespace RoleEditor
public List<Participant> Authorities { get; } = new List<Participant>(); public List<Participant> Authorities { get; } = new List<Participant>();
public List<Port> Ports { get; } = new List<Port>();
private void buttonCancel_Click(object sender, RoutedEventArgs e) private void buttonCancel_Click(object sender, RoutedEventArgs e)
{ {
this.DialogResult = false; this.DialogResult = false;
@ -52,6 +54,7 @@ namespace RoleEditor
this.DataContext = this.Berth; this.DataContext = this.Berth;
this.comboBoxParticipants.ItemsSource = this.Owners; this.comboBoxParticipants.ItemsSource = this.Owners;
this.comboBoxAuthorities.ItemsSource = this.Authorities; this.comboBoxAuthorities.ItemsSource = this.Authorities;
this.comboBoxPorts.ItemsSource = this.Ports;
} }
private void buttonResetParticipant_Click(object sender, RoutedEventArgs e) private void buttonResetParticipant_Click(object sender, RoutedEventArgs e)

View File

@ -6,7 +6,7 @@
xmlns:local="clr-namespace:RoleEditor" xmlns:local="clr-namespace:RoleEditor"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit" xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
mc:Ignorable="d" mc:Ignorable="d"
Title="Bremen calling admin editor" Height="670" Width="800" Icon="Resources/lock_preferences.ico" Loaded="Window_Loaded"> Title="Bremen calling admin editor" Height="670" Width="1024" Icon="Resources/lock_preferences.ico" Loaded="Window_Loaded">
<Grid> <Grid>
<TabControl> <TabControl>
<TabItem Header="Participant, users and roles"> <TabItem Header="Participant, users and roles">
@ -16,8 +16,9 @@
<RowDefinition Height=".5*" /> <RowDefinition Height=".5*" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width=".5*" /> <ColumnDefinition Width=".4*" />
<ColumnDefinition Width=".5*" /> <ColumnDefinition Width=".3*" />
<ColumnDefinition Width=".3*" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<GroupBox Header="Participant" Margin="2"> <GroupBox Header="Participant" Margin="2">
<Grid> <Grid>
@ -82,6 +83,69 @@
</Button> </Button>
</Grid> </Grid>
</GroupBox> </GroupBox>
<GroupBox Header="Port Assignment" Margin="2" Grid.Row="0" Grid.Column="1">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="60" />
</Grid.ColumnDefinitions>
<ListBox x:Name="listBoxPortAssignment" Margin="2" Grid.Row="0" Grid.Column="0" Grid.RowSpan="3" />
<Button x:Name="buttonAddPortAssignment" Margin="2" Grid.Row="0" Grid.Column="1" Click="buttonAddPortAssignment_Click">
<Image Source="./Resources/arrow_left_green.png"/>
</Button>
<Button x:Name="buttonRemovePortAssignment" Margin="2" Grid.Row="1" Grid.Column="1" Click="buttonRemovePortAssignment_Click">
<Image Source="./Resources/delete2.png"/>
</Button>
</Grid>
</GroupBox>
<GroupBox Header="Ports" Margin="2" Grid.Row="0" Grid.Column="2">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="28"/>
<RowDefinition Height="28"/>
<RowDefinition Height="28"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="160" />
<ColumnDefinition Width=".38*" />
<ColumnDefinition Width=".62*" />
</Grid.ColumnDefinitions>
<ListBox x:Name="listBoxPort" Margin="2" Grid.RowSpan="4" SelectionChanged="listBoxPort_SelectionChanged">
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem x:Name="menuItemNewPort" Header="New.." Click="menuItemNewPort_Click">
<MenuItem.Icon>
<Image Source="Resources/add.png" />
</MenuItem.Icon>
</MenuItem>
<MenuItem x:Name="menuItemDeletePort" Header="Delete" Click="menuItemDeletePort_Click">
<MenuItem.Icon>
<Image Source="Resources/delete2.png" />
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</ListBox.ContextMenu>
</ListBox>
<Label Grid.Row="0" Grid.Column="1" Content="Name" HorizontalAlignment="Right"/>
<Label Grid.Row="1" Grid.Column="1" Content="Locode" HorizontalAlignment="Right"/>
<TextBox x:Name="textBoxPortName" Grid.Row="0" Grid.Column="2" Margin="2" VerticalContentAlignment="Center" MaxLength="128"/>
<TextBox x:Name="textBoxPortLocode" Grid.Row="1" Grid.Column="2" Margin="2" VerticalContentAlignment="Center" MaxLength="5" />
<Button x:Name="buttonPortSave" Grid.Row="2" Grid.Column="2" Click="buttonPortSave_Click" Margin="2">
<DockPanel>
<Image Source="./Resources/disk_blue.png" Margin="0,0,5,0" Height="24" DockPanel.Dock="Left" Width="16"/>
<TextBlock Text="Save" VerticalAlignment="Center" DockPanel.Dock="Right"/>
</DockPanel>
</Button>
</Grid>
</GroupBox>
<GroupBox Header="User" Margin="2" Grid.Row="1"> <GroupBox Header="User" Margin="2" Grid.Row="1">
<Grid> <Grid>
<Grid.RowDefinitions> <Grid.RowDefinitions>
@ -145,7 +209,7 @@
</Button> </Button>
</Grid> </Grid>
</GroupBox> </GroupBox>
<GroupBox Header="Role" Margin="2" Grid.Column="1"> <GroupBox Header="Role" Margin="2" Grid.Column="1" Grid.Row="1">
<Grid> <Grid>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="28"/> <RowDefinition Height="28"/>
@ -199,7 +263,7 @@
</Button> </Button>
</Grid> </Grid>
</GroupBox> </GroupBox>
<GroupBox Header="Securable" Margin="2" Grid.Row="1" Grid.Column="1"> <GroupBox Header="Securable" Margin="2" Grid.Row="1" Grid.Column="2">
<Grid> <Grid>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="28"/> <RowDefinition Height="28"/>
@ -276,6 +340,7 @@
<DataGridCheckBoxColumn Header="Lock" Binding="{Binding Path=Lock}" IsReadOnly="True"/> <DataGridCheckBoxColumn Header="Lock" Binding="{Binding Path=Lock}" IsReadOnly="True"/>
<DataGridTextColumn Header="Terminal" Binding="{Binding Path=Terminal, Mode=OneWay}" IsReadOnly="True"/> <DataGridTextColumn Header="Terminal" Binding="{Binding Path=Terminal, Mode=OneWay}" IsReadOnly="True"/>
<DataGridTextColumn Header="Authority" Binding="{Binding Path=Authority_Text, Mode=OneWay}" IsReadOnly="True" /> <DataGridTextColumn Header="Authority" Binding="{Binding Path=Authority_Text, Mode=OneWay}" IsReadOnly="True" />
<DataGridTextColumn Header="Port" Binding="{Binding Path=Port}" IsReadOnly="True" />
<DataGridTextColumn Header="Deleted" Binding="{Binding Path=Deleted, Mode=OneWay}" IsReadOnly="True" /> <DataGridTextColumn Header="Deleted" Binding="{Binding Path=Deleted, Mode=OneWay}" IsReadOnly="True" />
</DataGrid.Columns> </DataGrid.Columns>
</local:ENIDataGrid> </local:ENIDataGrid>

View File

@ -38,6 +38,8 @@ namespace RoleEditor
private readonly ObservableCollection<SecurableAssignment> _assignedSecurables = new ObservableCollection<SecurableAssignment>(); private readonly ObservableCollection<SecurableAssignment> _assignedSecurables = new ObservableCollection<SecurableAssignment>();
private readonly ObservableCollection<Berth> _berths = new ObservableCollection<Berth>(); private readonly ObservableCollection<Berth> _berths = new ObservableCollection<Berth>();
private readonly ObservableCollection<Ship> _ships = new ObservableCollection<Ship>(); private readonly ObservableCollection<Ship> _ships = new ObservableCollection<Ship>();
private readonly ObservableCollection<Port> _ports = new ObservableCollection<Port>();
private readonly ObservableCollection<PortAssignment> _assignedPorts = new ObservableCollection<PortAssignment>();
private DBManager _dbManager; private DBManager _dbManager;
#endregion #endregion
@ -77,6 +79,10 @@ namespace RoleEditor
_securables.Add(s); _securables.Add(s);
this.listBoxSecurables.ItemsSource = _securables; this.listBoxSecurables.ItemsSource = _securables;
// load all ports
foreach (Port port in await Port.LoadAll(_dbManager)) _ports.Add(port);
this.listBoxPort.ItemsSource = _ports;
// load all berths // load all berths
foreach (Berth b in await Berth.LoadAll(_dbManager)) foreach (Berth b in await Berth.LoadAll(_dbManager))
{ {
@ -89,6 +95,10 @@ namespace RoleEditor
{ {
b.Authority = participants.Where(p => p.Id == b.Authority_Id).FirstOrDefault(); b.Authority = participants.Where(p => p.Id == b.Authority_Id).FirstOrDefault();
} }
if (b.Port_Id != null)
{
b.Port = _ports.Where(p => p.Id == b.Port_Id).FirstOrDefault();
}
} }
this.dataGridBerths.Initialize(); this.dataGridBerths.Initialize();
this.dataGridBerths.ItemsSource = _berths; this.dataGridBerths.ItemsSource = _berths;
@ -112,12 +122,14 @@ namespace RoleEditor
this.dataGridShips.CreateRequested += DataGridShips_CreateRequested; this.dataGridShips.CreateRequested += DataGridShips_CreateRequested;
this.dataGridShips.EditRequested += DataGridShips_EditRequested; this.dataGridShips.EditRequested += DataGridShips_EditRequested;
this.dataGridShips.DeleteRequested += DataGridShips_DeleteRequested; this.dataGridShips.DeleteRequested += DataGridShips_DeleteRequested;
// set other item sources (filled later after selection) // set other item sources (filled later after selection)
this.listBoxUser.ItemsSource = _users; this.listBoxUser.ItemsSource = _users;
this.listBoxRoleSecurables.ItemsSource = _assignedSecurables; this.listBoxRoleSecurables.ItemsSource = _assignedSecurables;
this.listBoxUserRoles.ItemsSource = _assignedRoles; this.listBoxUserRoles.ItemsSource = _assignedRoles;
this.listBoxPortAssignment.ItemsSource = _assignedPorts;
this.comboBoxParticipantType.ItemsSource = EnumHelper.GetAllValuesAndDescription(typeof(Participant.ParticipantType)); this.comboBoxParticipantType.ItemsSource = EnumHelper.GetAllValuesAndDescription(typeof(Participant.ParticipantType));
@ -192,6 +204,7 @@ namespace RoleEditor
ebd.Berth = b; ebd.Berth = b;
ebd.Owners.AddRange(this._terminals); ebd.Owners.AddRange(this._terminals);
ebd.Authorities.AddRange(this._authorities); ebd.Authorities.AddRange(this._authorities);
ebd.Ports.AddRange(this._ports.Where(p => !p.IsDeleted));
if (ebd.ShowDialog() ?? false) if (ebd.ShowDialog() ?? false)
{ {
await b.Save(_dbManager); await b.Save(_dbManager);
@ -208,6 +221,7 @@ namespace RoleEditor
ebd.Berth = b; ebd.Berth = b;
ebd.Owners.AddRange(this._terminals); ebd.Owners.AddRange(this._terminals);
ebd.Authorities.AddRange(this._authorities); ebd.Authorities.AddRange(this._authorities);
ebd.Ports.AddRange(_ports.Where(p => !p.IsDeleted));
if (ebd.ShowDialog() ?? false) if (ebd.ShowDialog() ?? false)
{ {
_berths.Add(b); _berths.Add(b);
@ -386,6 +400,59 @@ namespace RoleEditor
} }
} }
private async void buttonPortSave_Click(object sender, RoutedEventArgs e)
{
Port? p = this.listBoxPort.SelectedItem as Port;
if (p != null)
{
p.Name = this.textBoxPortName.Text.Trim();
p.Locode = this.textBoxPortLocode.Text.Trim();
await p.Save(_dbManager);
this.listBoxPort.ItemsSource = null;
this.listBoxPort.ItemsSource = _ports;
this.listBoxPort.SelectedItem = p;
}
}
private async void buttonAddPortAssignment_Click(object sender, RoutedEventArgs e)
{
if ((this.listBoxPort.SelectedItem is Port p) && (this.listBoxParticipant.SelectedItem is Participant pa))
{
// test if assignment is already present
bool foundMatchingAssignment = false;
foreach (PortAssignment portAssignment in _assignedPorts)
{
if ((portAssignment.PortId == p.Id) && (portAssignment.ParticipantId == pa.Id))
{
foundMatchingAssignment = true;
break;
}
}
if (!foundMatchingAssignment)
{
PortAssignment portAssignment = new PortAssignment();
portAssignment.PortId = (int)p.Id;
portAssignment.ParticipantId = (int)pa.Id;
portAssignment.AssignedParticipant = pa;
portAssignment.AssignedPort = p;
await portAssignment.Save(_dbManager);
_assignedPorts.Add(portAssignment);
}
}
}
private async void buttonRemovePortAssignment_Click(object sender, RoutedEventArgs e)
{
PortAssignment? pa = this.listBoxPortAssignment.SelectedItem as PortAssignment;
if (pa != null)
{
await pa.Delete(_dbManager);
if (_assignedPorts.Contains(pa))
_assignedPorts.Remove(pa);
}
}
#endregion #endregion
#region listbox selection callbacks #region listbox selection callbacks
@ -430,6 +497,19 @@ namespace RoleEditor
foreach (User u in await User.LoadForParticipant(p, _dbManager)) foreach (User u in await User.LoadForParticipant(p, _dbManager))
_users.Add(u); _users.Add(u);
} }
// -> load port assignments for this participant selection
this._assignedPorts.Clear();
if(p != null)
{
foreach (PortAssignment pa in await PortAssignment.LoadForParticipant(p, this._dbManager))
{
foreach (Port port in this._ports)
if (pa.PortId == port.Id)
pa.AssignedPort = port;
_assignedPorts.Add(pa);
}
}
} }
private async void listBoxRoles_SelectionChanged(object sender, SelectionChangedEventArgs e) private async void listBoxRoles_SelectionChanged(object sender, SelectionChangedEventArgs e)
@ -496,6 +576,13 @@ namespace RoleEditor
this.textBoxSecurableName.Text = (s != null) ? s.Name : string.Empty; this.textBoxSecurableName.Text = (s != null) ? s.Name : string.Empty;
} }
private void listBoxPort_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Port? p = this.listBoxPort.SelectedItem as Port;
this.textBoxPortName.Text = (p != null) ? p.Name : string.Empty;
this.textBoxPortLocode.Text = (p != null) ? p.Locode : string.Empty;
}
#endregion #endregion
#region menuitem callbacks #region menuitem callbacks
@ -597,6 +684,29 @@ namespace RoleEditor
} }
} }
private void menuItemNewPort_Click(object sender, RoutedEventArgs e)
{
Port p = new();
this._ports.Add(p);
this.listBoxPort.SelectedItem = p;
}
private async void menuItemDeletePort_Click(object sender, RoutedEventArgs e)
{
try
{
if (this.listBoxPort.SelectedItem is Port p)
{
await p.Delete(_dbManager);
this._ports.Remove(p);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
#endregion #endregion
#region Excel import #region Excel import
@ -634,7 +744,7 @@ namespace RoleEditor
{ {
if (reader.FieldCount < 2) if (reader.FieldCount < 2)
{ {
throw new InvalidDataException("Sheet must have at least 2 Columns of data"); throw new InvalidDataException("Sheet must have at least 3 Columns of data");
} }
if (reader.IsDBNull(0) && reader.IsDBNull(1)) continue; if (reader.IsDBNull(0) && reader.IsDBNull(1)) continue;
@ -649,8 +759,20 @@ namespace RoleEditor
if (_berths.Any(predicate: x => (x.Name != null) && x.Name.Equals(berth_name, StringComparison.OrdinalIgnoreCase))) if (_berths.Any(predicate: x => (x.Name != null) && x.Name.Equals(berth_name, StringComparison.OrdinalIgnoreCase)))
continue; continue;
string port_name = "";
if (!reader.IsDBNull(2)) port_name = reader.GetString(2);
// find port in list
if(!_ports.Any(x => (x.Name != null) && x.Name.Equals(port_name, StringComparison.OrdinalIgnoreCase)))
continue;
Port port = _ports.First(x => (x.Name != null) && x.Name.Equals(port_name, StringComparison.OrdinalIgnoreCase));
Berth b = new Berth(); Berth b = new Berth();
b.Name = berth_name; b.Name = berth_name;
b.Port = port;
b.Port_Id = port.Id;
bool found_participant = false; bool found_participant = false;
foreach(Participant p in this._participants) foreach(Participant p in this._participants)
@ -801,6 +923,6 @@ namespace RoleEditor
} }
#endregion #endregion
} }
} }

View File

@ -12,7 +12,7 @@ namespace RoleEditor.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.5.0.0")] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.10.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())));
@ -25,8 +25,8 @@ namespace RoleEditor.Properties {
[global::System.Configuration.ApplicationScopedSettingAttribute()] [global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("Server=localhost;User ID=ds;Password=HalloWach_2323XXL!!;Database=bremen_calling;" + [global::System.Configuration.DefaultSettingValueAttribute("Server=localhost;User ID=ds;Password=HalloWach_2323XXL!!;Database=bremen_calling_" +
"Port=33306")] "devel;Port=33306")]
public string ConnectionString { public string ConnectionString {
get { get {
return ((string)(this["ConnectionString"])); return ((string)(this["ConnectionString"]));

View File

@ -3,7 +3,7 @@
<Profiles /> <Profiles />
<Settings> <Settings>
<Setting Name="ConnectionString" Type="System.String" Scope="Application"> <Setting Name="ConnectionString" Type="System.String" Scope="Application">
<Value Profile="(Default)">Server=localhost;User ID=ds;Password=HalloWach_2323XXL!!;Database=bremen_calling;Port=33306</Value> <Value Profile="(Default)">Server=localhost;User ID=ds;Password=HalloWach_2323XXL!!;Database=bremen_calling_devel;Port=33306</Value>
</Setting> </Setting>
</Settings> </Settings>
</SettingsFile> </SettingsFile>

View File

@ -6,6 +6,8 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<UseWPF>true</UseWPF> <UseWPF>true</UseWPF>
<ApplicationIcon>Resources\lock_preferences.ico</ApplicationIcon> <ApplicationIcon>Resources\lock_preferences.ico</ApplicationIcon>
<FileVersion>1.6.0.0</FileVersion>
<AssemblyVersion>1.6.0.0</AssemblyVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -1,12 +1,7 @@
// Copyright (c) 2023- schick Informatik // Copyright (c) 2023- schick Informatik
// Description: Model class for berth entity // Description: Model class for berth entity
using System;
using System.Collections.Generic;
using System.Data; using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace brecal.model namespace brecal.model
{ {
@ -23,10 +18,14 @@ namespace brecal.model
public uint? Authority_Id { get; set; } public uint? Authority_Id { get; set; }
public uint? Port_Id { get; set; }
public Participant? Owner { get; set; } public Participant? Owner { get; set; }
public Participant? Authority { get; set; } public Participant? Authority { get; set; }
public Port? Port { get; set; }
public string? Terminal { get { if (Owner != null) return Owner.Name; else return "n/a"; } } public string? Terminal { get { if (Owner != null) return Owner.Name; else return "n/a"; } }
public string? Authority_Text { get { if (Authority != null) return Authority.Name; else return "n/a"; } } public string? Authority_Text { get { if (Authority != null) return Authority.Name; else return "n/a"; } }
@ -48,12 +47,12 @@ namespace brecal.model
public static void SetLoadQuery(IDbCommand cmd, params object?[] list) public static void SetLoadQuery(IDbCommand cmd, params object?[] list)
{ {
cmd.CommandText = "SELECT id, name, owner_id, authority_id, `lock`, created, modified, deleted FROM berth"; cmd.CommandText = "SELECT id, name, owner_id, authority_id, port_id, `lock`, created, modified, deleted FROM berth";
} }
public static List<DbEntity> LoadElems(IDataReader reader) public static List<DbEntity> LoadElems(IDataReader reader)
{ {
List<DbEntity> result = new List<DbEntity>(); List<DbEntity> result = new();
while (reader.Read()) while (reader.Read())
{ {
Berth b = new(); Berth b = new();
@ -61,10 +60,11 @@ namespace brecal.model
if (!reader.IsDBNull(1)) b.Name = reader.GetString(1); if (!reader.IsDBNull(1)) b.Name = reader.GetString(1);
if (!reader.IsDBNull(2)) b.Owner_Id = (uint) reader.GetInt32(2); if (!reader.IsDBNull(2)) b.Owner_Id = (uint) reader.GetInt32(2);
if (!reader.IsDBNull(3)) b.Authority_Id = (uint) reader.GetInt32(3); if (!reader.IsDBNull(3)) b.Authority_Id = (uint) reader.GetInt32(3);
if (!reader.IsDBNull(4)) b.Lock = reader.GetBoolean(4); if (!reader.IsDBNull(4)) b.Port_Id = (uint) reader.GetInt32(4);
if (!reader.IsDBNull(5)) b.Created = reader.GetDateTime(5); if (!reader.IsDBNull(5)) b.Lock = reader.GetBoolean(5);
if (!reader.IsDBNull(6)) b.Modified = reader.GetDateTime(6); if (!reader.IsDBNull(6)) b.Created = reader.GetDateTime(6);
if (!reader.IsDBNull(7)) b.Deleted = reader.GetInt16(7); if (!reader.IsDBNull(7)) b.Modified = reader.GetDateTime(7);
if (!reader.IsDBNull(8)) b.Deleted = reader.GetInt16(8);
result.Add(b); result.Add(b);
} }
return result; return result;
@ -76,7 +76,7 @@ namespace brecal.model
public override void SetCreate(IDbCommand cmd) public override void SetCreate(IDbCommand cmd)
{ {
cmd.CommandText = "INSERT INTO berth (owner_id, authority_id, name, `lock`) VALUES ( @PID, @AID, @NAME, @LOCK)"; cmd.CommandText = "INSERT INTO berth (owner_id, authority_id, port_id, name, `lock`) VALUES ( @PID, @AID, @PO_ID, @NAME, @LOCK)";
this.SetParameters(cmd); this.SetParameters(cmd);
} }
@ -92,7 +92,7 @@ namespace brecal.model
public override void SetUpdate(IDbCommand cmd) public override void SetUpdate(IDbCommand cmd)
{ {
cmd.CommandText = "UPDATE berth SET name = @NAME, owner_id = @PID, authority_id = @AID, `lock` = @LOCK WHERE id = @ID"; cmd.CommandText = "UPDATE berth SET name = @NAME, owner_id = @PID, authority_id = @AID, port_id = @PO_ID, `lock` = @LOCK WHERE id = @ID";
this.SetParameters(cmd); this.SetParameters(cmd);
} }
@ -109,14 +109,19 @@ namespace brecal.model
IDbDataParameter pid = cmd.CreateParameter(); IDbDataParameter pid = cmd.CreateParameter();
pid.ParameterName = "PID"; pid.ParameterName = "PID";
pid.Value = this.Owner_Id; pid.Value = this.Owner_Id.HasValue ? this.Owner_Id.Value : DBNull.Value;
cmd.Parameters.Add(pid); cmd.Parameters.Add(pid);
IDbDataParameter aid = cmd.CreateParameter(); IDbDataParameter aid = cmd.CreateParameter();
aid.ParameterName = "AID"; aid.ParameterName = "AID";
aid.Value = this.Authority_Id; aid.Value = this.Authority_Id.HasValue ? this.Authority_Id.Value : DBNull.Value;
cmd.Parameters.Add(aid); cmd.Parameters.Add(aid);
IDbDataParameter poid = cmd.CreateParameter();
poid.ParameterName = "PO_ID";
poid.Value = this.Port_Id.HasValue ? this.Port_Id.Value : DBNull.Value;
cmd.Parameters.Add(poid);
IDbDataParameter name = cmd.CreateParameter(); IDbDataParameter name = cmd.CreateParameter();
name.ParameterName = "NAME"; name.ParameterName = "NAME";
name.Value = this.Name; name.Value = this.Name;

View File

@ -70,7 +70,7 @@ namespace brecal.model
public static List<DbEntity> LoadElems(IDataReader reader) public static List<DbEntity> LoadElems(IDataReader reader)
{ {
List<DbEntity> result = new List<DbEntity>(); List<DbEntity> result = new();
while (reader.Read()) while (reader.Read())
{ {
Participant p = new(); Participant p = new();

115
src/brecal.model/Port.cs Normal file
View File

@ -0,0 +1,115 @@
// Copyright (c) 2023- schick Informatik
// Description: Port entity
using System.Data;
namespace brecal.model
{
public class Port : DbEntity
{
#region Properties
public string? Name { get; set; }
public string? Locode { get; set; }
public bool IsDeleted { get; set; } = false;
#endregion
#region overrides
public override void SetCreate(IDbCommand cmd)
{
cmd.CommandText = "INSERT INTO port (name, locode) VALUES ( @NAME, @LOCODE)";
this.SetParameters(cmd);
}
public override void SetDelete(IDbCommand cmd)
{
cmd.CommandText = "UPDATE port SET deleted = 1 WHERE id = @ID";
IDataParameter idParam = cmd.CreateParameter();
idParam.ParameterName = "ID";
idParam.Value = this.Id;
cmd.Parameters.Add(idParam);
}
public override void SetUpdate(IDbCommand cmd)
{
cmd.CommandText = "UPDATE port set name = @NAME, locode = @LOCODE WHERE id = @ID";
this.SetParameters(cmd);
}
#endregion
#region public static methods
public static async Task<List<Port>> LoadAll(IDBManager manager)
{
List<DbEntity> loadResultList = await manager.Load(SetLoadQuery, LoadElems);
List<Port> result = new();
foreach (Port p in loadResultList.Cast<Port>())
result.Add(p);
return result;
}
public static void SetLoadQuery(IDbCommand cmd, params object?[] list)
{
cmd.CommandText = "SELECT id, name, locode, created, modified, deleted FROM port WHERE deleted = 0";
}
public static List<DbEntity> LoadElems(IDataReader reader)
{
List<DbEntity> result = new();
while (reader.Read())
{
Port p = new();
p.Id = (uint)reader.GetInt32(0);
if (!reader.IsDBNull(1)) p.Name = reader.GetString(1);
if (!reader.IsDBNull(2)) p.Locode = reader.GetString(2);
if (!reader.IsDBNull(3)) p.Created = reader.GetDateTime(3);
if (!reader.IsDBNull(4)) p.Modified = reader.GetDateTime(4);
if (!reader.IsDBNull(5)) p.IsDeleted = reader.GetBoolean(5);
result.Add(p);
}
return result;
}
#endregion
#region private methods
private void SetParameters(IDbCommand cmd)
{
IDbDataParameter name = cmd.CreateParameter();
name.ParameterName = "NAME";
name.Value = this.Name;
cmd.Parameters.Add(name);
IDbDataParameter desc = cmd.CreateParameter();
desc.ParameterName = "LOCODE";
desc.Value = this.Locode;
cmd.Parameters.Add(desc);
IDataParameter idParam = cmd.CreateParameter();
idParam.ParameterName = "ID";
idParam.Value = this.Id;
cmd.Parameters.Add(idParam);
}
#endregion
#region overrides
public override string ToString()
{
return $"{Name} ({Locode})";
}
#endregion
}
}

View File

@ -0,0 +1,111 @@
// Copyright (c) 2023- schick Informatik
// Description: Participant Port Map Entity
using System.Data;
namespace brecal.model
{
public class PortAssignment : DbEntity
{
#region Properties
public int? ParticipantId { get; set; }
public int? PortId { get; set; }
public Participant? AssignedParticipant { get; set; }
public Port? AssignedPort { get; set; }
#endregion
#region public static methods
public static async Task<List<PortAssignment>> LoadForParticipant(Participant? p, IDBManager manager)
{
List<DbEntity> loadResultList = await manager.Load(SetLoadQuery, LoadElems, args: p);
List<PortAssignment> result = new();
foreach (PortAssignment pa in loadResultList.Cast<PortAssignment>())
{
pa.AssignedParticipant = p;
result.Add(pa);
}
return result;
}
public static void SetLoadQuery(IDbCommand cmd, params object?[] args)
{
cmd.CommandText = "SELECT id, participant_id, port_id FROM participant_port_map WHERE participant_id = @PID";
if (args.Length != 1 || args[0] is not Participant)
throw new ArgumentException("loader needs single participant as argument");
IDataParameter pid = cmd.CreateParameter();
pid.ParameterName = "PID";
if (args[0] is Participant p)
pid.Value = p.Id;
cmd.Parameters.Add(pid);
}
public static List<DbEntity> LoadElems(IDataReader reader)
{
List<DbEntity> result = new();
while (reader.Read())
{
PortAssignment ra = new();
ra.Id = (uint)reader.GetInt32(0);
if (!reader.IsDBNull(1)) ra.ParticipantId = reader.GetInt32(1);
if (!reader.IsDBNull(2)) ra.PortId = reader.GetInt32(2);
result.Add(ra);
}
return result;
}
#endregion
#region overrides
public override void SetUpdate(IDbCommand cmd)
{
throw new NotImplementedException();
}
public override void SetCreate(IDbCommand cmd)
{
cmd.CommandText = "INSERT INTO participant_port_map (participant_id, port_id) VALUES (@PID, @PORTID)";
IDbDataParameter participantId = cmd.CreateParameter();
participantId.ParameterName = "pID";
participantId.Value = this.ParticipantId;
cmd.Parameters.Add(participantId);
IDbDataParameter portId = cmd.CreateParameter();
portId.ParameterName = "PORTID";
portId.Value = this.PortId;
cmd.Parameters.Add(portId);
}
public override void SetDelete(IDbCommand cmd)
{
cmd.CommandText = "DELETE FROM participant_port_map WHERE id = @ID";
IDataParameter idParam = cmd.CreateParameter();
idParam.ParameterName = "ID";
idParam.Value = this.Id;
cmd.Parameters.Add(idParam);
}
public override string ToString()
{
if (this.AssignedPort == null)
{
return $"{Id}: <defunct port>";
}
else
{
return AssignedPort.Name ?? AssignedPort.Id.ToString();
}
}
#endregion
}
}

View File

@ -1,9 +1,7 @@
using System; // Copyright (c) 2023- schick Informatik
using System.Collections.Generic; // Description: Role Entity
using System.Data; using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace brecal.model namespace brecal.model
{ {

View File

@ -17,7 +17,7 @@ namespace brecal.mysql
public async Task<List<DbEntity>> Load(QueryFunc prepareAction, LoadFunc<IDataReader> loadAction, params object?[] args) public async Task<List<DbEntity>> Load(QueryFunc prepareAction, LoadFunc<IDataReader> loadAction, params object?[] args)
{ {
await using MySqlConnection connection = new MySqlConnection(_connectionString); await using MySqlConnection connection = new(_connectionString);
await connection.OpenAsync(); await connection.OpenAsync();
using MySqlCommand cmd = new(); using MySqlCommand cmd = new();
@ -31,7 +31,7 @@ namespace brecal.mysql
public async Task<object?> ExecuteScalar(Action<IDbCommand> prepareAction) public async Task<object?> ExecuteScalar(Action<IDbCommand> prepareAction)
{ {
await using MySqlConnection connection = new MySqlConnection(_connectionString); await using MySqlConnection connection = new(_connectionString);
await connection.OpenAsync(); await connection.OpenAsync();
using MySqlCommand cmd = new(); using MySqlCommand cmd = new();

View File

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