diff --git a/misc/BreCalApi.yaml b/misc/BreCalApi.yaml index 09ce060..66a598d 100644 --- a/misc/BreCalApi.yaml +++ b/misc/BreCalApi.yaml @@ -2,7 +2,7 @@ openapi: 3.0.0 x-stoplight: id: mwv4y8vcnopwr info: - version: 1.4.1 + version: 1.6.0 title: Bremen calling API description: 'Administer DEBRE ship calls, times and notifications' termsOfService: 'https://www.bsmd.de/' diff --git a/misc/update_1.5_to_1.6.sql b/misc/update_1.5_to_1.6.sql new file mode 100644 index 0000000..842df4b --- /dev/null +++ b/misc/update_1.5_to_1.6.sql @@ -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; \ No newline at end of file diff --git a/misc/version.txt b/misc/version.txt index 34c3267..1f98924 100644 --- a/misc/version.txt +++ b/misc/version.txt @@ -1 +1 @@ -1.4.1.0 \ No newline at end of file +1.6.0.0 \ No newline at end of file diff --git a/src/BreCalClient/BreCalClient.csproj b/src/BreCalClient/BreCalClient.csproj index 606c6a9..1235fff 100644 --- a/src/BreCalClient/BreCalClient.csproj +++ b/src/BreCalClient/BreCalClient.csproj @@ -8,8 +8,8 @@ True BreCalClient.App ..\..\misc\brecal.snk - 1.5.0.4 - 1.5.0.4 + 1.6.0.0 + 1.6.0.0 Bremen calling client A Windows WPF client for the Bremen calling API. containership.ico diff --git a/src/BreCalClient/Properties/PublishProfiles/ClickOnceDevelProfile.pubxml b/src/BreCalClient/Properties/PublishProfiles/ClickOnceDevelProfile.pubxml index e68ac40..96b197a 100644 --- a/src/BreCalClient/Properties/PublishProfiles/ClickOnceDevelProfile.pubxml +++ b/src/BreCalClient/Properties/PublishProfiles/ClickOnceDevelProfile.pubxml @@ -5,7 +5,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121. 1 - 1.4.1.0 + 1.6.0.0 True Debug True diff --git a/src/BreCalClient/Properties/PublishProfiles/ClickOnceTestProfile.pubxml b/src/BreCalClient/Properties/PublishProfiles/ClickOnceTestProfile.pubxml index 1cf52b4..39f9df6 100644 --- a/src/BreCalClient/Properties/PublishProfiles/ClickOnceTestProfile.pubxml +++ b/src/BreCalClient/Properties/PublishProfiles/ClickOnceTestProfile.pubxml @@ -5,7 +5,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121. 0 - 1.5.0.4 + 1.6.0.0 True Debug True diff --git a/src/RoleEditor/EditBerthDialog.xaml b/src/RoleEditor/EditBerthDialog.xaml index 234b02b..2fbb4e3 100644 --- a/src/RoleEditor/EditBerthDialog.xaml +++ b/src/RoleEditor/EditBerthDialog.xaml @@ -5,7 +5,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:RoleEditor" mc:Ignorable="d" - Title="Edit berth" Height="188" Width="450" Loaded="Window_Loaded"> + Title="Edit berth" Height="216" Width="450" Loaded="Window_Loaded"> @@ -16,6 +16,7 @@ + @@ -45,7 +46,9 @@ diff --git a/src/brecal.model/Berth.cs b/src/brecal.model/Berth.cs index a9d4f08..34a091d 100644 --- a/src/brecal.model/Berth.cs +++ b/src/brecal.model/Berth.cs @@ -1,12 +1,7 @@ // Copyright (c) 2023- schick Informatik // Description: Model class for berth entity -using System; -using System.Collections.Generic; using System.Data; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace brecal.model { @@ -23,10 +18,14 @@ namespace brecal.model public uint? Authority_Id { get; set; } + public uint? Port_Id { get; set; } + public Participant? Owner { 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? 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) { - 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 LoadElems(IDataReader reader) { - List result = new List(); + List result = new(); while (reader.Read()) { Berth b = new(); @@ -61,10 +60,11 @@ namespace brecal.model if (!reader.IsDBNull(1)) b.Name = reader.GetString(1); 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(4)) b.Lock = reader.GetBoolean(4); - if (!reader.IsDBNull(5)) b.Created = reader.GetDateTime(5); - if (!reader.IsDBNull(6)) b.Modified = reader.GetDateTime(6); - if (!reader.IsDBNull(7)) b.Deleted = reader.GetInt16(7); + if (!reader.IsDBNull(4)) b.Port_Id = (uint) reader.GetInt32(4); + if (!reader.IsDBNull(5)) b.Lock = reader.GetBoolean(5); + if (!reader.IsDBNull(6)) b.Created = reader.GetDateTime(6); + if (!reader.IsDBNull(7)) b.Modified = reader.GetDateTime(7); + if (!reader.IsDBNull(8)) b.Deleted = reader.GetInt16(8); result.Add(b); } return result; @@ -76,7 +76,7 @@ namespace brecal.model 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); } @@ -92,7 +92,7 @@ namespace brecal.model 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); } @@ -109,14 +109,19 @@ namespace brecal.model IDbDataParameter pid = cmd.CreateParameter(); pid.ParameterName = "PID"; - pid.Value = this.Owner_Id; + pid.Value = this.Owner_Id.HasValue ? this.Owner_Id.Value : DBNull.Value; cmd.Parameters.Add(pid); IDbDataParameter aid = cmd.CreateParameter(); aid.ParameterName = "AID"; - aid.Value = this.Authority_Id; + aid.Value = this.Authority_Id.HasValue ? this.Authority_Id.Value : DBNull.Value; 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(); name.ParameterName = "NAME"; name.Value = this.Name; diff --git a/src/brecal.model/Participant.cs b/src/brecal.model/Participant.cs index e2a8119..cc15705 100644 --- a/src/brecal.model/Participant.cs +++ b/src/brecal.model/Participant.cs @@ -70,7 +70,7 @@ namespace brecal.model public static List LoadElems(IDataReader reader) { - List result = new List(); + List result = new(); while (reader.Read()) { Participant p = new(); diff --git a/src/brecal.model/Port.cs b/src/brecal.model/Port.cs new file mode 100644 index 0000000..aef5b9a --- /dev/null +++ b/src/brecal.model/Port.cs @@ -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> LoadAll(IDBManager manager) + { + List loadResultList = await manager.Load(SetLoadQuery, LoadElems); + List result = new(); + foreach (Port p in loadResultList.Cast()) + 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 LoadElems(IDataReader reader) + { + List 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 + + } + + +} diff --git a/src/brecal.model/PortAssignment.cs b/src/brecal.model/PortAssignment.cs new file mode 100644 index 0000000..eaee03f --- /dev/null +++ b/src/brecal.model/PortAssignment.cs @@ -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> LoadForParticipant(Participant? p, IDBManager manager) + { + List loadResultList = await manager.Load(SetLoadQuery, LoadElems, args: p); + List result = new(); + foreach (PortAssignment pa in loadResultList.Cast()) + { + 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 LoadElems(IDataReader reader) + { + List 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}: "; + } + else + { + return AssignedPort.Name ?? AssignedPort.Id.ToString(); + } + } + + #endregion + + } +} diff --git a/src/brecal.model/Role.cs b/src/brecal.model/Role.cs index c85802b..c52ca1f 100644 --- a/src/brecal.model/Role.cs +++ b/src/brecal.model/Role.cs @@ -1,9 +1,7 @@ -using System; -using System.Collections.Generic; +// Copyright (c) 2023- schick Informatik +// Description: Role Entity + using System.Data; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace brecal.model { diff --git a/src/brecal.mysql/DBManager.cs b/src/brecal.mysql/DBManager.cs index d5c5571..8809061 100644 --- a/src/brecal.mysql/DBManager.cs +++ b/src/brecal.mysql/DBManager.cs @@ -17,7 +17,7 @@ namespace brecal.mysql public async Task> Load(QueryFunc prepareAction, LoadFunc loadAction, params object?[] args) { - await using MySqlConnection connection = new MySqlConnection(_connectionString); + await using MySqlConnection connection = new(_connectionString); await connection.OpenAsync(); using MySqlCommand cmd = new(); @@ -31,7 +31,7 @@ namespace brecal.mysql public async Task ExecuteScalar(Action prepareAction) { - await using MySqlConnection connection = new MySqlConnection(_connectionString); + await using MySqlConnection connection = new(_connectionString); await connection.OpenAsync(); using MySqlCommand cmd = new(); diff --git a/src/server/setup.py b/src/server/setup.py index 44750aa..30698c0 100644 --- a/src/server/setup.py +++ b/src/server/setup.py @@ -2,7 +2,7 @@ from setuptools import find_packages, setup setup( name='BreCal', - version='1.4.0', + version='1.6.0', packages=find_packages(), include_package_data=True, zip_safe=False,