Compare commits

..

1 Commits

Author SHA1 Message Date
joelthomastrenser b5c8b1ee9b Implement review fixes 2026-06-15 14:46:37 +05:30
17 changed files with 264 additions and 241 deletions
@@ -140,6 +140,7 @@
<ClCompile Include="models\User.cpp" /> <ClCompile Include="models\User.cpp" />
<ClCompile Include="services\AuthenticationManagementService.cpp" /> <ClCompile Include="services\AuthenticationManagementService.cpp" />
<ClCompile Include="services\InventoryManagementService.cpp" /> <ClCompile Include="services\InventoryManagementService.cpp" />
<ClCompile Include="services\NotificationManagementService.cpp" />
<ClCompile Include="services\PaymentManagementService.cpp" /> <ClCompile Include="services\PaymentManagementService.cpp" />
<ClCompile Include="services\ServiceManagementService.cpp" /> <ClCompile Include="services\ServiceManagementService.cpp" />
<ClCompile Include="services\UserManagementService.cpp" /> <ClCompile Include="services\UserManagementService.cpp" />
@@ -114,6 +114,9 @@
<ClCompile Include="datastores\DataStore.cpp"> <ClCompile Include="datastores\DataStore.cpp">
<Filter>Source Files\DataStores</Filter> <Filter>Source Files\DataStores</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="services\NotificationManagementService.cpp">
<Filter>Source Files\Services</Filter>
</ClCompile>
<ClCompile Include="core\patterns\Observer.cpp"> <ClCompile Include="core\patterns\Observer.cpp">
<Filter>Source Files\Core\Patterns</Filter> <Filter>Source Files\Core\Patterns</Filter>
</ClCompile> </ClCompile>
@@ -275,8 +278,5 @@
<ClInclude Include="datastores\sharedmemory\SharedMemory.h"> <ClInclude Include="datastores\sharedmemory\SharedMemory.h">
<Filter>Header Files\DataStores\SharedMemory</Filter> <Filter>Header Files\DataStores\SharedMemory</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="datastores\DataStoreLockGuard.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>
@@ -13,4 +13,5 @@ class Observer
{ {
public: public:
virtual ~Observer() = default; virtual ~Observer() = default;
virtual void addNotification(Notification* notification) = 0;
}; };
@@ -230,6 +230,20 @@ util::Map<std::string, TrackedRecord<User>>& DataStore::getUsers()
{ {
auto users = loadRecords<User, SerializedUser>(m_users); auto users = loadRecords<User, SerializedUser>(m_users);
refreshCache(m_userCache, users); refreshCache(m_userCache, users);
auto& notifications = getNotifications();
int numberOfNotifications = m_notificationCache.getSize();
for (int index = 0; index < numberOfNotifications; index++)
{
Notification* notification = notifications.getValueAt(index).data;
const std::string& recipientUserId = notification->getRecipientUserId();
int userIndex = m_userCache.find(recipientUserId);
if (userIndex == -1)
{
throw std::runtime_error("Invalid recipient user ID");
}
User* user = m_userCache.getValueAt(userIndex).data;
user->addNotification(notification);
}
return m_userCache; return m_userCache;
} }
@@ -326,37 +340,6 @@ util::Map<std::string, TrackedRecord<Invoice>>& DataStore::getInvoices()
return m_invoiceCache; return m_invoiceCache;
} }
/*
Function: getObservers
Description: Retrieves observer records from the specified observer mapping
and resolves them to User objects.
Parameters:
- mapping: Observer mapping to read from
Returns:
- util::Map<std::string, User*>: Collection of observer records
Throws:
- std::runtime_error if an observer references an invalid user ID
*/
util::Map<std::string, User*> DataStore::getObservers(MappingInfo& mapping)
{
auto& users = getUsers();
util::Map<std::string, User*> observers;
SharedMemory::ensureLatestMapping(mapping);
size_t recordCount = SharedMemory::getRecordCount(mapping);
for (size_t index = 0; index < recordCount; index++)
{
const SerializedObserver* observer = static_cast<SerializedObserver*>(SharedMemory::getRecordAddress(mapping, index));
int userIndex = users.find(observer->id);
if (userIndex == -1)
{
throw std::runtime_error("Invalid observer user ID");
}
User* user = users.getValueAt(userIndex).data;
observers.insert(user->getId(), user);
}
return observers;
}
/* /*
Function: getServiceManagementObservers Function: getServiceManagementObservers
Description: Retrieves all service management observer records from the datastore. Description: Retrieves all service management observer records from the datastore.
@@ -367,7 +350,7 @@ Returns:
*/ */
util::Map<std::string, User*> DataStore::getServiceManagementObservers() util::Map<std::string, User*> DataStore::getServiceManagementObservers()
{ {
return getObservers(m_serviceManagementObservers); return util::Map<std::string, User*>();
} }
/* /*
@@ -380,7 +363,7 @@ Returns:
*/ */
util::Map<std::string, User*> DataStore::getPaymentManagementObservers() util::Map<std::string, User*> DataStore::getPaymentManagementObservers()
{ {
return getObservers(m_paymentManagementObservers); return util::Map<std::string, User*>();
} }
/* /*
@@ -393,7 +376,7 @@ Returns:
*/ */
util::Map<std::string, User*> DataStore::getInventoryManagementObservers() util::Map<std::string, User*> DataStore::getInventoryManagementObservers()
{ {
return getObservers(m_inventoryManagementObservers); return util::Map<std::string, User*>();
} }
/* /*
@@ -407,6 +390,7 @@ Returns:
void DataStore::saveUsers() void DataStore::saveUsers()
{ {
saveRecords<User, SerializedUser>(m_users, m_userCache); saveRecords<User, SerializedUser>(m_users, m_userCache);
saveNotifications();
} }
/* /*
@@ -494,49 +478,16 @@ void DataStore::saveInvoices()
{ {
} }
/*
Function: saveObservers
Description: Persists observer records to the specified observer mapping.
Parameters:
- mapping: MappingInfo&, observer mapping to save to
- observers: util::Map<std::string, User*>&, collection of observer records
Returns:
- None
*/
void DataStore::saveObservers(MappingInfo& mapping, util::Map<std::string, User*>& observers)
{
size_t observerCount = static_cast<size_t>(observers.getSize());
size_t capacity = config::file::INITIAL_CAPACITY;
while (capacity < observerCount)
{
capacity *= config::file::GROWTH_FACTOR;
}
if (!SharedMemory::resizeMapping(mapping, capacity))
{
throw std::runtime_error("Failed to resize observer mapping");
}
SharedMemory::setRecordCount(mapping, observerCount);
for (size_t index = 0; index < observerCount; index++)
{
SerializedObserver serializedObserver;
User* user = observers.getValueAt(static_cast<int>(index));
strcpy_s(serializedObserver.id, user->getId().c_str());
SerializedObserver* destination = static_cast<SerializedObserver*>(SharedMemory::getRecordAddress(mapping, index));
*destination = serializedObserver;
}
}
/* /*
Function: saveServiceManagementObservers Function: saveServiceManagementObservers
Description: Persists all service management observer records to the datastore. Description: Persists all service management observer records to the datastore.
Parameters: Parameters:
- observers: util::Map<std::string, User*>&, collection of observer records - observers: util::Map<std::string, TrackedRecord<std::string>>&, collection of observer records
Returns: Returns:
- None - None
*/ */
void DataStore::saveServiceManagementObservers(util::Map<std::string, User*>& observers) void DataStore::saveServiceManagementObservers(util::Map<std::string, User*>& observers)
{ {
saveObservers(m_serviceManagementObservers, observers);
} }
/* /*
@@ -549,7 +500,6 @@ Returns:
*/ */
void DataStore::savePaymentManagementObservers(util::Map<std::string, User*>& observers) void DataStore::savePaymentManagementObservers(util::Map<std::string, User*>& observers)
{ {
saveObservers(m_paymentManagementObservers, observers);
} }
/* /*
@@ -562,7 +512,6 @@ Returns:
*/ */
void DataStore::saveInventoryManagementObservers(util::Map<std::string, User*>& observers) void DataStore::saveInventoryManagementObservers(util::Map<std::string, User*>& observers)
{ {
saveObservers(m_inventoryManagementObservers, observers);
} }
/* /*
@@ -86,8 +86,6 @@ private:
void saveRecords(MappingInfo& mapping, util::Map<std::string, TrackedRecord<TObject>>& records); void saveRecords(MappingInfo& mapping, util::Map<std::string, TrackedRecord<TObject>>& records);
template<typename TObject> void clearCache(util::Map<std::string, TrackedRecord<TObject>>&cache); template<typename TObject> void clearCache(util::Map<std::string, TrackedRecord<TObject>>&cache);
template<typename TObject> void refreshCache(util::Map<std::string, TrackedRecord<TObject>>&cache, util::Map<std::string, TrackedRecord<TObject>>&refreshedCache); template<typename TObject> void refreshCache(util::Map<std::string, TrackedRecord<TObject>>&cache, util::Map<std::string, TrackedRecord<TObject>>&refreshedCache);
util::Map<std::string, User*> getObservers(MappingInfo& mapping);
void saveObservers(MappingInfo& mapping, util::Map<std::string, User*>& observers);
}; };
/* /*
@@ -320,7 +320,7 @@ bool SharedMemory::ensureCapacityForInsert(MappingInfo& mapping)
{ {
return true; return true;
} }
return resizeMapping(mapping, capacity * config::file::GROWTH_FACTOR); return resizeMapping(mapping, capacity * 2);
} }
/* /*
@@ -1,13 +1,12 @@
/* /*
File: Notification.cpp File: Notification.cpp
Description: Implements the Notification class which represents system notifications in the Vehicle Service Management System. Description: Implements the Notification class which represents system notifications in the Vehicle Service Management System.
Provides constructors, accessors, and mutators for notification details such as ID, recipientID, title, message, and timestamp. Provides constructors, accessors, and mutators for notification details such as ID, recipient, title, message, and timestamp.
Author: Trenser Author: Trenser
Date: 19-May-2026 Date: 19-May-2026
*/ */
#include <sstream> #include <sstream>
#include "SerializedRecords.h"
#include "Notification.h" #include "Notification.h"
#include "StringHelper.h" #include "StringHelper.h"
#include "Factory.h" #include "Factory.h"
@@ -24,7 +23,7 @@ Returns:
*/ */
Notification::Notification() Notification::Notification()
: m_id("NOT" + std::to_string(++m_uid)), : m_id("NOT" + std::to_string(++m_uid)),
m_state(util::State::ACTIVE) {} m_recipient(nullptr) {}
/* /*
Function: Notification Function: Notification
@@ -38,14 +37,13 @@ Parameters:
Returns: Returns:
- A new Notification object. - A new Notification object.
*/ */
Notification::Notification(const std::string& recipientUserId, const std::string& title, const std::string& message, const util::Timestamp& createdAt) Notification::Notification(const std::string& recipientUserId, User* recipient, const std::string& title, const std::string& message, const util::Timestamp& createdAt)
: m_id("NOT" + std::to_string(++m_uid)), : m_id("NOT" + std::to_string(++m_uid)),
m_recipientUserId(recipientUserId), m_recipientUserId(recipientUserId),
m_recipient(recipient),
m_title(title), m_title(title),
m_message(message), m_message(message),
m_state(util::State::ACTIVE), m_createdAt(createdAt) {}
m_createdAt(createdAt) {
}
/* /*
Function: Notification (parameterized constructor with ID) Function: Notification (parameterized constructor with ID)
@@ -60,13 +58,13 @@ Parameters:
Returns: Returns:
- A new Notification object - A new Notification object
*/ */
Notification::Notification(const std::string& id, const std::string& recipientUserId, const std::string& title, const std::string& message, const util::Timestamp& createdAt, const util::State& state) Notification::Notification(const std::string& id, const std::string& recipientUserId, const std::string& title, const std::string& message, const util::Timestamp& createdAt)
: m_id(id), : m_id(id),
m_recipientUserId(recipientUserId), m_recipientUserId(recipientUserId),
m_recipient(nullptr),
m_title(title), m_title(title),
m_message(message), m_message(message),
m_createdAt(createdAt), m_createdAt(createdAt)
m_state(state)
{ {
int idNumber = util::extractNumber(m_id); int idNumber = util::extractNumber(m_id);
if (idNumber > m_uid) if (idNumber > m_uid)
@@ -97,6 +95,17 @@ const std::string& Notification::getRecipientUserId() const
return m_recipientUserId; return m_recipientUserId;
} }
/*
Function: getRecipient
Description: Retrieves the pointer to the recipient user.
Returns:
- User* representing the recipient.
*/
User* Notification::getRecipient() const
{
return m_recipient;
}
/* /*
Function: getTitle Function: getTitle
Description: Retrieves the title of the notification. Description: Retrieves the title of the notification.
@@ -130,17 +139,6 @@ const util::Timestamp& Notification::getCreatedAt() const
return m_createdAt; return m_createdAt;
} }
/*
Function: getState
Description: Retrieves the Notification state
Returns:
- const util::Timestamp& representing the creation timestamp.
*/
util::State Notification::getState() const
{
return m_state;
}
/* /*
Function: setId Function: setId
Description: Sets the unique ID of the notification. Description: Sets the unique ID of the notification.
@@ -167,6 +165,19 @@ void Notification::setRecipientUserId(const std::string& recipientUserId)
m_recipientUserId = recipientUserId; m_recipientUserId = recipientUserId;
} }
/*
Function: setRecipient
Description: Sets the recipient user pointer for the notification.
Parameters:
- recipient: Pointer to the User object.
Returns:
- void
*/
void Notification::setRecipient(User* recipient)
{
m_recipient = recipient;
}
/* /*
Function: setTitle Function: setTitle
Description: Sets the title of the notification. Description: Sets the title of the notification.
@@ -206,54 +217,71 @@ void Notification::setCreatedAt(const util::Timestamp& createdAt)
m_createdAt = createdAt; m_createdAt = createdAt;
} }
/*
Function: setState
Description: Sets the Notification state.
Parameters:
- state: Notification state value.
Returns:
- void
*/
void Notification::setState(util::State state)
{
m_state = state;
}
/* /*
Function: serialize Function: serialize
Description: Serializes the Notification object into a SerializedNotification record. Description: Serializes the notification into a CSV-formatted string.
Parameters: Parameters:
- None - None
Returns: Returns:
- SerializedNotification: Serialized representation of the notification - std::string: Serialized notification record
*/ */
SerializedNotification Notification::serialize() const std::string Notification::serialize() const
{ {
SerializedNotification serialized = {}; std::ostringstream serializedNotification;
strcpy_s(serialized.id, sizeof(serialized.id), m_id.c_str()); serializedNotification << m_id << ','
strcpy_s(serialized.recipientUserId, sizeof(serialized.recipientUserId), m_recipientUserId.c_str()); << m_recipientUserId << ','
strcpy_s(serialized.title, sizeof(serialized.title), m_title.c_str()); << m_title << ','
strcpy_s(serialized.message, sizeof(serialized.message), m_message.c_str()); << m_message << ','
serialized.createdAt = m_createdAt; << m_createdAt.toString();
serialized.state = m_state; return serializedNotification.str();
return serialized;
} }
/* /*
Function: deserialize Function: deserialize
Description: Deserializes a SerializedNotification record into a Notification object. Description: Deserializes a CSV-formatted string into a Notification object.
Parameters: Parameters:
- serializedNotification: const SerializedNotification&, serialized notification record - record: const std::string&, serialized notification record
Returns: Returns:
- Notification*: Pointer to the deserialized Notification object - Notification*: Pointer to the deserialized Notification object
Throws:
- std::runtime_error if timestamp parsing fails
*/ */
Notification* Notification::deserialize(const SerializedNotification& serializedNotification) Notification* Notification::deserialize(const std::string& record)
{ {
std::string id, recipientUserId, title, message, createdAtTimestampString;
std::istringstream serializedNotification(record);
getline(serializedNotification, id, ',');
getline(serializedNotification, recipientUserId, ',');
getline(serializedNotification, title, ',');
getline(serializedNotification, message, ',');
getline(serializedNotification, createdAtTimestampString, ',');
util::Timestamp createdAtTimestamp;
try
{
createdAtTimestamp = util::Timestamp::fromString(createdAtTimestampString);
}
catch (...)
{
throw std::runtime_error("Invalid createdAt timestamp");
}
return Factory::getObject<Notification>( return Factory::getObject<Notification>(
serializedNotification.id, id,
serializedNotification.recipientUserId, recipientUserId,
serializedNotification.title, title,
serializedNotification.message, message,
serializedNotification.createdAt, createdAtTimestamp
serializedNotification.state); );
}
/*
Function: getHeaders
Description: Retrieves the CSV headers for notification serialization.
Parameters:
- None
Returns:
- std::string: Header string ("ID,RecipientID,Title,Message,Timestamp")
*/
std::string Notification::getHeaders()
{
return "ID,RecipientID,Title,Message,Timestamp";
} }
@@ -9,10 +9,8 @@ Date: 19-May-2026
#pragma once #pragma once
#include <string> #include <string>
#include "Timestamp.h" #include "Timestamp.h"
#include "Enums.h"
class User; class User;
struct SerializedNotification;
class Notification class Notification
{ {
@@ -20,26 +18,27 @@ private:
static int m_uid; static int m_uid;
std::string m_id; std::string m_id;
std::string m_recipientUserId; std::string m_recipientUserId;
User* m_recipient;
std::string m_title; std::string m_title;
std::string m_message; std::string m_message;
util::Timestamp m_createdAt; util::Timestamp m_createdAt;
util::State m_state;
public: public:
Notification(); Notification();
Notification(const std::string& recipientUserId, const std::string& title, const std::string& message, const util::Timestamp& createdAt); Notification(const std::string& recipientUserId, User* recipient, const std::string& title, const std::string& message, const util::Timestamp& createdAt);
Notification(const std::string& id, const std::string& recipientUserId, const std::string& title, const std::string& message, const util::Timestamp& createdAt, const util::State& state); Notification(const std::string& id, const std::string& recipientUserId, const std::string& title, const std::string& message, const util::Timestamp& createdAt);
const std::string& getId() const; const std::string& getId() const;
const std::string& getRecipientUserId() const; const std::string& getRecipientUserId() const;
User* getRecipient() const;
const std::string& getTitle() const; const std::string& getTitle() const;
const std::string& getMessage() const; const std::string& getMessage() const;
const util::Timestamp& getCreatedAt() const; const util::Timestamp& getCreatedAt() const;
void setId(const std::string& id); void setId(const std::string& id);
void setRecipientUserId(const std::string& recipientUserId); void setRecipientUserId(const std::string& recipientUserId);
void setRecipient(User* recipient);
void setTitle(const std::string& title); void setTitle(const std::string& title);
void setMessage(const std::string& message); void setMessage(const std::string& message);
void setCreatedAt(const util::Timestamp& createdAt); void setCreatedAt(const util::Timestamp& createdAt);
util::State getState() const; std::string serialize() const;
void setState(util::State state); static Notification* deserialize(const std::string&);
SerializedNotification serialize() const; static std::string getHeaders();
static Notification* deserialize(const SerializedNotification&);
}; };
@@ -89,6 +89,23 @@ User::User(const std::string& userId, const std::string& userName, const std::st
} }
} }
/*
Function: ~User
Description: Destructor that cleans up dynamically allocated notifications associated with the user.
Parameters:
- None
Returns:
- void
*/
User::~User()
{
auto values = m_notifications.getValues();
for (int index = 0; index < values.getSize(); index++)
{
delete values[index];
}
}
/* /*
Function: getId Function: getId
Description: Retrieves the unique ID of the user. Description: Retrieves the unique ID of the user.
@@ -155,6 +172,17 @@ const std::string& User::getEmail() const
return m_email; return m_email;
} }
/*
Function: getNotifications
Description: Retrieves the map of notifications associated with the user.
Returns:
- util::Map<std::string, Notification*>& representing the notifications.
*/
util::Map<std::string, Notification*>& User::getNotifications()
{
return m_notifications;
}
/* /*
Function: getUserType Function: getUserType
Description: Retrieves the role of the user. Description: Retrieves the role of the user.
@@ -255,6 +283,22 @@ void User::setEmail(const std::string& email)
m_email = email; m_email = email;
} }
/*
Function: addNotification
Description: Adds a new notification to the users notification map.
Parameters:
- notification: Pointer to the Notification object.
Returns:
- void
*/
void User::addNotification(Notification* notification)
{
if (notification)
{
m_notifications.insert(notification->getId(), notification);
}
}
/* /*
Function: setRole Function: setRole
Description: Sets the role of the user. Description: Sets the role of the user.
@@ -26,19 +26,21 @@ private:
std::string m_name; std::string m_name;
std::string m_phone; std::string m_phone;
std::string m_email; std::string m_email;
util::Map<std::string, Notification*> m_notifications;
util::UserType m_type; util::UserType m_type;
util::State m_status; util::State m_status;
public: public:
User(); User();
User(const std::string& userName, const std::string& password, const std::string& name, const std::string& phone, const std::string& email, util::UserType role); User(const std::string& userName, const std::string& password, const std::string& name, const std::string& phone, const std::string& email, util::UserType role);
User(const std::string& userId, const std::string& userName, const std::string& password, const std::string& name, const std::string& phone, const std::string& email, util::UserType role, util::State status); User(const std::string& userId, const std::string& userName, const std::string& password, const std::string& name, const std::string& phone, const std::string& email, util::UserType role, util::State status);
~User() = default; ~User();
const std::string& getId() const; const std::string& getId() const;
const std::string& getUserName() const; const std::string& getUserName() const;
const std::string& getPassword() const; const std::string& getPassword() const;
const std::string& getName() const; const std::string& getName() const;
const std::string& getPhone() const; const std::string& getPhone() const;
const std::string& getEmail() const; const std::string& getEmail() const;
util::Map<std::string, Notification*>& getNotifications();
util::UserType getUserType() const; util::UserType getUserType() const;
util::State getState() const; util::State getState() const;
void setId(const std::string& id); void setId(const std::string& id);
@@ -47,6 +49,7 @@ public:
void setName(const std::string& name); void setName(const std::string& name);
void setPhone(const std::string& phone); void setPhone(const std::string& phone);
void setEmail(const std::string& email); void setEmail(const std::string& email);
void addNotification(Notification* notification) override;
void setRole(util::UserType role); void setRole(util::UserType role);
void setState(util::State status); void setState(util::State status);
SerializedUser serialize() const; SerializedUser serialize() const;
@@ -19,7 +19,7 @@ Date: 22-May-2026
#include "User.h" #include "User.h"
#include "Utility.h" #include "Utility.h"
#include "Vector.h" #include "Vector.h"
#include "DataStoreLockGuard.h"
util::Map<std::string, User*> InventoryManagementService::m_observers{}; util::Map<std::string, User*> InventoryManagementService::m_observers{};
@@ -271,9 +271,6 @@ Returns:
*/ */
void InventoryManagementService::attach(User* user) void InventoryManagementService::attach(User* user)
{ {
DataStoreLockGuard lock(m_dataStore);
m_observers.clear();
m_observers = m_dataStore.getInventoryManagementObservers();
if (user) if (user)
{ {
const std::string& userID = user->getId(); const std::string& userID = user->getId();
@@ -282,7 +279,6 @@ void InventoryManagementService::attach(User* user)
m_observers[userID] = user; m_observers[userID] = user;
} }
} }
m_dataStore.saveInventoryManagementObservers(m_observers);
} }
/* /*
@@ -295,9 +291,6 @@ Returns:
*/ */
void InventoryManagementService::detach(User* user) void InventoryManagementService::detach(User* user)
{ {
DataStoreLockGuard lock(m_dataStore);
m_observers.clear();
m_observers = m_dataStore.getInventoryManagementObservers();
if (user) if (user)
{ {
const std::string& userID = user->getId(); const std::string& userID = user->getId();
@@ -306,7 +299,6 @@ void InventoryManagementService::detach(User* user)
m_observers.remove(userID); m_observers.remove(userID);
} }
} }
m_dataStore.saveInventoryManagementObservers(m_observers);
} }
/* /*
@@ -323,27 +315,27 @@ Throws:
*/ */
void InventoryManagementService::sendNotification(User* user, const std::string& title, const std::string& message) void InventoryManagementService::sendNotification(User* user, const std::string& title, const std::string& message)
{ {
if (!user) if (user)
{ {
return; if (m_observers.find(user->getId()) != -1)
{
Notification* notification =
Factory::getObject<Notification>(
user->getId(),
user,
title,
message,
util::Timestamp()
);
if (notification)
{
user->addNotification(notification);
}
else
{
throw std::runtime_error("Failed to create notification");
}
}
} }
DataStoreLockGuard lock(m_dataStore);
m_observers = m_dataStore.getInventoryManagementObservers();
if (m_observers.find(user->getId()) == -1)
{
return;
}
Notification* notification = Factory::getObject<Notification>(
user->getId(),
title,
message,
util::Timestamp());
if (!notification)
{
throw std::runtime_error("Failed to create notification");
}
auto& trackedNotificationsMap = m_dataStore.getNotifications();
trackedNotificationsMap.insert(notification->getId(), util::createNewRecord(notification));
m_dataStore.saveNotifications();
} }
@@ -0,0 +1 @@
#include "NotificationManagementService.h"
@@ -21,7 +21,6 @@ Date: 20-May-2026
#include "Timestamp.h" #include "Timestamp.h"
#include "User.h" #include "User.h"
#include "Utility.h" #include "Utility.h"
#include "DataStoreLockGuard.h"
util::Map<std::string, User*> PaymentManagementService::m_observers{}; util::Map<std::string, User*> PaymentManagementService::m_observers{};
@@ -35,9 +34,6 @@ Returns:
*/ */
void PaymentManagementService::attach(User* user) void PaymentManagementService::attach(User* user)
{ {
DataStoreLockGuard lock(m_dataStore);
m_observers.clear();
m_observers = m_dataStore.getPaymentManagementObservers();
if (user) if (user)
{ {
const std::string& userID = user->getId(); const std::string& userID = user->getId();
@@ -46,7 +42,6 @@ void PaymentManagementService::attach(User* user)
m_observers[userID] = user; m_observers[userID] = user;
} }
} }
m_dataStore.savePaymentManagementObservers(m_observers);
} }
/* /*
@@ -59,9 +54,6 @@ Returns:
*/ */
void PaymentManagementService::detach(User* user) void PaymentManagementService::detach(User* user)
{ {
DataStoreLockGuard lock(m_dataStore);
m_observers.clear();
m_observers = m_dataStore.getPaymentManagementObservers();
if (user) if (user)
{ {
const std::string& userID = user->getId(); const std::string& userID = user->getId();
@@ -70,7 +62,6 @@ void PaymentManagementService::detach(User* user)
m_observers.remove(userID); m_observers.remove(userID);
} }
} }
m_dataStore.savePaymentManagementObservers(m_observers);
} }
/* /*
@@ -87,28 +78,28 @@ Throws:
*/ */
void PaymentManagementService::sendNotification(User* user, const std::string& title, const std::string& message) void PaymentManagementService::sendNotification(User* user, const std::string& title, const std::string& message)
{ {
if (!user) if (user)
{ {
return; if (m_observers.find(user->getId()) != -1)
{
Notification* notification =
Factory::getObject<Notification>(
user->getId(),
user,
title,
message,
util::Timestamp()
);
if (notification)
{
user->addNotification(notification);
}
else
{
throw std::runtime_error("Failed to create notification");
}
}
} }
DataStoreLockGuard lock(m_dataStore);
m_observers = m_dataStore.getPaymentManagementObservers();
if (m_observers.find(user->getId()) == -1)
{
return;
}
Notification* notification = Factory::getObject<Notification>(
user->getId(),
title,
message,
util::Timestamp());
if (!notification)
{
throw std::runtime_error("Failed to create notification");
}
auto& trackedNotificationsMap = m_dataStore.getNotifications();
trackedNotificationsMap.insert(notification->getId(), util::createNewRecord(notification));
m_dataStore.saveNotifications();
} }
/* /*
@@ -26,7 +26,6 @@ Date:19-May-2026
#include "User.h" #include "User.h"
#include "UserManagementService.h" #include "UserManagementService.h"
#include "Utility.h" #include "Utility.h"
#include "DataStoreLockGuard.h"
/* /*
Function: purchaseService Function: purchaseService
@@ -123,9 +122,6 @@ Returns:
*/ */
void ServiceManagementService::attach(User* user) void ServiceManagementService::attach(User* user)
{ {
DataStoreLockGuard lock(m_dataStore);
m_observers.clear();
m_observers = m_dataStore.getServiceManagementObservers();
if (user) if (user)
{ {
const std::string& userID = user->getId(); const std::string& userID = user->getId();
@@ -134,7 +130,6 @@ void ServiceManagementService::attach(User* user)
m_observers[userID] = user; m_observers[userID] = user;
} }
} }
m_dataStore.saveServiceManagementObservers(m_observers);
} }
/* /*
@@ -147,9 +142,6 @@ Returns:
*/ */
void ServiceManagementService::detach(User* user) void ServiceManagementService::detach(User* user)
{ {
DataStoreLockGuard lock(m_dataStore);
m_observers.clear();
m_observers = m_dataStore.getServiceManagementObservers();
if (user) if (user)
{ {
const std::string& userID = user->getId(); const std::string& userID = user->getId();
@@ -158,7 +150,6 @@ void ServiceManagementService::detach(User* user)
m_observers.remove(userID); m_observers.remove(userID);
} }
} }
m_dataStore.saveServiceManagementObservers(m_observers);
} }
/* /*
@@ -175,28 +166,52 @@ Throws:
*/ */
void ServiceManagementService::sendNotification(User* user, const std::string& title, const std::string& message) void ServiceManagementService::sendNotification(User* user, const std::string& title, const std::string& message)
{ {
if (!user) if (user)
{ {
return; if (m_observers.find(user->getId()) != -1)
} {
DataStoreLockGuard lock(m_dataStore); Notification* notification =
m_observers = m_dataStore.getServiceManagementObservers(); Factory::getObject<Notification>(
if (m_observers.find(user->getId()) == -1) user->getId(),
{ user,
return; title,
} message,
Notification* notification = Factory::getObject<Notification>( util::Timestamp()
user->getId(), );
title, if (notification)
message, {
util::Timestamp()); user->addNotification(notification);
if (!notification) }
{ else
throw std::runtime_error("Failed to create notification"); {
} throw std::runtime_error("Failed to create notification");
auto& trackedNotificationsMap = m_dataStore.getNotifications(); }
trackedNotificationsMap.insert(notification->getId(), util::createNewRecord(notification)); }
m_dataStore.saveNotifications(); }
}
/*
Function: getObserverIDs
Description: Retrieves the IDs of all observers currently attached to the
ServiceManagementService.
Parameters:
- None
Returns:
- util::Vector<std::string>: Vector of observer user IDs
*/
util::Vector<std::string> ServiceManagementService::getObserverIDs()
{
util::Vector<std::string> observerIDs;
int numberOfObservers = m_observers.getSize();
for (int index = 0; index < numberOfObservers; index++)
{
User* observer = m_observers.getValueAt(index);
if (observer)
{
observerIDs.push_back(observer->getId());
}
}
return observerIDs;
} }
/* /*
@@ -53,4 +53,6 @@ public:
void saveServiceBookings(); void saveServiceBookings();
void loadJobCards(); void loadJobCards();
void saveJobCards(); void saveJobCards();
void loadObservers();
void saveObservers();
}; };
@@ -170,18 +170,13 @@ util::Vector<Notification*> UserManagementService::getUserNotifications(const st
User* user = trackedUsersMap[userID].data; User* user = trackedUsersMap[userID].data;
if (user) if (user)
{ {
auto& trackedNotificationMap = m_dataStore.getNotifications(); auto& notifications = user->getNotifications();
int numberOfNotifications = trackedNotificationMap.getSize(); int numberOfNotifications = notifications.getSize();
util::Vector<Notification*> notificationsVector; util::Vector<Notification*> notificationsVector;
for (int index = 0; index < numberOfNotifications; index++) for (int index = 0; index < numberOfNotifications; index++)
{ {
Notification* notification = trackedNotificationMap.getValueAt(index).data; notificationsVector.push_back(notifications.getValueAt(index));
if (notification->getRecipientUserId() == userID && notification->getState() == util::State::ACTIVE)
{
notificationsVector.push_back(notification);
}
} }
m_dataStore.unlockDataStore();
return notificationsVector; return notificationsVector;
} }
else else
@@ -214,12 +209,17 @@ void UserManagementService::deleteNotification(const std::string& notificationID
throw std::runtime_error("No user found with given UserID"); throw std::runtime_error("No user found with given UserID");
} }
User* user = trackedUsersMap.getValueAt(userIndex).data; User* user = trackedUsersMap.getValueAt(userIndex).data;
auto& notifications = user->getNotifications();
if (notifications.find(notificationID) == -1)
{
throw std::runtime_error("No notification found with given NotificationID");
}
int notificationIndex = trackedNotificationsMap.find(notificationID); int notificationIndex = trackedNotificationsMap.find(notificationID);
if (notificationIndex == -1) if (notificationIndex == -1)
{ {
throw std::runtime_error("No notification found with given NotificationID"); throw std::runtime_error("No notification found with given NotificationID");
} }
trackedNotificationsMap.getValueAt(notificationIndex).data->setState(util::State::INACTIVE); notifications[notificationID]->setState(util::State::INACTIVE);
trackedNotificationsMap.getValueAt(notificationIndex).state = RecordState::MODIFIED; trackedNotificationsMap.getValueAt(notificationIndex).state = RecordState::MODIFIED;
m_dataStore.saveNotifications(); m_dataStore.saveNotifications();
} }
@@ -29,7 +29,6 @@ namespace config
namespace file namespace file
{ {
const size_t INITIAL_CAPACITY = 100; const size_t INITIAL_CAPACITY = 100;
const size_t GROWTH_FACTOR = 2;
constexpr const char* DIRECTORY = "files/"; constexpr const char* DIRECTORY = "files/";
constexpr const char* INVENTORYITEM_FILE = "files/InventoryItem.dat"; constexpr const char* INVENTORYITEM_FILE = "files/InventoryItem.dat";
constexpr const char* USER_FILE = "files/User.dat"; constexpr const char* USER_FILE = "files/User.dat";