diff --git a/misc/notification_element.html b/misc/notification_element.html
new file mode 100644
index 0000000..154cf8b
--- /dev/null
+++ b/misc/notification_element.html
@@ -0,0 +1,15 @@
+
+
+ | |
+
+
+
+
+
+
+
+
+
+ |
+ Hallo,
+ Sie erhalten eine oder mehrere Benachrichtigungen von Bremen calling:
+
+
+
+ Wenn Sie diese E-Mails nicht länger erhalten wollen, loggen Sie sich bitte in der Bremen Calling App ein. Im Bereich "Passwort ändern"
+ können Sie auch die Benachrichtungen anpassen.
+
+ |
+
+
+
+
+
+
+
+
+
+
+
+ |
+ |
+
+
+
+
diff --git a/src/server/BreCal/impl/shipcalls.py b/src/server/BreCal/impl/shipcalls.py
index 3fe6c2c..efe03bd 100644
--- a/src/server/BreCal/impl/shipcalls.py
+++ b/src/server/BreCal/impl/shipcalls.py
@@ -8,8 +8,8 @@ from .. import local_db
from ..services.auth_guard import check_jwt
from BreCal.database.update_database import evaluate_shipcall_state
-from BreCal.database.sql_utils import get_notification_for_shipcall_and_type
-from BreCal.database.sql_queries import create_sql_query_shipcall_get, create_sql_query_shipcall_post, create_sql_query_shipcall_put, create_sql_query_history_post, create_sql_query_history_put, SQLQuery
+from BreCal.database.sql_utils import get_notification_for_shipcall_and_type, get_ship_data_for_id
+from BreCal.database.sql_queries import create_sql_query_shipcall_get
from marshmallow import Schema, fields, ValidationError
from BreCal.validators.validation_error import create_validation_error_response
@@ -76,6 +76,7 @@ def PostShipcalls(schemaModel):
commands = pydapper.using(pooledConnection)
# query = SQLQuery.get_shipcall_post(schemaModel) # create_sql_query_shipcall_post(schemaModel)
+
query = "INSERT INTO shipcall ("
isNotFirst = False
for key in schemaModel.keys():
@@ -134,15 +135,26 @@ def PostShipcalls(schemaModel):
# new_id = commands.execute_scalar(lquery)
new_id = commands.execute_scalar("select last_insert_id()")
+ shipdata = get_ship_data_for_id(schemaModel["ship_id"])
+ message = {shipdata['name']}
+ if "type_value" in schemaModel:
+ match schemaModel["type_value"]:
+ case 1:
+ message += " [ARRIVAL]"
+ case 2:
+ message += " [DEPARTURE]"
+ case 3:
+ message += " [SHIFTING]"
+
# add participant assignments if we have a list of participants
if 'participants' in schemaModel:
# pquery = SQLQuery.get_shipcall_post_update_shipcall_participant_map()
pquery = "INSERT INTO shipcall_participant_map (shipcall_id, participant_id, type) VALUES (?shipcall_id?, ?participant_id?, ?type?)"
- nquery = "INSERT INTO notification (shipcall_id, participant_id, level, type) VALUES (?shipcall_id?, ?participant_id?, 0, 1)" # type = 1 is assignment
+ nquery = "INSERT INTO notification (shipcall_id, participant_id, level, type, message) VALUES (?shipcall_id?, ?participant_id?, 0, 1, ?message?)" # type = 1 is assignment
for participant_assignment in schemaModel["participants"]:
commands.execute(pquery, param={"shipcall_id" : new_id, "participant_id" : participant_assignment["participant_id"], "type" : participant_assignment["type"]})
- commands.execute(nquery, param={"shipcall_id" : new_id, "participant_id" : participant_assignment["participant_id"]})
+ commands.execute(nquery, param={"shipcall_id" : new_id, "participant_id" : participant_assignment["participant_id"], "message" : message})
# apply 'Traffic Light' evaluation to obtain 'GREEN', 'YELLOW' or 'RED' evaluation state. The function internally updates the mysql database
# evaluate_shipcall_state(mysql_connector_instance=pooledConnection, shipcall_id=new_id) # new_id (last insert id) refers to the shipcall id
@@ -189,8 +201,7 @@ def PutShipcalls(schemaModel):
# test if object to update is found
sentinel = object()
- # query = SQLQuery.get_shipcall_by_id()
- # theshipcall = commands.query_single_or_default(query, sentinel, param={"id" : schemaModel["id"]})
+
theshipcall = commands.query_single_or_default("SELECT * FROM shipcall where id = ?id?", sentinel, param={"id" : schemaModel["id"]})
if theshipcall is sentinel:
pooledConnection.close()
@@ -230,6 +241,17 @@ def PutShipcalls(schemaModel):
affected_rows = commands.execute(query, param=schemaModel)
+ shipdata = get_ship_data_for_id(schemaModel["ship_id"])
+ message = {shipdata['name']}
+ if "type_value" in schemaModel:
+ match schemaModel["type_value"]:
+ case 1:
+ message += " [ARRIVAL]"
+ case 2:
+ message += " [DEPARTURE]"
+ case 3:
+ message += " [SHIFTING]"
+
# pquery = SQLQuery.get_shipcall_participant_map_by_shipcall_id()
pquery = "SELECT id, participant_id, type FROM shipcall_participant_map where shipcall_id = ?id?"
pdata = commands.query(pquery,param={"id" : schemaModel["id"]}) # existing list of assignments
@@ -256,8 +278,8 @@ def PutShipcalls(schemaModel):
found_notification = True
break
if not found_notification:
- nquery = "INSERT INTO notification (shipcall_id, participant_id, level, type) VALUES (?shipcall_id?, ?participant_id?, 0, 1)" # type = 1 is assignment
- commands.execute(nquery, param={"shipcall_id" : schemaModel["id"], "participant_id" : participant_assignment["participant_id"]})
+ nquery = "INSERT INTO notification (shipcall_id, participant_id, level, type, message) VALUES (?shipcall_id?, ?participant_id?, 0, 1, ?message?)" # type = 1 is assignment
+ commands.execute(nquery, param={"shipcall_id" : schemaModel["id"], "participant_id" : participant_assignment["participant_id"], "message" : message})
# loop across existing pdata entries, deleting those not present in participant list
for elem in pdata:
@@ -278,8 +300,8 @@ def PutShipcalls(schemaModel):
commands.execute(nquery, param={"nid" : existing_notification["id"]})
else:
# create un-assignment notification
- nquery = "INSERT INTO notification (shipcall_id, participant_id, level, type) VALUES (?shipcall_id?, ?participant_id?, 0, 5)"
- commands.execute(nquery, param={"shipcall_id" : schemaModel["id"], "participant_id" : elem["participant_id"]})
+ nquery = "INSERT INTO notification (shipcall_id, participant_id, level, type, message) VALUES (?shipcall_id?, ?participant_id?, 0, 5, ?message?)"
+ commands.execute(nquery, param={"shipcall_id" : schemaModel["id"], "participant_id" : elem["participant_id"], "message" : message})
break
# save history data
diff --git a/src/server/BreCal/local_db.py b/src/server/BreCal/local_db.py
index 08846e4..f6e04f7 100644
--- a/src/server/BreCal/local_db.py
+++ b/src/server/BreCal/local_db.py
@@ -4,8 +4,7 @@ import logging
import json
import os
import sys
-import schemas.defs as defs
-
+from BreCal.schemas import defs
config_path = None
def initPool(instancePath, connection_filename="connection_data_devel.json"):
@@ -14,7 +13,7 @@ def initPool(instancePath, connection_filename="connection_data_devel.json"):
if(config_path == None):
config_path = os.path.join(instancePath,f'../../../secure/{connection_filename}') #connection_data_devel.json');
- config_path = "E:/temp/connection_data.json"
+ config_path = "C:/temp/connection_data_devel.json"
print (config_path)
if not os.path.exists(config_path):
@@ -35,9 +34,13 @@ def initPool(instancePath, connection_filename="connection_data_devel.json"):
credentials_file = "email_credentials_devel.json"
credentials_path = os.path.join(instancePath,f'../../../secure/{credentials_file}')
+
+ credentials_path = "C:/temp/email_credentials_devel.json"
+
if not os.path.exists(credentials_path):
print ('cannot find ' + os.path.abspath(credentials_path))
sys.exit(1)
+
f = open(credentials_path);
defs.email_credentials = json.load(f)
f.close()
diff --git a/src/server/BreCal/schemas/model.py b/src/server/BreCal/schemas/model.py
index 4ce7603..5f07741 100644
--- a/src/server/BreCal/schemas/model.py
+++ b/src/server/BreCal/schemas/model.py
@@ -552,6 +552,9 @@ class User:
created: datetime
modified: datetime
+ def __hash__(self):
+ return hash(id)
+
@dataclass
class Ship:
id: int
diff --git a/src/server/BreCal/services/schedule_routines.py b/src/server/BreCal/services/schedule_routines.py
index 401e9f4..fe6d9db 100644
--- a/src/server/BreCal/services/schedule_routines.py
+++ b/src/server/BreCal/services/schedule_routines.py
@@ -61,7 +61,7 @@ def UpdateNotifications():
pooledConnection = getPoolConnection()
commands = pydapper.using(pooledConnection)
- query = "SELECT * FROM notification WHERE level = 0 AND created < DATE(NOW() - INTERVAL 10 MINUTE)"
+ query = "SELECT * FROM notification WHERE level = 0 AND created < TIMESTAMP(NOW() - INTERVAL 10 MINUTE)"
data = commands.query(query, model=model.Notification)
for notification in data:
commands.execute("UPDATE notification SET level = 1 WHERE id = ?id?", param={"id":notification.id})
@@ -75,7 +75,7 @@ def SendEmails(email_dict):
This function sends emails to all users in the emaildict
"""
try:
- conn = smtplib.SMTP_SSL(defs.email_credentials["server"], defs.email_credentials["port"])
+ conn = smtplib.SMTP(defs.email_credentials["server"], defs.email_credentials["port"])
conn.set_debuglevel(1)
conn.ehlo()
conn.starttls()
@@ -91,12 +91,13 @@ def SendEmails(email_dict):
# TODO: pretty-print and format message according to template
msg.set_content(message)
- conn.sendmail(user.user_email, user.user_email, msg.as_string())
+ conn.sendmail(defs.email_credentials["sender"], user.user_email, msg.as_string())
except Exception as ex:
logging.error(ex)
finally:
- conn.quit()
+ if conn is not None:
+ conn.quit()
def SendNotifications():
@@ -134,22 +135,24 @@ def SendNotifications():
for user in users:
# send notification to user
if user.notify_email:
+ if user not in email_dict:
+ email_dict[user] = ""
match notification.type:
case 1: # assignment
email_dict[user] += "\n"
- email_dict[user] += "You have been assigned to a new shipcall: " + notification.message
+ email_dict[user] += "You have been assigned to a new shipcall: " + str(notification.message or "")
case 2: # next 24 hours
email_dict[user] += "\n"
- email_dict[user] += "A shipcall is scheduled for the next 24 hours: " + notification.message
+ email_dict[user] += "A shipcall is scheduled for the next 24 hours: " + str(notification.message or "")
case 3: # Time conflict
email_dict[user] += "\n"
- email_dict[user] += "There is a time conflict in a shipcall: " + notification.message
+ email_dict[user] += "There is a time conflict in a shipcall: " + str(notification.message or "")
case 4: # Time conflict resolved
email_dict[user] += "\n"
- email_dict[user] += "A time conflict in a shipcall has been resolved: " + notification.message
+ email_dict[user] += "A time conflict in a shipcall has been resolved: " + str(notification.message or "")
case 5: # unassigned
email_dict[user] += "\n"
- email_dict[user] += "You have been unassigned from a shipcall: " + notification.message
+ email_dict[user] += "You have been unassigned from a shipcall: " + str(notification.message or "")
if user.notify_whatsapp:
# TBD
pass
@@ -161,10 +164,13 @@ def SendNotifications():
# send emails (if any)
if len(email_dict) > 0:
- SendEmails(email_dict)
+ SendEmails(email_dict)
except Exception as ex:
logging.error(ex)
+ finally:
+ if pooledConnection is not None:
+ pooledConnection.close()
def add_function_to_schedule__update_shipcalls(interval_in_minutes:int, options:dict={'past_days':2}):
kwargs_ = {"options":options}
@@ -207,6 +213,10 @@ def eval_next_24_hrs():
except Exception as ex:
logging.error(ex)
+ finally:
+ if pooledConnection is not None:
+ pooledConnection.close()
+
return
def setup_schedule(update_shipcalls_interval_in_minutes:int=60):