added port_id and ports endpoint to flask app (no validation yet!), reading works

This commit is contained in:
Daniel Schick 2024-09-13 17:45:31 +02:00
parent c796be2892
commit 489dfc2ed6
13 changed files with 189 additions and 42 deletions

View File

@ -1,7 +1,7 @@
//---------------------- //----------------------
// <auto-generated> // <auto-generated>
// Generated REST API Client Code Generator v1.9.8.0 on 12.09.2024 16:39:15 // Generated REST API Client Code Generator v1.9.8.0 on 13.09.2024 16:04:34
// Using the tool OpenAPI Generator v7.4.0 // Using the tool OpenAPI Generator v7.4.0
// </auto-generated> // </auto-generated>
//---------------------- //----------------------
@ -7729,10 +7729,11 @@ namespace BreCalClient.misc.Model
/// <param name="city">city.</param> /// <param name="city">city.</param>
/// <param name="type">a logical combination (bitflag) of possible values. This cannot be encoded in a Enumeration type with discrete values in OpenAPI version &lt; 3.1..</param> /// <param name="type">a logical combination (bitflag) of possible values. This cannot be encoded in a Enumeration type with discrete values in OpenAPI version &lt; 3.1..</param>
/// <param name="flags">Bit-encoded flag array for internal use.</param> /// <param name="flags">Bit-encoded flag array for internal use.</param>
/// <param name="ports">ports.</param>
/// <param name="created">Readonly field set by the database when participant was created.</param> /// <param name="created">Readonly field set by the database when participant was created.</param>
/// <param name="modified">Readonly field set by the database when participant was last modified.</param> /// <param name="modified">Readonly field set by the database when participant was last modified.</param>
/// <param name="deleted">marks the participant as logically deleted (default to false).</param> /// <param name="deleted">marks the participant as logically deleted (default to false).</param>
public Participant(int id = default(int), string name = default(string), string street = default(string), string postalCode = default(string), string city = default(string), int type = default(int), int? flags = default(int?), DateTime created = default(DateTime), DateTime? modified = default(DateTime?), bool deleted = false) public Participant(int id = default(int), string name = default(string), string street = default(string), string postalCode = default(string), string city = default(string), int type = default(int), int? flags = default(int?), List<int> ports = default(List<int>), DateTime created = default(DateTime), DateTime? modified = default(DateTime?), bool deleted = false)
{ {
this.Id = id; this.Id = id;
this.Name = name; this.Name = name;
@ -7741,6 +7742,7 @@ namespace BreCalClient.misc.Model
this.City = city; this.City = city;
this.Type = type; this.Type = type;
this.Flags = flags; this.Flags = flags;
this.Ports = ports;
this.Created = created; this.Created = created;
this.Modified = modified; this.Modified = modified;
this.Deleted = deleted; this.Deleted = deleted;
@ -7790,6 +7792,12 @@ namespace BreCalClient.misc.Model
[DataMember(Name = "flags", EmitDefaultValue = true)] [DataMember(Name = "flags", EmitDefaultValue = true)]
public int? Flags { get; set; } public int? Flags { get; set; }
/// <summary> /// <summary>
/// Gets or Sets Ports
/// </summary>
/// <example>[1,2]</example>
[DataMember(Name = "ports", EmitDefaultValue = true)]
public List<int> Ports { get; set; }
/// <summary>
/// Readonly field set by the database when participant was created /// Readonly field set by the database when participant was created
/// </summary> /// </summary>
/// <value>Readonly field set by the database when participant was created</value> /// <value>Readonly field set by the database when participant was created</value>
@ -7825,6 +7833,7 @@ namespace BreCalClient.misc.Model
sb.Append(" City: ").Append(City).Append("\n"); sb.Append(" City: ").Append(City).Append("\n");
sb.Append(" Type: ").Append(Type).Append("\n"); sb.Append(" Type: ").Append(Type).Append("\n");
sb.Append(" Flags: ").Append(Flags).Append("\n"); sb.Append(" Flags: ").Append(Flags).Append("\n");
sb.Append(" Ports: ").Append(Ports).Append("\n");
sb.Append(" Created: ").Append(Created).Append("\n"); sb.Append(" Created: ").Append(Created).Append("\n");
sb.Append(" Modified: ").Append(Modified).Append("\n"); sb.Append(" Modified: ").Append(Modified).Append("\n");
sb.Append(" Deleted: ").Append(Deleted).Append("\n"); sb.Append(" Deleted: ").Append(Deleted).Append("\n");
@ -7893,6 +7902,12 @@ namespace BreCalClient.misc.Model
(this.Flags != null && (this.Flags != null &&
this.Flags.Equals(input.Flags)) this.Flags.Equals(input.Flags))
) && ) &&
(
this.Ports == input.Ports ||
this.Ports != null &&
input.Ports != null &&
this.Ports.SequenceEqual(input.Ports)
) &&
( (
this.Created == input.Created || this.Created == input.Created ||
(this.Created != null && (this.Created != null &&
@ -7939,6 +7954,10 @@ namespace BreCalClient.misc.Model
{ {
hashCode = (hashCode * 59) + this.Flags.GetHashCode(); hashCode = (hashCode * 59) + this.Flags.GetHashCode();
} }
if (this.Ports != null)
{
hashCode = (hashCode * 59) + this.Ports.GetHashCode();
}
if (this.Created != null) if (this.Created != null)
{ {
hashCode = (hashCode * 59) + this.Created.GetHashCode(); hashCode = (hashCode * 59) + this.Created.GetHashCode();

View File

@ -766,7 +766,7 @@ paths:
description: Returns a list of ports description: Returns a list of ports
tags: tags:
- static - static
operationId: get-ports operationId: get-ports
responses: responses:
'200': '200':
description: list of ports description: list of ports
@ -780,7 +780,7 @@ paths:
country: Germany country: Germany
- id: 4 - id: 4
name: Hamburg name: Hamburg
country: Germany country: Germany
'401': '401':
$ref: '#/components/responses/401' $ref: '#/components/responses/401'
'403': '403':
@ -789,7 +789,6 @@ paths:
$ref: '#/components/responses/500' $ref: '#/components/responses/500'
'503': '503':
$ref: '#/components/responses/503' $ref: '#/components/responses/503'
components: components:
schemas: schemas:
credentials: credentials:
@ -1593,6 +1592,17 @@ components:
participant: participant:
type: object type: object
description: A organisational entity that participates in Bremen Calling description: A organisational entity that participates in Bremen Calling
example:
id: 42
name: BSMD
street: Hermann-Hollerith-Str. 7
postal code: '28359'
city: Bremen
type: 10
flags: 0
created: '2023-08-21T08:23:35Z'
modified: '2023-08-21T08:23:35Z'
deleted: false
properties: properties:
id: id:
type: integer type: integer
@ -1620,8 +1630,21 @@ components:
flags: flags:
description: Bit-encoded flag array for internal use description: Bit-encoded flag array for internal use
type: integer type: integer
nullable: true
example: 0 example: 0
nullable: true
ports:
type: array
x-stoplight:
id: cj29rdqeg15b3
items:
x-stoplight:
id: is7kj0fmlc1nz
type: integer
minimum: 1
example: 1
example:
- 1
- 2
created: created:
type: string type: string
format: date-time format: date-time
@ -1630,25 +1653,14 @@ components:
modified: modified:
type: string type: string
format: date-time format: date-time
nullable: true
description: Readonly field set by the database when participant was last modified description: Readonly field set by the database when participant was last modified
example: '2023-08-21T08:23:35Z' example: '2023-08-21T08:23:35Z'
nullable: true
deleted: deleted:
description: marks the participant as logically deleted description: marks the participant as logically deleted
type: boolean type: boolean
default: false default: false
example: false example: false
example:
id: 42
name: BSMD
street: Hermann-Hollerith-Str. 7
postal code: '28359'
city: Bremen
type: 10
flags: 0
created: '2023-08-21T08:23:35Z'
modified: '2023-08-21T08:23:35Z'
deleted: false
participant_list: participant_list:
description: List of participants description: List of participants
type: array type: array
@ -1856,7 +1868,7 @@ components:
x-stoplight: x-stoplight:
id: it0cu6ivurgii id: it0cu6ivurgii
type: array type: array
items: items:
$ref: '#/components/schemas/port' $ref: '#/components/schemas/port'
example: example:
- id: 2 - id: 2

View File

@ -13,6 +13,7 @@ from .api import ships
from .api import login from .api import login
from .api import user from .api import user
from .api import history from .api import history
from .api import ports
from BreCal.brecal_utils.file_handling import get_project_root, ensure_path from BreCal.brecal_utils.file_handling import get_project_root, ensure_path
from BreCal.brecal_utils.test_handling import execute_test_with_pytest, execute_coverage_test from BreCal.brecal_utils.test_handling import execute_test_with_pytest, execute_coverage_test
@ -65,6 +66,7 @@ def create_app(test_config=None, instance_path=None):
app.register_blueprint(login.bp) app.register_blueprint(login.bp)
app.register_blueprint(user.bp) app.register_blueprint(user.bp)
app.register_blueprint(history.bp) app.register_blueprint(history.bp)
app.register_blueprint(ports.bp)
logging.basicConfig(filename='brecaldevel.log', level=logging.DEBUG, format='%(asctime)s | %(name)s | %(levelname)s | %(message)s') logging.basicConfig(filename='brecaldevel.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))

View File

@ -3,6 +3,7 @@ from flask import Blueprint, request
from webargs.flaskparser import parser from webargs.flaskparser import parser
from .. import impl from .. import impl
from ..services.auth_guard import auth_guard from ..services.auth_guard import auth_guard
from ..services.jwt_handler import decode_jwt
import json import json
from BreCal.validators.validation_error import create_dynamic_exception_response from BreCal.validators.validation_error import create_dynamic_exception_response
@ -15,8 +16,11 @@ def GetBerths():
try: try:
if 'Authorization' in request.headers: if 'Authorization' in request.headers:
token = request.headers.get('Authorization') token = request.headers.get('Authorization')
return impl.berths.GetBerths(token) payload = decode_jwt(token.split("Bearer ")[-1])
options = {}
options["participant_id"] = payload["participant_id"]
return impl.berths.GetBerths(options)
else: else:
return create_dynamic_exception_response(ex=None, status_code=403, message="not authenticated") return create_dynamic_exception_response(ex=None, status_code=403, message="not authenticated")

View File

@ -2,6 +2,7 @@ import logging
from flask import Blueprint, request from flask import Blueprint, request
from .. import impl from .. import impl
from ..services.auth_guard import auth_guard from ..services.auth_guard import auth_guard
from ..services.jwt_handler import decode_jwt
import json import json
from BreCal.validators.validation_error import create_dynamic_exception_response from BreCal.validators.validation_error import create_dynamic_exception_response
@ -12,10 +13,15 @@ bp = Blueprint('participants', __name__)
def GetParticipant(): def GetParticipant():
try: try:
if 'Authorization' in request.headers: if 'Authorization' in request.headers:
token = request.headers.get('Authorization') payload = decode_jwt(request.headers.get("Authorization").split("Bearer ")[-1])
options = {} options = {}
options["user_id"] = request.args.get("user_id") options["user_id"] = request.args.get("user_id")
if "participant_id" in payload:
options["participant_id"] = payload["participant_id"]
else:
return create_dynamic_exception_response(ex=None, status_code=403, message="not authorized")
return impl.participant.GetParticipant(options) return impl.participant.GetParticipant(options)
else: else:
return create_dynamic_exception_response(ex=None, status_code=403, message="not authenticated") return create_dynamic_exception_response(ex=None, status_code=403, message="not authenticated")

View File

@ -0,0 +1,24 @@
import logging
from flask import Blueprint, request
from webargs.flaskparser import parser
from .. import impl
from ..services.auth_guard import auth_guard
import json
from BreCal.validators.validation_error import create_dynamic_exception_response
bp = Blueprint('ports', __name__)
@bp.route('/ports', methods=['get'])
@auth_guard() # no restriction by role
def GetPorts():
try:
if 'Authorization' in request.headers:
token = request.headers.get('Authorization')
return impl.ports.GetPorts(token)
else:
return create_dynamic_exception_response(ex=None, status_code=403, message="not authenticated")
except Exception as ex:
return create_dynamic_exception_response(ex=ex, status_code=400)

View File

@ -7,6 +7,7 @@ from ..services.auth_guard import auth_guard, check_jwt
from BreCal.validators.input_validation import validate_posted_shipcall_data, check_if_user_is_bsmd_type from BreCal.validators.input_validation import validate_posted_shipcall_data, check_if_user_is_bsmd_type
from BreCal.validators.input_validation_shipcall import InputValidationShipcall from BreCal.validators.input_validation_shipcall import InputValidationShipcall
from BreCal.database.sql_handler import execute_sql_query_standalone from BreCal.database.sql_handler import execute_sql_query_standalone
from BreCal.services.jwt_handler import decode_jwt
from BreCal.validators.validation_error import create_validation_error_response, create_werkzeug_error_response, create_dynamic_exception_response from BreCal.validators.validation_error import create_validation_error_response, create_werkzeug_error_response, create_dynamic_exception_response
from . import verify_if_request_is_json from . import verify_if_request_is_json
@ -32,9 +33,10 @@ def GetShipcalls():
# oneline: # oneline:
payload = decode_jwt(request.headers.get("Authorization").split("Bearer ")[-1]) payload = decode_jwt(request.headers.get("Authorization").split("Bearer ")[-1])
""" """
options = {} payload = decode_jwt(request.headers.get("Authorization").split("Bearer ")[-1])
options["participant_id"] = request.args.get("participant_id") options = {}
options["past_days"] = request.args.get("past_days", default=1, type=int) options["past_days"] = request.args.get("past_days", default=1, type=int)
options["participant_id"] = payload["participant_id"]
return impl.shipcalls.GetShipcalls(options) return impl.shipcalls.GetShipcalls(options)
else: else:

View File

@ -10,20 +10,22 @@ def create_sql_query_shipcall_get(options:dict)->str:
options : dict. A dictionary, which must contains the 'past_days' key (int). Determines the range options : dict. A dictionary, which must contains the 'past_days' key (int). Determines the range
by which shipcalls are filtered. by which shipcalls are filtered.
""" """
query = ("SELECT s.id as 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, port_id, type, eta, voyage, etd, arrival_berth_id, departure_berth_id, tug_required, pilot_required, " +
"flags, s.pier_side, bunkering, replenishing_terminal, replenishing_lock, draft, tidal_window_from, " + "flags, s.pier_side, bunkering, replenishing_terminal, replenishing_lock, draft, tidal_window_from, " +
"tidal_window_to, rain_sensitive_cargo, recommended_tugs, anchored, moored_lock, canceled, evaluation, " + "tidal_window_to, rain_sensitive_cargo, recommended_tugs, anchored, moored_lock, canceled, evaluation, " +
"evaluation_message, evaluation_time, evaluation_notifications_sent, s.created as created, s.modified as modified, time_ref_point " + "evaluation_message, evaluation_time, evaluation_notifications_sent, s.created as created, s.modified as modified, time_ref_point " +
"FROM shipcall s " + "FROM shipcall s " +
"LEFT JOIN times t ON t.shipcall_id = s.id AND t.participant_type = 8 " + "LEFT JOIN times t ON t.shipcall_id = s.id AND t.participant_type = 8 " +
"WHERE " + "WHERE " +
"port_id in (SELECT port_id FROM participant_port_map WHERE participant_id = %d)" +
" AND (" +
"(type = 1 AND " + "(type = 1 AND " +
"((t.id IS NOT NULL AND t.eta_berth >= DATE(NOW() - INTERVAL %d DAY)) OR " + "((t.id IS NOT NULL AND t.eta_berth >= DATE(NOW() - INTERVAL %d DAY)) OR " +
"(eta >= DATE(NOW() - INTERVAL %d DAY)))) OR " + "(eta >= DATE(NOW() - INTERVAL %d DAY)))) OR " +
"((type = 2 OR type = 3) AND " + "((type = 2 OR type = 3) AND " +
"((t.id IS NOT NULL AND t.etd_berth >= DATE(NOW() - INTERVAL %d DAY)) OR " + "((t.id IS NOT NULL AND t.etd_berth >= DATE(NOW() - INTERVAL %d DAY)) OR " +
"(etd >= DATE(NOW() - INTERVAL %d DAY)))) " + "(etd >= DATE(NOW() - INTERVAL %d DAY))))) " +
"ORDER BY eta") % (options["past_days"], options["past_days"], options["past_days"], options["past_days"]) "ORDER BY eta") % (options["participant_id"], options["past_days"], options["past_days"], options["past_days"], options["past_days"])
return query return query

View File

@ -6,4 +6,5 @@ from . import times
from . import ships from . import ships
from . import login from . import login
from . import user from . import user
from . import history from . import history
from . import ports

View File

@ -4,9 +4,8 @@ import pydapper
from ..schemas import model from ..schemas import model
from .. import local_db from .. import local_db
from BreCal.database.sql_queries import SQLQuery
def GetBerths(token): def GetBerths(options):
""" """
No parameters, gets all entries No parameters, gets all entries
""" """
@ -14,9 +13,13 @@ def GetBerths(token):
try: try:
pooledConnection = local_db.getPoolConnection() pooledConnection = local_db.getPoolConnection()
commands = pydapper.using(pooledConnection) commands = pydapper.using(pooledConnection)
# query = SQLQuery.get_berth()
# data = commands.query(query, model=model.Berth) # only load berths to ports that the participant is assigned to
data = commands.query("SELECT id, name, `lock`, owner_id, authority_id, created, modified, deleted FROM berth WHERE deleted = 0 ORDER BY name", model=model.Berth) query = ("SELECT id, name, `lock`, owner_id, port_id, authority_id, created, modified, deleted FROM berth WHERE " +
"deleted = 0 AND + "
"port_id IN (SELECT port_id FROM participant_port_map WHERE participant_id = %d) " +
"ORDER BY name") % (options["participant_id"])
data = commands.query(query, model=model.Berth)
return json.dumps(data, default=model.obj_dict), 200, {'Content-Type': 'application/json; charset=utf-8'} return json.dumps(data, default=model.obj_dict), 200, {'Content-Type': 'application/json; charset=utf-8'}
except Exception as ex: except Exception as ex:

View File

@ -10,18 +10,35 @@ def GetParticipant(options):
""" """
:param options: A dictionary containing all the paramters for the Operations :param options: A dictionary containing all the paramters for the Operations
options["user_id"]: **Id of user**. *Example: 2*. User id returned by login call. options["user_id"]: **Id of user**. *Example: 2*. User id returned by login call.
"""
"""
try: try:
pooledConnection = local_db.getPoolConnection() pooledConnection = local_db.getPoolConnection()
commands = pydapper.using(pooledConnection) commands = pydapper.using(pooledConnection)
if "user_id" in options and options["user_id"]: if "user_id" in options and options["user_id"]:
# query = SQLQuery.get_participant_by_user_id() # query = SQLQuery.get_participant_by_user_id()
data = commands.query("SELECT p.id as id, p.name as name, p.street as street, p.postal_code as postal_code, p.city as city, p.type as type, p.flags as flags, p.created as created, p.modified as modified, p.deleted as deleted FROM participant p INNER JOIN user u WHERE u.participant_id = p.id and u.id = ?userid?", model=model.Participant, param={"userid" : options["user_id"]}) query = ("SELECT p.id as id, p.name as name, p.street as street, p.postal_code as postal_code, p.city as city, p.type as type, p.flags as flags, " +
"p.created as created, p.modified as modified, p.deleted as deleted FROM participant p " +
"INNER JOIN user u WHERE u.participant_id = p.id and u.id = %d") % options["user_id"]
data = commands.query(query, model=model.Participant)
else: else:
# query = SQLQuery.get_participants() # query = SQLQuery.get_participants()
data = commands.query("SELECT id, name, street, postal_code, city, type, flags, created, modified, deleted FROM participant p ORDER BY p.name", model=model.Participant)
# list only participants that are assigned to the same ports than participant of caller
query = ("SELECT p.id as id, name, street, postal_code, city, type, flags, p.created, p.modified, p.deleted " +
"FROM participant p " +
"JOIN participant_port_map ON p.id = participant_port_map.participant_id " +
"WHERE participant_port_map.port_id IN " +
"(SELECT port_id FROM participant_port_map where participant_id = %d) " +
"GROUP BY id " +
"ORDER BY p.name") % options["participant_id"]
data = commands.query(query, model=model.Participant)
for participant in data:
port_query = "SELECT port_id FROM participant_port_map WHERE participant_id=?id?";
for record in commands.query(port_query, model=model.Port_Assignment, param={"id" : participant.id}, buffered=False):
pa = model.Port_Assignment(record.port_id)
participant.ports.append(pa.port_id)
return json.dumps(data, default=model.obj_dict), 200, {'Content-Type': 'application/json; charset=utf-8'} return json.dumps(data, default=model.obj_dict), 200, {'Content-Type': 'application/json; charset=utf-8'}

View File

@ -0,0 +1,33 @@
import json
import logging
import pydapper
from ..schemas import model
from .. import local_db
from BreCal.database.sql_queries import SQLQuery
def GetPorts(token):
"""
No parameters, gets all entries
"""
try:
pooledConnection = local_db.getPoolConnection()
commands = pydapper.using(pooledConnection)
data = commands.query("SELECT id, name, locode, created, modified, deleted FROM port WHERE deleted = 0 ORDER BY name", model=model.Port)
return json.dumps(data, default=model.obj_dict), 200, {'Content-Type': 'application/json; charset=utf-8'}
except Exception as ex:
logging.error(ex)
print(ex)
result = {}
result["message"] = "call failed"
return json.dumps(result), 500
finally:
if pooledConnection is not None:
pooledConnection.close()

View File

@ -29,6 +29,15 @@ class Berth(Schema):
lock: bool lock: bool
owner_id: int owner_id: int
authority_id: int authority_id: int
port_id: int
created: datetime
modified: datetime
deleted: bool
class Port(Schema):
id: int
name: str
locode: str
created: datetime created: datetime
modified: datetime modified: datetime
deleted: bool deleted: bool
@ -164,10 +173,11 @@ class Participant(Schema):
postal_code: str postal_code: str
city: str city: str
type: int # fields.Enum(ParticipantType ...) type: int # fields.Enum(ParticipantType ...)
flags: int flags: int
created: datetime created: datetime
modified: datetime modified: datetime
deleted: bool deleted: bool
ports: List[int] = field(default_factory=list)
@validates("type") @validates("type")
def validate_type(self, value): def validate_type(self, value):
@ -269,6 +279,16 @@ class Participant_Assignment:
def to_json(self): def to_json(self):
return self.__dict__ return self.__dict__
@dataclass
class Port_Assignment:
def __init__(self, port_id):
self.port_id = port_id
pass
port_id: int
def to_json(self):
return self.__dict__
@dataclass @dataclass
class Shipcall: class Shipcall:
@ -301,6 +321,7 @@ class Shipcall:
evaluation_time: datetime evaluation_time: datetime
evaluation_notifications_sent: bool evaluation_notifications_sent: bool
time_ref_point: int time_ref_point: int
port_id: int
created: datetime created: datetime
modified: datetime modified: datetime
participants: List[Participant_Assignment] = field(default_factory=list) participants: List[Participant_Assignment] = field(default_factory=list)
@ -335,6 +356,7 @@ class Shipcall:
"evaluation_time": self.evaluation_time.isoformat() if self.evaluation_time else "", "evaluation_time": self.evaluation_time.isoformat() if self.evaluation_time else "",
"evaluation_notifications_sent": self.evaluation_notifications_sent, "evaluation_notifications_sent": self.evaluation_notifications_sent,
"time_ref_point": self.time_ref_point, "time_ref_point": self.time_ref_point,
"port_id": self.port_id,
"created": self.created.isoformat() if self.created else "", "created": self.created.isoformat() if self.created else "",
"modified": self.modified.isoformat() if self.modified else "", "modified": self.modified.isoformat() if self.modified else "",
"participants": [participant.__dict__ for participant in self.participants] "participants": [participant.__dict__ for participant in self.participants]
@ -343,8 +365,8 @@ class Shipcall:
@classmethod @classmethod
def from_query_row(self, 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, anchored, moored_lock, canceled, evaluation, evaluation_message, evaluation_time, evaluation_notifications_sent, time_ref_point, created, modified): def from_query_row(self, 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, anchored, moored_lock, canceled, evaluation, evaluation_message, evaluation_time, evaluation_notifications_sent, time_ref_point, port_id, created, modified):
return self(id, ship_id, ShipcallType(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, anchored, moored_lock, canceled, EvaluationType(evaluation), evaluation_message, evaluation_time, evaluation_notifications_sent, time_ref_point, created, modified) return self(id, ship_id, ShipcallType(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, anchored, moored_lock, canceled, EvaluationType(evaluation), evaluation_message, evaluation_time, evaluation_notifications_sent, time_ref_point, port_id, created, modified)
class ShipcallId(Schema): class ShipcallId(Schema):
pass pass