fixed some smaller issues
This commit is contained in:
parent
47da3ff475
commit
622ab6b4a3
@ -81,7 +81,7 @@ def SendEmails(email_dict):
|
||||
commands = pydapper.using(pooledConnection)
|
||||
|
||||
conn = smtplib.SMTP(defs.email_credentials["server"], defs.email_credentials["port"])
|
||||
conn.set_debuglevel(1)
|
||||
conn.set_debuglevel(1) # set this to 0 to disable debug output to log
|
||||
conn.ehlo()
|
||||
conn.starttls()
|
||||
conn.ehlo()
|
||||
@ -107,7 +107,10 @@ def SendEmails(email_dict):
|
||||
|
||||
for notification in notifications:
|
||||
|
||||
message_type = defs.message_types[notification.type]
|
||||
message_type = next((x for x in defs.message_types if x["type"] == notification.type), None)
|
||||
if message_type is None:
|
||||
logging.error(f"Message type {notification.type} not found")
|
||||
continue
|
||||
|
||||
with open(os.path.join(current_path,'../msg/notification_element.html'), mode="r", encoding="utf-8") as file:
|
||||
element = file.read()
|
||||
@ -185,21 +188,38 @@ def SendNotifications():
|
||||
|
||||
|
||||
for notification in data:
|
||||
if notification.participant_id not in users_dict:
|
||||
continue
|
||||
users = users_dict[notification.participant_id]
|
||||
for user in users:
|
||||
# send notification to user
|
||||
if user.notify_email:
|
||||
if user not in email_dict:
|
||||
email_dict[user] = []
|
||||
email_dict[user].append(notification)
|
||||
if user.notify_whatsapp:
|
||||
# TBD
|
||||
pass
|
||||
if user.notify_signal:
|
||||
# TBD
|
||||
pass
|
||||
if not notification.participant_id: # no participant defined, this update goes to all participants of this shipcall
|
||||
p_query = "SELECT * from shipcall_participant_map where shipcall_id = ?id?"
|
||||
assigned_participants = commands.query(p_query, model=model.ShipcallParticipantMap, param={"id":notification.shipcall_id})
|
||||
for assigned_participant in assigned_participants:
|
||||
users = users_dict[assigned_participant.participant_id]
|
||||
for user in users:
|
||||
# send notification to user
|
||||
if user.notify_email:
|
||||
if user not in email_dict:
|
||||
email_dict[user] = []
|
||||
email_dict[user].append(notification)
|
||||
if user.notify_whatsapp:
|
||||
# TBD
|
||||
pass
|
||||
if user.notify_signal:
|
||||
# TBD
|
||||
pass
|
||||
else:
|
||||
users = users_dict[notification.participant_id]
|
||||
for user in users:
|
||||
# send notification to user
|
||||
if user.notify_email:
|
||||
if user not in email_dict:
|
||||
email_dict[user] = []
|
||||
email_dict[user].append(notification)
|
||||
if user.notify_whatsapp:
|
||||
# TBD
|
||||
pass
|
||||
if user.notify_signal:
|
||||
# TBD
|
||||
pass
|
||||
|
||||
# mark as sent
|
||||
commands.execute("UPDATE notification SET level = 2 WHERE id = ?id?", param={"id":notification.id})
|
||||
|
||||
@ -273,11 +293,8 @@ def setup_schedule(update_shipcalls_interval_in_minutes:int=60):
|
||||
|
||||
schedule.every().day.at("09:00").do(eval_next_24_hrs)
|
||||
|
||||
SendNotifications()
|
||||
add_function_to_schedule_send_notifications(1)
|
||||
|
||||
# TODO: Add schedule function to evaluate all notifications in level 1 and create actions
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import copy
|
||||
import logging
|
||||
import pydapper
|
||||
import re
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
@ -7,6 +8,7 @@ import datetime
|
||||
from BreCal.database.enums import StatusFlags
|
||||
from BreCal.validators.validation_rule_functions import ValidationRuleFunctions
|
||||
from BreCal.schemas.model import Shipcall
|
||||
from BreCal.local_db import getPoolConnection
|
||||
|
||||
|
||||
class ValidationRules(ValidationRuleFunctions):
|
||||
@ -76,7 +78,7 @@ class ValidationRules(ValidationRuleFunctions):
|
||||
evaluation_states_old = [state_old if not pd.isna(state_old) else 0 for state_old in evaluation_states_old]
|
||||
results = shipcall_df.apply(lambda x: self.evaluate_shipcall_from_df(x), axis=1).values # returns tuple (state, message)
|
||||
|
||||
# unbundle individual results. evaluation_states becomes an integer, violation
|
||||
# unbundle individual results. evaluation_states becomes an integer, violation
|
||||
evaluation_states_new = [StatusFlags(res[0]).value for res in results]
|
||||
violations = [",\r\n".join(res[1]) if len(res[1])>0 else None for res in results]
|
||||
violations = [self.concise_evaluation_message_if_too_long(violation) for violation in violations]
|
||||
@ -84,9 +86,49 @@ class ValidationRules(ValidationRuleFunctions):
|
||||
# build the list of evaluation times ('now', as isoformat)
|
||||
#evaluation_time = self.get_notification_times(evaluation_states_new)
|
||||
|
||||
send_notification = False
|
||||
if evaluation_states_old is not None and evaluation_states_new is not None:
|
||||
if len(evaluation_states_old) == 1 and len(evaluation_states_new) == 1:
|
||||
if evaluation_states_old[0] != evaluation_states_new[0]:
|
||||
pooledConnection = getPoolConnection()
|
||||
commands = pydapper.using(pooledConnection)
|
||||
if evaluation_states_new[0] == 2:
|
||||
match evaluation_states_old[0]:
|
||||
case 0:
|
||||
send_notification = True
|
||||
case 1:
|
||||
send_notification = True
|
||||
if evaluation_states_new[0] == 3:
|
||||
match evaluation_states_old[0]:
|
||||
case 0:
|
||||
send_notification = True
|
||||
case 1:
|
||||
send_notification = True
|
||||
case 2:
|
||||
send_notification = True
|
||||
|
||||
if send_notification:
|
||||
query = "INSERT INTO notification (shipcall_id, type, level, message) VALUES (?shipcall_id?, 3, 0, ?message?)"
|
||||
commands.execute(query, param={"shipcall_id" : int(shipcall_df.index[0]), "message" : violations[0]})
|
||||
|
||||
if evaluation_states_new[0] == 1 and evaluation_states_old[0] != 0: # this resolves the conflict
|
||||
query = "SELECT * from notification where shipcall_id = ?shipcall_id? and type = 3 and level = 0"
|
||||
existing_notification = commands.query(query, param={"shipcall_id" : int(shipcall_df.index[0])})
|
||||
if len(existing_notification) > 0:
|
||||
query = "DELETE from notification where id = ?id?"
|
||||
commands.execute(query, param={"id" : existing_notification[0]["id"]})
|
||||
else:
|
||||
query = "INSERT INTO notification (shipcall_id, type, level) VALUES (?shipcall_id?, 4, 0)"
|
||||
commands.execute(query, param={"shipcall_id" : int(shipcall_df.index[0])})
|
||||
|
||||
pooledConnection.close()
|
||||
|
||||
|
||||
# build the list of 'evaluation_notifications_sent'. The value is 'False', when a notification should be created
|
||||
#evaluation_notifications_sent = self.get_notification_states(evaluation_states_old, evaluation_states_new)
|
||||
|
||||
# TODO: detect evaluation state changes and create notifications
|
||||
|
||||
shipcall_df.loc[:,"evaluation"] = evaluation_states_new
|
||||
shipcall_df.loc[:,"evaluation_message"] = violations
|
||||
#shipcall_df.loc[:,"evaluation_time"] = evaluation_time
|
||||
@ -107,14 +149,14 @@ class ValidationRules(ValidationRuleFunctions):
|
||||
# e.g.: Evaluation message too long. Violated Rules: ['Rule #0001C', 'Rule #0001H', 'Rule #0001F', 'Rule #0001G', 'Rule #0001L', 'Rule #0001M', 'Rule #0001J', 'Rule #0001K']
|
||||
violation = f"Evaluation message too long. Violated Rules: {concise}"
|
||||
return violation
|
||||
|
||||
|
||||
def undefined_method(self) -> str:
|
||||
"""this function should apply the ValidationRules to the respective .shipcall, in regards to .times"""
|
||||
return (StatusFlags.GREEN, False) # (state:str, should_notify:bool)
|
||||
|
||||
|
||||
def determine_notification_state(self, state_old, state_new):
|
||||
"""
|
||||
this method determines state changes in the notification state. When the state increases, a user is notified about it.
|
||||
this method determines state changes in the notification state. When the state increases, a user is notified about it.
|
||||
state order: (NONE = GREEN < YELLOW < RED)
|
||||
"""
|
||||
# identify a state increase
|
||||
@ -123,10 +165,10 @@ class ValidationRules(ValidationRuleFunctions):
|
||||
# when a state increases, a notification must be sent. Thereby, the field should be set to False ({evaluation_notifications_sent})
|
||||
evaluation_notifications_sent = False if bool(should_notify) else None
|
||||
return evaluation_notifications_sent
|
||||
|
||||
|
||||
def identify_notification_state_change(self, state_old, state_new) -> bool:
|
||||
"""
|
||||
determines, whether the observed state change should trigger a notification.
|
||||
determines, whether the observed state change should trigger a notification.
|
||||
internally, this function maps StatusFlags to an integer and determines, if the successor state is more severe than the predecessor.
|
||||
|
||||
state changes trigger a notification in the following cases:
|
||||
@ -136,7 +178,7 @@ class ValidationRules(ValidationRuleFunctions):
|
||||
|
||||
(none -> yellow) or (none -> red)
|
||||
due to the values in the enumeration objects, the states are mapped to provide this function.
|
||||
green=1, yellow=2, red=3, none=1. Hence, critical changes can be observed by simply checking with "greater than".
|
||||
green=1, yellow=2, red=3, none=1. Hence, critical changes can be observed by simply checking with "greater than".
|
||||
|
||||
returns bool, whether a notification should be triggered
|
||||
"""
|
||||
@ -145,12 +187,12 @@ class ValidationRules(ValidationRuleFunctions):
|
||||
state_old = StatusFlags.NONE.value
|
||||
state_old = max(int(state_old), StatusFlags.GREEN.value)
|
||||
return int(state_new) > int(state_old)
|
||||
|
||||
|
||||
def get_notification_times(self, evaluation_states_new)->list[datetime.datetime]:
|
||||
"""# build the list of evaluation times ('now', as isoformat)"""
|
||||
evaluation_times = [datetime.datetime.now().isoformat() for _i in range(len(evaluation_states_new))]
|
||||
return evaluation_times
|
||||
|
||||
|
||||
def get_notification_states(self, evaluation_states_old, evaluation_states_new)->list[bool]:
|
||||
"""# build the list of 'evaluation_notifications_sent'. The value is 'False', when a notification should be created"""
|
||||
evaluation_notifications_sent = [self.determine_notification_state(state_old=int(state_old), state_new=int(state_new)) for state_old, state_new in zip(evaluation_states_old, evaluation_states_new)]
|
||||
@ -160,7 +202,7 @@ class ValidationRules(ValidationRuleFunctions):
|
||||
def inspect_shipcall_evaluation(vr, sql_handler, shipcall_id):
|
||||
"""
|
||||
# debug only!
|
||||
|
||||
|
||||
a simple debugging function, which serves in inspecting an evaluation function for a single shipcall id. It returns the result and all related data.
|
||||
returns: result, shipcall_df (filtered by shipcall id), shipcall, spm (shipcall participant map, filtered by shipcall id), times_df (filtered by shipcall id)
|
||||
"""
|
||||
@ -170,7 +212,7 @@ def inspect_shipcall_evaluation(vr, sql_handler, shipcall_id):
|
||||
result = vr.evaluate(shipcall=shipcall)
|
||||
notification_state = vr.identify_notification_state_change(state_old=int(shipcall.evaluation), state_new=int(result[0]))
|
||||
print(f"Previous state: {int(shipcall.evaluation)}, New State: {result[0]}, Notification State: {notification_state}")
|
||||
|
||||
|
||||
times_df = sql_handler.df_dict.get("times")
|
||||
times_df = times_df.loc[times_df["shipcall_id"]==shipcall_id]
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user