Merge ee53d7fd9d into 50e9261267
This commit is contained in:
commit
a8dde26a02
@ -13,6 +13,7 @@ from .api import ships
|
||||
from .api import login
|
||||
from .api import user
|
||||
from .api import history
|
||||
from .api import latest
|
||||
|
||||
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
|
||||
@ -61,6 +62,7 @@ def create_app(test_config=None):
|
||||
app.register_blueprint(login.bp)
|
||||
app.register_blueprint(user.bp)
|
||||
app.register_blueprint(history.bp)
|
||||
app.register_blueprint(latest.bp)
|
||||
|
||||
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))
|
||||
|
||||
@ -0,0 +1,35 @@
|
||||
import typing
|
||||
import datetime
|
||||
|
||||
# global dictionary, which informs about the latest change of a given database (e.g., 'berths')
|
||||
# initialize all values as null (None)
|
||||
latest_get_request_dict = {database:None for database in ["shipcalls", "ships", "times"]}
|
||||
|
||||
def update_latest_modification_time(key:str, modification_time:datetime.datetime)->None:
|
||||
"""
|
||||
This function updates the {latest_get_request_dict} inplace at the specified {key} with the defined {modification_time},
|
||||
*if* the time is more recent than the currently stored value
|
||||
"""
|
||||
global latest_get_request_dict
|
||||
|
||||
value = latest_get_request_dict.get(key,None)
|
||||
if value is None:
|
||||
# when there is no value stored for the key, update the value
|
||||
latest_get_request_dict[key] = modification_time
|
||||
else:
|
||||
# when the modification date is more recent than the stored value, update it
|
||||
if modification_time > value:
|
||||
latest_get_request_dict[key] = modification_time
|
||||
|
||||
return
|
||||
|
||||
def get_latest_modification_times()->dict[str,typing.Optional[str]]:
|
||||
"""
|
||||
This function returns a dictionary, where each key determines the database name, and each value is either an isoformatted datetime
|
||||
of the latest modification time, or None.
|
||||
"""
|
||||
global latest_get_request_dict
|
||||
|
||||
latest_dict = {k:v.isoformat() if isinstance(v,datetime.datetime) else v for k,v in latest_get_request_dict.items()}
|
||||
return latest_dict
|
||||
|
||||
@ -16,3 +16,4 @@ def GetBerths():
|
||||
return impl.berths.GetBerths(token)
|
||||
else:
|
||||
return json.dumps("not authenticated"), 403
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@ bp = Blueprint('history', __name__)
|
||||
|
||||
@bp.route('/history', methods=['get'])
|
||||
@auth_guard() # no restriction by role
|
||||
def GetParticipant():
|
||||
def GetParticipant(): # #TODO: rename? Naming might be a copy-paste typo
|
||||
|
||||
if 'Authorization' in request.headers:
|
||||
token = request.headers.get('Authorization')
|
||||
|
||||
18
src/server/BreCal/api/latest.py
Normal file
18
src/server/BreCal/api/latest.py
Normal file
@ -0,0 +1,18 @@
|
||||
from flask import Blueprint, request
|
||||
from webargs.flaskparser import parser
|
||||
from .. import impl
|
||||
from ..services.auth_guard import auth_guard
|
||||
import json
|
||||
|
||||
bp = Blueprint('getlatest', __name__)
|
||||
|
||||
|
||||
@bp.route('/getlatest', methods=['get'])
|
||||
@auth_guard() # no restriction by role
|
||||
def GetLatest():
|
||||
"""This endpoint verifies the user and executes impl.latest.GetLatest"""
|
||||
if 'Authorization' in request.headers:
|
||||
token = request.headers.get('Authorization')
|
||||
return impl.latest.GetLatest(token)
|
||||
else:
|
||||
return json.dumps("not authenticated"), 403
|
||||
@ -16,4 +16,6 @@ def GetNotifications():
|
||||
return impl.notifications.GetNotifications(options)
|
||||
else:
|
||||
logging.warning("attempt to load notifications without shipcall id")
|
||||
return json.dumps("missing argument"), 400
|
||||
return json.dumps("missing argument"), 400
|
||||
|
||||
|
||||
|
||||
@ -53,3 +53,4 @@ def PutShipcalls():
|
||||
return json.dumps("bad format"), 400
|
||||
|
||||
return impl.shipcalls.PutShipcalls(loadedModel)
|
||||
|
||||
|
||||
@ -66,3 +66,5 @@ def DeleteShip():
|
||||
return json.dumps("bad format"), 400
|
||||
|
||||
return impl.ships.DeleteShip(options)
|
||||
|
||||
|
||||
|
||||
@ -67,3 +67,4 @@ def DeleteTimes():
|
||||
else:
|
||||
logging.warning("Times delete missing id argument")
|
||||
return json.dumps("missing argument"), 400
|
||||
|
||||
|
||||
@ -6,4 +6,4 @@ from . import times
|
||||
from . import ships
|
||||
from . import login
|
||||
from . import user
|
||||
from . import history
|
||||
from . import history
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import json
|
||||
import logging
|
||||
import pydapper
|
||||
import datetime
|
||||
|
||||
from ..schemas import model
|
||||
from .. import local_db
|
||||
@ -14,6 +15,7 @@ def GetBerths(token):
|
||||
pooledConnection = local_db.getPoolConnection()
|
||||
commands = pydapper.using(pooledConnection)
|
||||
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)
|
||||
|
||||
return json.dumps(data, default=model.obj_dict), 200, {'Content-Type': 'application/json; charset=utf-8'}
|
||||
|
||||
except Exception as ex:
|
||||
@ -30,3 +32,5 @@ def GetBerths(token):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -37,3 +37,5 @@ def GetHistory(options):
|
||||
|
||||
return json.dumps(data, default=model.obj_dict), 200, {'Content-Type': 'application/json; charset=utf-8'}
|
||||
|
||||
|
||||
|
||||
|
||||
32
src/server/BreCal/impl/latest.py
Normal file
32
src/server/BreCal/impl/latest.py
Normal file
@ -0,0 +1,32 @@
|
||||
import json
|
||||
import logging
|
||||
import pydapper
|
||||
import datetime
|
||||
|
||||
from ..schemas import model
|
||||
from .. import local_db
|
||||
from BreCal.api import get_latest_modification_times
|
||||
|
||||
def GetLatest(token):
|
||||
"""
|
||||
Returns a dictionary of the latest modification dates within the databases 'ships', 'shipcalls' and 'times'. When there has not yet been a modification, this method returns null.
|
||||
Creates a dictionary of type dict[str, typing.Optional[datetime.datetime]]
|
||||
"""
|
||||
|
||||
try:
|
||||
data = get_latest_modification_times()
|
||||
return json.dumps(data), 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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -30,3 +30,4 @@ def GetNotifications(options):
|
||||
return json.dumps(data, default=model.obj_dict), 200, {'Content-Type': 'application/json; charset=utf-8'}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -2,12 +2,14 @@ import json
|
||||
import logging
|
||||
import traceback
|
||||
import pydapper
|
||||
import datetime
|
||||
|
||||
from ..schemas import model
|
||||
from .. import local_db
|
||||
from ..services.auth_guard import check_jwt
|
||||
|
||||
from BreCal.database.update_database import evaluate_shipcall_state
|
||||
from BreCal.api import update_latest_modification_time
|
||||
|
||||
def GetShipcalls(options):
|
||||
"""
|
||||
@ -140,6 +142,9 @@ def PostShipcalls(schemaModel):
|
||||
user_data = check_jwt()
|
||||
query = "INSERT INTO history (participant_id, shipcall_id, user_id, timestamp, eta, type, operation) VALUES (?pid?, ?scid?, ?uid?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 1, 1)"
|
||||
commands.execute(query, {"scid" : new_id, "pid" : user_data["participant_id"], "uid" : user_data["id"]})
|
||||
|
||||
# track the latest update in the global dictionary
|
||||
update_latest_modification_time(key="shipcalls",modification_time=datetime.datetime.now()) # new_id
|
||||
|
||||
return json.dumps({"id" : new_id}), 201, {'Content-Type': 'application/json; charset=utf-8'}
|
||||
|
||||
@ -243,6 +248,9 @@ def PutShipcalls(schemaModel):
|
||||
query = "INSERT INTO history (participant_id, shipcall_id, user_id, timestamp, eta, type, operation) VALUES (?pid?, ?scid?, ?uid?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 1, 2)"
|
||||
commands.execute(query, {"scid" : schemaModel["id"], "pid" : user_data["participant_id"], "uid" : user_data["id"]})
|
||||
|
||||
# track the latest update in the global dictionary
|
||||
update_latest_modification_time(key="shipcalls",modification_time=datetime.datetime.now()) # schemaModel["id"]
|
||||
|
||||
return json.dumps({"id" : schemaModel["id"]}), 200
|
||||
|
||||
except Exception as ex:
|
||||
@ -256,4 +264,3 @@ def PutShipcalls(schemaModel):
|
||||
finally:
|
||||
if pooledConnection is not None:
|
||||
pooledConnection.close()
|
||||
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
import json
|
||||
import logging
|
||||
import pydapper
|
||||
import datetime
|
||||
|
||||
from ..schemas import model
|
||||
from .. import local_db
|
||||
from BreCal.api import update_latest_modification_time
|
||||
|
||||
def GetShips(token):
|
||||
"""
|
||||
@ -11,10 +13,10 @@ def GetShips(token):
|
||||
"""
|
||||
|
||||
try:
|
||||
|
||||
pooledConnection = local_db.getPoolConnection()
|
||||
commands = pydapper.using(pooledConnection)
|
||||
data = commands.query("SELECT id, name, imo, callsign, participant_id, length, width, is_tug, bollard_pull, eni, created, modified, deleted FROM ship ORDER BY name", model=model.Ship)
|
||||
update_latest_modification_time(key="ships", modification_time=datetime.datetime.now())
|
||||
|
||||
return json.dumps(data, default=model.obj_dict), 200, {'Content-Type': 'application/json; charset=utf-8'}
|
||||
|
||||
@ -156,4 +158,5 @@ def DeleteShip(options):
|
||||
print(ex)
|
||||
result = {}
|
||||
result["message"] = "call failed"
|
||||
return json.dumps(result), 500, {'Content-Type': 'application/json; charset=utf-8'}
|
||||
return json.dumps(result), 500, {'Content-Type': 'application/json; charset=utf-8'}
|
||||
|
||||
@ -2,11 +2,13 @@ import json
|
||||
import logging
|
||||
import traceback
|
||||
import pydapper
|
||||
import datetime
|
||||
|
||||
from ..schemas import model
|
||||
from .. import local_db
|
||||
from ..services.auth_guard import check_jwt
|
||||
|
||||
from BreCal.api import update_latest_modification_time
|
||||
from BreCal.database.update_database import evaluate_shipcall_state
|
||||
|
||||
def GetTimes(options):
|
||||
@ -91,6 +93,9 @@ def PostTimes(schemaModel):
|
||||
user_data = check_jwt()
|
||||
query = "INSERT INTO history (participant_id, shipcall_id, user_id, timestamp, eta, type, operation) VALUES (?pid?, ?scid?, ?uid?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 2, 1)"
|
||||
commands.execute(query, {"scid" : schemaModel["shipcall_id"], "pid" : user_data["participant_id"], "uid" : user_data["id"]})
|
||||
|
||||
# track the latest update in the global dictionary
|
||||
update_latest_modification_time(key="times", modification_time=datetime.datetime.now()) # new_id
|
||||
|
||||
return json.dumps({"id" : new_id}), 201, {'Content-Type': 'application/json; charset=utf-8'}
|
||||
|
||||
@ -136,6 +141,7 @@ def PutTimes(schemaModel):
|
||||
query += "WHERE id = ?id?"
|
||||
|
||||
affected_rows = commands.execute(query, param=schemaModel)
|
||||
new_id = commands.execute_scalar("select last_insert_id()")
|
||||
|
||||
# apply 'Traffic Light' evaluation to obtain 'GREEN', 'YELLOW' or 'RED' evaluation state. The function internally updates the mysql database 'shipcall'
|
||||
evaluate_shipcall_state(mysql_connector_instance=pooledConnection, shipcall_id=schemaModel["shipcall_id"]) # every times data object refers to the 'shipcall_id'
|
||||
@ -151,6 +157,9 @@ def PutTimes(schemaModel):
|
||||
|
||||
# if affected_rows == 1: # this doesn't work as expected
|
||||
|
||||
# track the latest update in the global dictionary
|
||||
update_latest_modification_time(key="times", modification_time=datetime.datetime.now()) # new_id
|
||||
|
||||
return json.dumps({"id" : schemaModel["id"]}), 200, {'Content-Type': 'application/json; charset=utf-8'}
|
||||
|
||||
except Exception as ex:
|
||||
@ -185,6 +194,10 @@ def DeleteTimes(options):
|
||||
query = "INSERT INTO history (participant_id, shipcall_id, user_id, timestamp, eta, type, operation) VALUES (?pid?, ?shipcall_id?, ?uid?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 2, 3)"
|
||||
commands.execute(query, {"pid" : user_data["participant_id"], "shipcall_id" : shipcall_id, "uid" : user_data["id"]})
|
||||
|
||||
# track the latest update in the global dictionary
|
||||
###### could use a query similar to this one: modification_time = commands.execute_scalar("SELECT modified FROM times WHERE id = ?id?", param={"id" : options["id"]}) # clarify: when modified is null, created should be used...
|
||||
update_latest_modification_time(key="times", modification_time=datetime.datetime.now()) # options["id"]
|
||||
|
||||
if affected_rows == 1:
|
||||
return json.dumps({"id" : options["id"]}), 200, {'Content-Type': 'application/json; charset=utf-8'}
|
||||
|
||||
@ -201,4 +214,4 @@ def DeleteTimes(options):
|
||||
|
||||
finally:
|
||||
if pooledConnection is not None:
|
||||
pooledConnection.close()
|
||||
pooledConnection.close()
|
||||
|
||||
Reference in New Issue
Block a user