From a5b16154c61cfccd0ae038dc8ce6f5e74ec51c8d Mon Sep 17 00:00:00 2001 From: Daniel Schick Date: Wed, 27 Mar 2024 19:20:54 +0100 Subject: [PATCH] Fixed saving of shipcall by correctly interpreting enums now The trick was to use a helper-field and a (decorated) @post_load method in the model that allows to fill the helper fields with the values (ints) instead of strings for enums. Trouble is: We are parsing strings from API/JSON and want to serialize as int (value in IntEnum). The helper fields also must be skipped when setting up the query. Pretty convoluted, but gets the jon done (finally). Also extended the database by new field 'interval_end' which is a preparation to allow not only timestamps but also intervals when specifying times for participants. --- misc/BreCalApi.yaml | 5 +++++ misc/update_1.1_to_1.2.sql | 3 ++- src/server/BreCal/impl/shipcalls.py | 11 ++++++++++- src/server/BreCal/impl/times.py | 2 +- src/server/BreCal/schemas/model.py | 14 +++++++++++--- 5 files changed, 29 insertions(+), 6 deletions(-) diff --git a/misc/BreCalApi.yaml b/misc/BreCalApi.yaml index 1b8f578..fd767b0 100644 --- a/misc/BreCalApi.yaml +++ b/misc/BreCalApi.yaml @@ -669,6 +669,11 @@ components: format: date-time nullable: true description: can be set by mooring if actual times are different from planned + interval_end: + type: string + format: date-time + nullable: true + description: End of the interval for the times entry created: type: string format: date-time diff --git a/misc/update_1.1_to_1.2.sql b/misc/update_1.1_to_1.2.sql index 0e31388..d023c47 100644 --- a/misc/update_1.1_to_1.2.sql +++ b/misc/update_1.1_to_1.2.sql @@ -89,4 +89,5 @@ ADD CONSTRAINT `FK_HISTORY_USER` -- add ata_atd field to times ALTER TABLE `bremen_calling_devel`.`times` -ADD COLUMN `ata_atd` DATETIME NULL DEFAULT NULL COMMENT 'Relevant only for mooring, this field can be used to record actual ATA / ATD' AFTER `participant_type`; \ No newline at end of file +ADD COLUMN `ata_atd` DATETIME NULL DEFAULT NULL COMMENT 'Relevant only for mooring, this field can be used to record actual ATA / ATD' AFTER `participant_type`, +ADD COLUMN `interval_end` DATETIME NULL DEFAULT NULL COMMENT 'If this value is set the times are given as interval instead of a single point in time. The start time value depends on the participant type.' AFTER `ata_atd`; \ No newline at end of file diff --git a/src/server/BreCal/impl/shipcalls.py b/src/server/BreCal/impl/shipcalls.py index 733f516..f06e474 100644 --- a/src/server/BreCal/impl/shipcalls.py +++ b/src/server/BreCal/impl/shipcalls.py @@ -166,6 +166,7 @@ def PutShipcalls(schemaModel): query = "UPDATE shipcall SET " isNotFirst = False for key in schemaModel.keys(): + param_key = key if key == "id": continue if key == "participants": @@ -178,10 +179,18 @@ def PutShipcalls(schemaModel): continue if key == "evaluation_message": continue + if key == "type": + param_key = "type_value" + if key == "type_value": + continue + if key == "evaluation": + param_key = "evaluation_value" + if key == "evaluation_value": + continue if isNotFirst: query += ", " isNotFirst = True - query += key + " = ?" + key + "? " + query += key + " = ?" + param_key + "? " query += "WHERE id = ?id?" affected_rows = commands.execute(query, param=schemaModel) diff --git a/src/server/BreCal/impl/times.py b/src/server/BreCal/impl/times.py index 5fff877..b7b7dcb 100644 --- a/src/server/BreCal/impl/times.py +++ b/src/server/BreCal/impl/times.py @@ -22,7 +22,7 @@ def GetTimes(options): commands = pydapper.using(pooledConnection) data = commands.query("SELECT id, eta_berth, eta_berth_fixed, etd_berth, etd_berth_fixed, lock_time, lock_time_fixed, " + "zone_entry, zone_entry_fixed, operations_start, operations_end, remarks, shipcall_id, participant_id, " + - "berth_id, berth_info, pier_side, participant_type, created, modified, ata_atd FROM times " + + "berth_id, berth_info, pier_side, participant_type, created, modified, ata_atd, interval_end FROM times " + "WHERE times.shipcall_id = ?scid?", model=model.Times, param={"scid" : options["shipcall_id"]}) pooledConnection.close() diff --git a/src/server/BreCal/schemas/model.py b/src/server/BreCal/schemas/model.py index 5a2c15f..0b427f2 100644 --- a/src/server/BreCal/schemas/model.py +++ b/src/server/BreCal/schemas/model.py @@ -1,5 +1,5 @@ from dataclasses import field, dataclass -from marshmallow import Schema, fields, INCLUDE, ValidationError +from marshmallow import Schema, fields, post_load, INCLUDE, ValidationError from marshmallow.fields import Field from marshmallow_enum import EnumField from enum import IntEnum @@ -151,7 +151,7 @@ class ShipcallSchema(Schema): id = fields.Int() ship_id = fields.Int() - type = EnumField(ShipcallType, by_value=True, required=True) + type = fields.Enum(ShipcallType, by_value=True, required=True) eta = fields.DateTime(Required = False, allow_none=True) voyage = fields.Str(allow_none=True, metadata={'Required':False}) # Solving: RemovedInMarshmallow4Warning: Passing field metadata as keyword arguments is deprecated. Use the explicit `metadata=...` argument instead. Additional metadata: {'Required': False} etd = fields.DateTime(Required = False, allow_none=True) @@ -172,7 +172,7 @@ class ShipcallSchema(Schema): anchored = fields.Bool(Required = False, allow_none=True) moored_lock = fields.Bool(Required = False, allow_none=True) canceled = fields.Bool(Required = False, allow_none=True) - evaluation = EnumField(EvaluationType, required=False, allow_none=True, by_value=True) + evaluation = fields.Enum(EvaluationType, required=False, allow_none=True, by_value=True) evaluation_message = fields.Str(allow_none=True, metadata={'Required':False}) # Solving: RemovedInMarshmallow4Warning: Passing field metadata as keyword arguments is deprecated. Use the explicit `metadata=...` argument instead. Additional metadata: {'Required': False} evaluation_time = fields.DateTime(Required = False, allow_none=True) evaluation_notifications_sent = fields.Bool(Required = False, allow_none=True) @@ -181,6 +181,12 @@ class ShipcallSchema(Schema): created = fields.DateTime(Required = False, allow_none=True) modified = fields.DateTime(Required = False, allow_none=True) + @post_load + def make_shipcall(self, data, **kwargs): + data['type_value'] = data['type'].value + data['evaluation_value'] = data['evaluation'].value + return data + @dataclass class Participant_Assignment: def __init__(self, participant_id, type): @@ -297,6 +303,7 @@ class TimesSchema(Schema): shipcall_id = fields.Int(Required = True) participant_type = fields.Int(Required = False, allow_none=True) ata_atd = fields.DateTime(Required = False, allow_none=True) + interval_end = fields.DateTime(Required = False, allow_none=True) created = fields.DateTime(Required = False, allow_none=True) modified = fields.DateTime(Required = False, allow_none=True) @@ -335,6 +342,7 @@ class Times: participant_type: int shipcall_id: int ata_atd: datetime + interval_end: datetime created: datetime modified: datetime