Files
qt5-legatus-legacy/Lts/Services/NotificationManagement/object_notification.cpp
T
2026-08-13 18:33:10 +02:00

428 lines
16 KiB
C++
Executable File

/**
* NomNotification object
* $Id$
* $HeadURL$
* $Author$
* Created by Hanna E. Rathje, ESZS, 2025-06-23
*/
#include "object_notification.h"
#include "dds_handler.h"
#include <ngldb/dbtransaction.h>
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
namespace NotificationManagement
{
const QString TRANSLATION_ARGS = QStringLiteral("translationsArgs");
const QString CONTENT_ID = QStringLiteral("id");
const QString CONTENT_ARG = QStringLiteral("contentArg");
ObjectNotification::ObjectNotification(const std::shared_ptr<DdsHandler> &ddsHandler, const std::shared_ptr<DatabaseInterface> &db)
: m_ddsHandler(ddsHandler)
, m_db(db)
, m_logger(getLogger("ObjectNotification"))
{
} // end of ctor()
//-----------------------------------------------------------------------------
ObjectNotification::~ObjectNotification() { m_ddsHandler->dts()->removeNomNotificationByKey(m_dataNotificationObject.id()); } // end of dtor()
//-----------------------------------------------------------------------------
Core::FunctionReplyObject ObjectNotification::createObject(const NomNotification &data)
{
m_dataNotificationObject = data;
if (data.id() <= 0)
{
Database::NomNotification dbDataNotification = toDbData(data);
dbDataNotification.timeStamp = QDateTime::currentMSecsSinceEpoch();
DBTransaction trans(m_db->database());
if (!m_db->insert(dbDataNotification))
return Core::FunctionReplyObject(0, tr_lts("dds", "Error inserting NomNotification-data into database"));
// Neue DB Id in lokale Struktur uebernehmen
m_dataNotificationObject.id(dbDataNotification.id);
DEBUG_LOG(m_logger) << "New NotificationId: " << dbDataNotification.id;
DEBUG_LOG(m_logger) << "Handle Address for notificationId:" << dbDataNotification.id << " number of depending recipients: " << data.recipientIds().size();
// Behandlung von Recipients
for (size_t i = 0; i < data.recipientIds().size(); ++i)
{
Address &recipientAddress = m_dataNotificationObject.recipientIds()[i];
Database::NomAddress dbDataRecipientAddr = toDbData(recipientAddress);
// Struct Address vorbereiten
dbDataRecipientAddr.notificationId = dbDataNotification.id; // FK auf NotificationId
dbDataRecipientAddr.id = 0;
dbDataRecipientAddr.isRead = false;
dbDataRecipientAddr.isSender = false;
if (!m_db->insert(dbDataRecipientAddr))
return Core::FunctionReplyObject(0, tr_lts("dds", "Error inserting RecipientAddress-data into database"));
// Neue DB Id in lokale Struktur uebernehmen
recipientAddress.id(dbDataRecipientAddr.id);
}
Address &senderAddress = m_dataNotificationObject.sender();
Database::NomAddress dbDataSenderAddr = toDbData(senderAddress);
// Struct Address vorbereiten
dbDataSenderAddr.notificationId = dbDataNotification.id; // FK auf NotificationId
dbDataSenderAddr.isRead = false;
dbDataSenderAddr.isSender = true;
dbDataSenderAddr.id = 0;
if (!m_db->insert(dbDataSenderAddr))
return Core::FunctionReplyObject(0, tr_lts("dds", "Error inserting SenderAddress-data into database"));
// Neue DB Id in lokale Struktur uebernehmen
senderAddress.id(dbDataSenderAddr.id);
trans.commit();
}
// Publish Data via DTS
onPublishData();
return Core::FunctionReplyObject(m_dataNotificationObject.id());
} // end of createObject()
//-----------------------------------------------------------------------------
QString ObjectNotification::contentArgsToJson()
{
int i = 1;
QJsonArray jsonArray;
for (const std::string& arg : qAsConst(m_dataNotificationObject.contentArgs()))
{
DEBUG_LOG(m_logger) << ".arg() ersetzt immer den kleinsten freien Platzhalter"
<< ", arg=" << arg;
QJsonObject argObj;
argObj[CONTENT_ID] = i;
argObj[CONTENT_ARG] = QString::fromStdString(arg);
jsonArray.append(argObj);
i++;
}
QJsonObject mainObject;
mainObject[TRANSLATION_ARGS] = jsonArray;
QJsonDocument doc(mainObject);
DEBUG_LOG(m_logger) << "ObjectNotification::contentArgsToJson properties=" << QString::fromUtf8(doc.toJson(QJsonDocument::Compact));
return QString::fromUtf8(doc.toJson(QJsonDocument::Compact));
}
std::vector<std::string> ObjectNotification::jsonToContentArgs(const QString &jsonString)
{
//DEBUG_LOG(m_logger) << "jsonToContentArgs jsonString=" << jsonString;
std::vector<std::string> result;
// 1. String parsen
QJsonDocument doc = QJsonDocument::fromJson(jsonString.toUtf8());
if (!doc.isObject()) {
//WARNING_LOG(m_logger) << "properties: Invalid JSON-Object";
return result;
}
QJsonObject hauptObjekt = doc.object();
// 2. Das Array aus "translationsArgs" herausholen
if (!hauptObjekt.contains(TRANSLATION_ARGS) || !hauptObjekt[TRANSLATION_ARGS].isArray()) {
//WARNING_LOG(m_logger) << "Missing or invalid 'translationsArgs' key (must be an array).";
return result;
}
QJsonArray jsonArray = hauptObjekt[TRANSLATION_ARGS].toArray();
for ( int gesuchteId = 1; gesuchteId <= jsonArray.size(); gesuchteId++)
{
// 3. Für schnellen Zugriff nach ID indizieren
QHash<int, QJsonObject> sucheMap;
for (const QJsonValue &wert : qAsConst(jsonArray))
{
QJsonObject obj = wert.toObject();
int id = obj[CONTENT_ID].toInt();
sucheMap[id] = obj;
}
// 4. Zugriff über die ID testen
if (sucheMap.contains(gesuchteId)) {
QJsonObject treffer = sucheMap[gesuchteId];
//DEBUG_LOG(m_logger) << "ID" << gesuchteId << "gefunden!";
//DEBUG_LOG(m_logger) << "Inhalt:" << treffer[CONTENT_ARG].toString();
QString contentStr = treffer[CONTENT_ARG].toString();
result.emplace_back(contentStr.toStdString());
} else {
//qDebug() << "ID" << gesuchteId << "nicht im System.";
}
}
return result;
}
Core::FunctionReplyObject ObjectNotification::readReceipt(const ReadReceipt &data, int notificationId)
{
if (!isValid())
return Core::FunctionReplyObject(notificationId, tr_lts("dds", "Object not valid/blocked"));
Database::NomNotification dbDataNotification = toDbData(m_dataNotificationObject);
Database::NomAddress dbDataAddr;
for (const Address &recipientAddr : qAsConst(m_dataNotificationObject.recipientIds()))
{
if (data.operatorId() > 0 && recipientAddr.addressType() == AddressType_def::Operator && recipientAddr.addressId() != data.operatorId())
continue;
if (data.workstationId() > 0 && recipientAddr.addressType() == AddressType_def::Workstation && recipientAddr.addressId() != data.workstationId())
continue;
dbDataAddr = toDbData(recipientAddr);
DEBUG_LOG(m_logger) << "Found Operator " << data.operatorId() << " with repicpentID " << dbDataAddr.id;
dbDataAddr.notificationId = dbDataNotification.id;
break;
}
if (dbDataAddr.id <= 0)
return Core::FunctionReplyObject(data.addressId(), tr_lts("dds", "No Address found"));
dbDataAddr.isRead = true;
DBTransaction trans(m_db->database());
// NomNotification shall be marked as processed
if (data.processed())
{
// but hasn't been so yet
if (dbDataNotification.processed <= 0)
{
dbDataNotification.processed = dbDataAddr.id;
dbDataNotification.processTime = QDateTime::currentMSecsSinceEpoch();
if (dbDataNotification.priorityId != dbDataNotification.processedPriority)
dbDataNotification.priorityId = dbDataNotification.processedPriority;
if (!m_db->update(dbDataNotification))
return Core::FunctionReplyObject(notificationId, tr_lts("dds", "Error updating notification-data"));
}
else
{
DEBUG_LOG(m_logger) << "Notification already processed id=" << notificationId;
return Core::FunctionReplyObject(dbDataNotification.processed, {}, {}, tr_lts("dds", "Notification already processed"));
}
}
if (!m_db->update(dbDataAddr))
return Core::FunctionReplyObject(dbDataAddr.id, tr_lts("dds", "Error updating address-data into database"));
trans.commit();
INFO_LOG(m_logger) << "Data changed for NotificationId: " << m_dataNotificationObject.id();
const std::vector<Address> recipients = m_dataNotificationObject.recipientIds();
const Address sender = m_dataNotificationObject.sender();
m_dataNotificationObject = toDdsData(dbDataNotification);
m_dataNotificationObject.sender(sender);
for (const Address &addr : qAsConst(recipients))
{
if (addr.id() == dbDataAddr.id)
m_dataNotificationObject.recipientIds().push_back(toDdsData(dbDataAddr));
else
m_dataNotificationObject.recipientIds().push_back(addr);
}
// Publish Data via DTS
onPublishData();
return Core::FunctionReplyObject(m_dataNotificationObject.id());
} // end of updateObject()
//-----------------------------------------------------------------------------
Core::FunctionReplyObject ObjectNotification::deleteMessage(const DeleteMessage &data, int notificationId)
{
if (!isValid())
return Core::FunctionReplyObject(notificationId, tr_lts("dds", "Object not valid/blocked"));
Database::NomNotification dbDataNotification = toDbData(m_dataNotificationObject);
Database::NomAddress dbDataAddr;
for (const Address &recipientAddr : qAsConst(m_dataNotificationObject.recipientIds()))
{
DEBUG_LOG(m_logger) << "recipientAddr="
<< ", id: " << recipientAddr.id() << ", addressId: " << recipientAddr.addressId() << ", isDeleted: " << recipientAddr.isDeleted();
if (data.operatorId() > 0 && recipientAddr.addressType() == AddressType_def::Operator && recipientAddr.addressId() != data.operatorId())
continue;
if (data.workstationId() > 0 && recipientAddr.addressType() == AddressType_def::Workstation && recipientAddr.addressId() != data.workstationId())
continue;
dbDataAddr = toDbData(recipientAddr);
dbDataAddr.notificationId = dbDataNotification.id;
break;
}
if (dbDataAddr.id <= 0)
return Core::FunctionReplyObject(data.addressId(), tr_lts("dds", "No Address found"));
dbDataAddr.isDeleted = true;
DBTransaction trans(m_db->database());
if (!m_db->update(dbDataAddr))
return Core::FunctionReplyObject(dbDataAddr.id, tr_lts("dds", "Error updating address-data into database"));
trans.commit();
INFO_LOG(m_logger) << "Data changed for NotificationId: " << m_dataNotificationObject.id();
std::vector<Address> recipients = m_dataNotificationObject.recipientIds();
Address sender = m_dataNotificationObject.sender();
m_dataNotificationObject = toDdsData(dbDataNotification);
m_dataNotificationObject.sender(sender);
for (const Address &addr : qAsConst(recipients))
{
DEBUG_LOG(m_logger) << "addr="
<< ", id: " << addr.id() << ", addressId: " << addr.addressId() << ", isDeleted: " << addr.isDeleted();
if (addr.id() == dbDataAddr.id)
m_dataNotificationObject.recipientIds().push_back(toDdsData(dbDataAddr));
else
m_dataNotificationObject.recipientIds().push_back(addr);
}
// Publish Data via DTS
onPublishData();
return Core::FunctionReplyObject(m_dataNotificationObject.id());
} // end of updateObject()
//-----------------------------------------------------------------------------
Core::FunctionReplyObject ObjectNotification::deleteObject(const DeleteMessage &data, int notificationId)
{
DEBUG_LOG(m_logger) << "ObjectNotification::deleteObject"
<< ", notificationId: " << notificationId << ", addressId: " << data.addressId() << ", operatorId: " << data.operatorId()
<< ", workstationId: " << data.workstationId();
deleteMessage(data, notificationId);
return Core::FunctionReplyObject(m_dataNotificationObject.id());
}
Core::FunctionReplyObject ObjectNotification::removeObject()
{
if (!m_db->removeNomNotification(m_dataNotificationObject.id()))
return Core::FunctionReplyObject(m_dataNotificationObject.id(), tr_lts("dds", "NomNotification with id %1 can not be removed from DB"))
.arg(m_dataNotificationObject.id());
if (!m_ddsHandler->dts()->removeNomNotificationByKey(m_dataNotificationObject.id()))
return Core::FunctionReplyObject(m_dataNotificationObject.id(), tr_lts("dds", "NomNotification with id %1 can not be removed from DDS"))
.arg(m_dataNotificationObject.id());
return Core::FunctionReplyObject(m_dataNotificationObject.id());
} // end of removeObject()
//-----------------------------------------------------------------------------
bool ObjectNotification::isValid() const { return m_dataNotificationObject.id() > 0; } // end of isValid()
//-----------------------------------------------------------------------------
void ObjectNotification::onPublishData()
{
INFO_LOG(m_logger) << "Publish NomNotification-data to dds notificationId:" << m_dataNotificationObject.id();
if (!m_ddsHandler->dts()->publish(m_dataNotificationObject))
WARNING_LOG(m_logger) << "Error publishing NomNotification-data to dds";
} // end of onPublishData()
//-----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// convert methods
// ----------------------------------------------------------------------------
// NotificationManagement::NomNotification => Database::NomNotification
Database::NomNotification ObjectNotification::toDbData(const NomNotification &ddsData)
{
Database::NomNotification dbData;
dbData.id = ddsData.id();
dbData.exerciseId = ddsData.exerciseId();
dbData.content = QString::fromStdString(ddsData.content());
QString properties = contentArgsToJson();
dbData.properties = properties;
dbData.title = QString::fromStdString(ddsData.title());
dbData.messageType = ddsData.messageType().underlying();
dbData.notificationType = ddsData.notificationType().underlying();
dbData.processTime = ddsData.processTime();
dbData.processed = ddsData.processed();
dbData.processedPriority = ddsData.processedPriority();
dbData.expiryTime = ddsData.expiryTime();
dbData.priorityId = ddsData.priority();
dbData.timeStamp = ddsData.timeStamp();
return dbData;
} // end of toDbData()
//-----------------------------------------------------------------------------
// Database::NomNotification => NotificationManagement::NomNotification
NomNotification ObjectNotification::toDdsData(const Database::NomNotification &dbData)
{
NomNotification ddsData;
ddsData.id(dbData.id);
ddsData.content(dbData.content.toStdString());
std::vector< std::string > contentArgs = jsonToContentArgs(dbData.properties);
ddsData.contentArgs(contentArgs);
ddsData.title(dbData.title.toStdString());
ddsData.messageType(static_cast<NotificationManagement::MessageType::inner_enum>(dbData.messageType));
ddsData.notificationType(static_cast<NotificationManagement::NotificationType::inner_enum>(dbData.notificationType));
ddsData.timeStamp(dbData.timeStamp);
ddsData.priority(dbData.priorityId);
ddsData.exerciseId(dbData.exerciseId);
ddsData.expiryTime(dbData.expiryTime);
ddsData.processTime(dbData.processTime);
ddsData.processed(dbData.processed);
ddsData.processedPriority(dbData.processedPriority.underlying());
return ddsData;
} // end of toDdsData()
//-----------------------------------------------------------------------------
// NotificationManagement::Address => Database::NomAddress
Database::NomAddress ObjectNotification::toDbData(const Address &ddsData)
{
Database::NomAddress dbData;
dbData.id = ddsData.id();
dbData.addressId = ddsData.addressId();
dbData.addressSubId = ddsData.addressSubId();
dbData.addressSubSubId = ddsData.addressSubSubId();
dbData.addressTypeId = ddsData.addressType().underlying();
dbData.isRead = ddsData.isRead();
dbData.isDeleted = ddsData.isDeleted();
dbData.name = QString::fromStdString(ddsData.name());
return dbData;
} // end of toDbData()
//-----------------------------------------------------------------------------
// Database::NomAddress => NotificationManagement::Address
Address ObjectNotification::toDdsData(const Database::NomAddress &dbData)
{
Address ddsData;
ddsData.id(dbData.id);
ddsData.addressType(dbData.addressTypeId);
ddsData.name(dbData.name.toStdString());
ddsData.addressId(dbData.addressId);
ddsData.addressSubId(dbData.addressSubId);
ddsData.addressSubSubId(dbData.addressSubSubId);
ddsData.isRead(dbData.isRead);
ddsData.isDeleted(dbData.isDeleted);
return ddsData;
} // end of toDdsData()
//-----------------------------------------------------------------------------
} // namespace NotificationManagement