Merged PR 1166: User Management Refactoring - 1925

User Story #1959
User Story #1960

**Changes**
- Refactored User serialization/deserialization to use SerializedUser.
- Removed user loading and saving responsibilities from UserManagementService.
- Added DataStoreLockGuard for automatic datastore locking/unlocking.
- Updated user operations to work with tracked records.
- Added persistence support for user creation, updates, notification changes, and user removal.
- Refactored notification handling to use datastore-managed notifications.
- Updated DataStore to load and save users and notifications using shared memory records.
- Reworked application startup and shutdown flow using Controller::initialize() and Controller::shutdown().
- Updated UI flow to use the new initialization and shutdown methods.
- Added required project and shared memory updates to support the refactoring.

Related work items: #1925, #1959, #1960
This commit is contained in:
2026-06-15 15:16:15 +05:30
11 changed files with 195 additions and 208 deletions
@@ -157,6 +157,7 @@
<ClInclude Include="core\patterns\Observer.h" /> <ClInclude Include="core\patterns\Observer.h" />
<ClInclude Include="core\patterns\Subject.h" /> <ClInclude Include="core\patterns\Subject.h" />
<ClInclude Include="datastores\DataStore.h" /> <ClInclude Include="datastores\DataStore.h" />
<ClInclude Include="datastores\DataStoreLockGuard.h" />
<ClInclude Include="datastores\sharedmemory\FileHeader.h" /> <ClInclude Include="datastores\sharedmemory\FileHeader.h" />
<ClInclude Include="datastores\sharedmemory\MappingInfo.h" /> <ClInclude Include="datastores\sharedmemory\MappingInfo.h" />
<ClInclude Include="datastores\sharedmemory\RecordState.h" /> <ClInclude Include="datastores\sharedmemory\RecordState.h" />
@@ -588,63 +588,37 @@ void Controller::configureNotifications(bool paymentNotifications, bool serviceN
} }
/* /*
Function: loadSystemData Function: initialize
Description: Loads all system data from persistent storage into memory. Description: Initializes the system and run system checks to ensure critical configurations, such as verifying admin existence.
Invokes the respective management services to load users, inventory items, services,
combo packages, service bookings, job cards, invoices, and observers.
Parameters: Parameters:
- None - None
Returns: Returns:
- void - bool
*/ */
void Controller::loadSystemData() bool Controller::initialize()
{ {
m_userManagementService.loadUsers(); auto& dataStore = DataStore::getInstance();
m_inventoryManagementService.loadInventoryItems();
m_serviceManagementService.loadServices();
m_serviceManagementService.loadComboPackages();
m_serviceManagementService.loadServiceBookings();
m_serviceManagementService.loadJobCards();
m_paymentManagementService.loadInvoices();
m_serviceManagementService.loadObservers();
m_paymentManagementService.loadObservers();
m_inventoryManagementService.loadObservers();
}
/* if (!dataStore.initialize())
Function: saveSystemData
Description: Saves all system data from memory back to persistent storage.
Invokes the respective management services to save users, inventory items, services,
combo packages, service bookings, job cards, invoices, and observers.
Parameters:
- None
Returns:
- void
*/
void Controller::saveSystemData()
{ {
m_userManagementService.saveUsers(); return false;
m_inventoryManagementService.saveInventoryItems();
m_serviceManagementService.saveServices();
m_serviceManagementService.saveComboPackages();
m_serviceManagementService.saveServiceBookings();
m_serviceManagementService.saveJobCards();
m_paymentManagementService.saveInvoices();
m_serviceManagementService.saveObservers();
m_paymentManagementService.saveObservers();
m_inventoryManagementService.saveObservers();
} }
/*
Function: runSystemChecks
Description: Runs system checks to ensure critical configurations, such as verifying admin existence.
Parameter: None
Return type: void
*/
void Controller::runSystemChecks()
{
m_userManagementService.ensureAdminExists(); m_userManagementService.ensureAdminExists();
m_inventoryManagementService.sendLowStockAlerts(); m_inventoryManagementService.sendLowStockAlerts();
m_paymentManagementService.sendPaymentReminders(); m_paymentManagementService.sendPaymentReminders();
return true;
} }
/*
Function: shutdown
Description: Shutdown the system, and do necessary cleanups
Parameters:
- None
Returns:
- void
*/
void Controller::shutdown()
{
auto& dataStore = DataStore::getInstance();
dataStore.shutdown();
}
@@ -70,7 +70,6 @@ public:
util::Vector<const Notification*> getNotifications(); util::Vector<const Notification*> getNotifications();
void deleteNotification(const std::string& notificationID); void deleteNotification(const std::string& notificationID);
void configureNotifications(bool paymentNotifications, bool serviceNotifications); void configureNotifications(bool paymentNotifications, bool serviceNotifications);
void loadSystemData(); bool initialize();
void saveSystemData(); void shutdown();
void runSystemChecks();
}; };
@@ -228,6 +228,22 @@ Returns:
*/ */
util::Map<std::string, TrackedRecord<User>>& DataStore::getUsers() util::Map<std::string, TrackedRecord<User>>& DataStore::getUsers()
{ {
auto users = loadRecords<User, SerializedUser>(m_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;
} }
@@ -241,6 +257,8 @@ Returns:
*/ */
util::Map<std::string, TrackedRecord<Notification>>& DataStore::getNotifications() util::Map<std::string, TrackedRecord<Notification>>& DataStore::getNotifications()
{ {
auto notifications = loadRecords<Notification, SerializedNotification>(m_notifications);
refreshCache(m_notificationCache, notifications);
return m_notificationCache; return m_notificationCache;
} }
@@ -371,6 +389,8 @@ Returns:
*/ */
void DataStore::saveUsers() void DataStore::saveUsers()
{ {
saveRecords<User, SerializedUser>(m_users, m_userCache);
saveNotifications();
} }
/* /*
@@ -383,6 +403,7 @@ Returns:
*/ */
void DataStore::saveNotifications() void DataStore::saveNotifications()
{ {
saveRecords<Notification, SerializedNotification>(m_notifications, m_notificationCache);
} }
/* /*
@@ -0,0 +1,28 @@
/*
File: DataStoreLockGuard.h
Description: Defines the DataStoreLockGuard class used to manage DataStore
locking and unlocking automatically within a scope.
Author: Trenser
Date: 12-June-2026
*/
#pragma once
#include "DataStore.h"
class DataStoreLockGuard
{
public:
explicit DataStoreLockGuard(DataStore& dataStore)
: m_dataStore(dataStore)
{
m_dataStore.lockDataStore();
}
~DataStoreLockGuard()
{
m_dataStore.unlockDataStore();
}
DataStoreLockGuard(const DataStoreLockGuard&) = delete;
DataStoreLockGuard& operator=(const DataStoreLockGuard&) = delete;
private:
DataStore& m_dataStore;
};
@@ -10,6 +10,7 @@ Created: 11-June-2026
*/ */
#include "SharedMemory.h" #include "SharedMemory.h"
#include "Windows.h"
#include "Config.h" #include "Config.h"
/* /*
@@ -8,6 +8,7 @@ Date: 19-May-2026
*/ */
#include <sstream> #include <sstream>
#include "SerializedRecords.h"
#include "User.h" #include "User.h"
#include "Notification.h" #include "Notification.h"
#include "Enums.h" #include "Enums.h"
@@ -28,7 +29,8 @@ Returns:
User::User() User::User()
: m_id("USR" + std::to_string(++m_uid)), : m_id("USR" + std::to_string(++m_uid)),
m_type(util::UserType::CUSTOMER), m_type(util::UserType::CUSTOMER),
m_status(util::State::ACTIVE) {} m_status(util::State::ACTIVE) {
}
/* /*
Function: User Function: User
@@ -51,7 +53,8 @@ User::User(const std::string& userName, const std::string& password, const std::
m_phone(phone), m_phone(phone),
m_email(email), m_email(email),
m_type(role), m_type(role),
m_status(util::State::ACTIVE) {} m_status(util::State::ACTIVE) {
}
/* /*
Function: User (parameterized constructor with ID) Function: User (parameterized constructor with ID)
@@ -324,68 +327,43 @@ void User::setState(util::State status)
/* /*
Function: serialize Function: serialize
Description: Serializes the user into a CSV-formatted string. Description: Serializes the User object into a SerializedUser record.
Parameters: Parameters:
- None - None
Returns: Returns:
- std::string: Serialized user record - SerializedUser: Serialized representation of the user
*/ */
std::string User::serialize() const SerializedUser User::serialize() const
{ {
std::ostringstream serializedUser; SerializedUser serialized = {};
serializedUser << m_id << ',' strcpy_s(serialized.id, sizeof(serialized.id), m_id.c_str());
<< m_userName << ',' strcpy_s(serialized.username, sizeof(serialized.username), m_userName.c_str());
<< m_password << ',' strcpy_s(serialized.password, sizeof(serialized.password), m_password.c_str());
<< m_name << ',' strcpy_s(serialized.name, sizeof(serialized.name), m_name.c_str());
<< m_phone << ',' strcpy_s(serialized.phone, sizeof(serialized.phone), m_phone.c_str());
<< m_email << ',' strcpy_s(serialized.email, sizeof(serialized.email), m_email.c_str());
<< util::getUserTypeString(m_type) << ',' serialized.userType = m_type;
<< util::getStateString(m_status); serialized.status = m_status;
return serializedUser.str(); return serialized;
} }
/* /*
Function: deserialize Function: deserialize
Description: Deserializes a CSV-formatted string into a User object. Description: Deserializes a SerializedUser record into a User object.
Parameters: Parameters:
- record: const std::string&, serialized user record - serializedUser: const SerializedUser&, serialized user record
Returns: Returns:
- User*: Pointer to the deserialized User object - User*: Pointer to the deserialized User object
*/ */
User* User::deserialize(const std::string& record) User* User::deserialize(const SerializedUser& serializedUser)
{ {
std::string id, name, username, phone, password, email; return Factory::getObject<User>(
std::string userTypeString, stateString; serializedUser.id,
std::istringstream serializedUser(record); serializedUser.username,
getline(serializedUser, id, ','); serializedUser.password,
getline(serializedUser, username, ','); serializedUser.name,
getline(serializedUser, password, ','); serializedUser.phone,
getline(serializedUser, name, ','); serializedUser.email,
getline(serializedUser, phone, ','); serializedUser.userType,
getline(serializedUser, email, ','); serializedUser.status);
getline(serializedUser, userTypeString, ',');
getline(serializedUser, stateString);
util::UserType userType = util::getUserType(userTypeString);
util::State status = util::getState(stateString);
return Factory::getObject<User>(id,
username,
password,
name,
phone,
email,
userType,
status);
}
/*
Function: getHeaders
Description: Retrieves the CSV headers for user serialization.
Parameters:
- None
Returns:
- std::string: Header string ("ID,Username,Password,Name,Phone,Email,UserType,UserStatus")
*/
std::string User::getHeaders()
{
return "ID,Username,Password,Name,Phone,Email,UserType,UserStatus";
} }
@@ -14,6 +14,7 @@ Date: 19-May-2026
#include "Enums.h" #include "Enums.h"
class Notification; class Notification;
struct SerializedUser;
class User : public Observer class User : public Observer
{ {
@@ -51,7 +52,6 @@ public:
void addNotification(Notification* notification) override; 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);
std::string serialize() const; SerializedUser serialize() const;
static User* deserialize(const std::string&); static User* deserialize(const SerializedUser& serializedUser);
static std::string getHeaders();
}; };
@@ -20,6 +20,9 @@ Date:19-May-2026
#include "UserManagementService.h" #include "UserManagementService.h"
#include "Vector.h" #include "Vector.h"
#include "Validator.h" #include "Validator.h"
#include "Utility.h"
#include "TrackedRecord.h"
#include "DataStoreLockGuard.h"
/* /*
Function: ensureAdminExists Function: ensureAdminExists
@@ -31,12 +34,13 @@ Return type: void
*/ */
void UserManagementService::ensureAdminExists() void UserManagementService::ensureAdminExists()
{ {
DataStoreLockGuard lock(m_dataStore);
auto& usersMap = m_dataStore.getUsers(); auto& usersMap = m_dataStore.getUsers();
int usersMapSize = usersMap.getSize(); int usersMapSize = usersMap.getSize();
bool isAdminFound = false; bool isAdminFound = false;
for (int index = 0; index < usersMapSize; index++) for (int index = 0; index < usersMapSize; index++)
{ {
User* user = usersMap.getValueAt(index); User* user = usersMap.getValueAt(index).data;
if (user && user->getUserType() == util::UserType::ADMIN) if (user && user->getUserType() == util::UserType::ADMIN)
{ {
isAdminFound = true; isAdminFound = true;
@@ -73,7 +77,9 @@ void UserManagementService::createUser(const std::string& username, const std::s
InventoryManagementService inventoryManagementService; InventoryManagementService inventoryManagementService;
PaymentManagementService paymentManagementService; PaymentManagementService paymentManagementService;
ServiceManagementService serviceManagementService; ServiceManagementService serviceManagementService;
auto& usersMap = m_dataStore.getUsers(); DataStoreLockGuard lock(m_dataStore);
auto& trackedUsersMap = m_dataStore.getUsers();
auto usersMap = util::getObjects(trackedUsersMap);
if (util::isUsernameDuplicate(username, usersMap)) if (util::isUsernameDuplicate(username, usersMap))
{ {
throw std::runtime_error("Username already exists"); throw std::runtime_error("Username already exists");
@@ -87,13 +93,14 @@ void UserManagementService::createUser(const std::string& username, const std::s
throw std::runtime_error("Phone already exists"); throw std::runtime_error("Phone already exists");
} }
User* newUser = Factory::getObject<User>(username, password, name, phone, email, type); User* newUser = Factory::getObject<User>(username, password, name, phone, email, type);
usersMap.insert(newUser->getId(), newUser); trackedUsersMap.insert(newUser->getId(), util::createNewRecord(newUser));
paymentManagementService.attach(newUser); paymentManagementService.attach(newUser);
serviceManagementService.attach(newUser); serviceManagementService.attach(newUser);
if (newUser->getUserType() == util::UserType::ADMIN) if (newUser->getUserType() == util::UserType::ADMIN)
{ {
inventoryManagementService.attach(newUser); inventoryManagementService.attach(newUser);
} }
m_dataStore.saveUsers();
} }
/* /*
@@ -107,19 +114,24 @@ Return type: void
*/ */
void UserManagementService::updateUserDetails(const std::string& userID, const std::string& email, const std::string& phone) void UserManagementService::updateUserDetails(const std::string& userID, const std::string& email, const std::string& phone)
{ {
auto& usersMap = m_dataStore.getUsers(); DataStoreLockGuard lock(m_dataStore);
int index = usersMap.find(userID); auto& trackedUsersMap = m_dataStore.getUsers();
auto usersMap = util::getObjects(trackedUsersMap);
int index = trackedUsersMap.find(userID);
if (index == -1) if (index == -1)
{ {
throw std::runtime_error("User does not exist!\n"); throw std::runtime_error("User does not exist!\n");
} }
User* user = usersMap.getValueAt(index); User* user = trackedUsersMap.getValueAt(index).data;
bool isModified = false;
if (email != user->getEmail()) if (email != user->getEmail())
{ {
if (util::isEmailDuplicate(email, usersMap)) if (util::isEmailDuplicate(email, usersMap))
{ {
throw std::runtime_error("Email already exists!\n"); throw std::runtime_error("Email already exists!\n");
} }
user->setEmail(email);
isModified = true;
} }
if (phone != user->getPhone()) if (phone != user->getPhone())
{ {
@@ -127,9 +139,14 @@ void UserManagementService::updateUserDetails(const std::string& userID, const s
{ {
throw std::runtime_error("Phone number already exists!\n"); throw std::runtime_error("Phone number already exists!\n");
} }
}
user->setEmail(email);
user->setPhone(phone); user->setPhone(phone);
isModified = true;
}
if (isModified)
{
trackedUsersMap.getValueAt(index).state = RecordState::MODIFIED;
m_dataStore.saveUsers();
}
} }
/* /*
@@ -144,12 +161,13 @@ Throws:
*/ */
util::Vector<Notification*> UserManagementService::getUserNotifications(const std::string& userID) util::Vector<Notification*> UserManagementService::getUserNotifications(const std::string& userID)
{ {
auto& usersMap = m_dataStore.getUsers(); DataStoreLockGuard lock(m_dataStore);
if (usersMap.find(userID) == -1) auto& trackedUsersMap = m_dataStore.getUsers();
if (trackedUsersMap.find(userID) == -1)
{ {
throw std::runtime_error("No user found with given UserID"); throw std::runtime_error("No user found with given UserID");
} }
User* user = usersMap[userID]; User* user = trackedUsersMap[userID].data;
if (user) if (user)
{ {
auto& notifications = user->getNotifications(); auto& notifications = user->getNotifications();
@@ -169,97 +187,41 @@ util::Vector<Notification*> UserManagementService::getUserNotifications(const st
/* /*
Function: deleteNotification Function: deleteNotification
Description: Deletes a specific notification associated with a given user ID. Description: Marks a specific notification associated with a given user
as inactive.
Parameters: Parameters:
- notificationID: The unique ID of the notification to be deleted. - notificationID: The unique ID of the notification to be deleted.
- userID: The unique ID of the user whose notification is to be deleted. - userID: The unique ID of the user whose notification is to be deleted.
Returns: Returns:
- void - void
Throws: Throws:
- std::runtime_error if no user is found with the given UserID or if no notification is found with the given NotificationID. - std::runtime_error if no user is found with the given UserID or
if no notification is found with the given NotificationID.
*/ */
void UserManagementService::deleteNotification(const std::string& notificationID, const std::string& userID) void UserManagementService::deleteNotification(const std::string& notificationID, const std::string& userID)
{ {
auto& usersMap = m_dataStore.getUsers(); DataStoreLockGuard lock(m_dataStore);
if (usersMap.find(userID) == -1) auto& trackedUsersMap = m_dataStore.getUsers();
auto& trackedNotificationsMap = m_dataStore.getNotifications();
int userIndex = trackedUsersMap.find(userID);
if (userIndex == -1)
{ {
throw std::runtime_error("No user found with given UserID"); throw std::runtime_error("No user found with given UserID");
} }
User* user = usersMap[userID]; User* user = trackedUsersMap.getValueAt(userIndex).data;
auto& notifications = user->getNotifications(); auto& notifications = user->getNotifications();
if (notifications.find(notificationID) == -1) if (notifications.find(notificationID) == -1)
{ {
throw std::runtime_error("No notification found with given NotificationID"); throw std::runtime_error("No notification found with given NotificationID");
} }
notifications.remove(notificationID); int notificationIndex = trackedNotificationsMap.find(notificationID);
} if (notificationIndex == -1)
/*
Function: loadUsers
Description: Loads users and notifications from persistent storage into the datastore.
Validates that each notifications recipient exists and attaches the
notification to the corresponding user.
Parameters:
- None
Returns:
- void
Throws:
- std::runtime_error if a notification recipient user ID is invalid
*/
void UserManagementService::loadUsers()
{ {
util::FileManager<User> userFileManager(config::file::USER_FILE); throw std::runtime_error("No notification found with given NotificationID");
util::FileManager<Notification> notificationFileManager(config::file::NOTIFICATION_FILE);
auto& users = m_dataStore.getUsers();
auto usersMap = userFileManager.load();
auto notificationsMap = notificationFileManager.load();
int numberOfUsers = usersMap.getSize();
int numberOfNotifications = notificationsMap.getSize();
for (int index = 0; index < numberOfUsers; index++)
{
users[usersMap.getKeyAt(index)] = usersMap.getValueAt(index);
} }
for (int index = 0; index < numberOfNotifications; index++) notifications[notificationID]->setState(util::State::INACTIVE);
{ trackedNotificationsMap.getValueAt(notificationIndex).state = RecordState::MODIFIED;
Notification* notification = notificationsMap.getValueAt(index); m_dataStore.saveNotifications();
const std::string& recipientUserId = notification->getRecipientUserId();
int userIndex = users.find(recipientUserId);
if (userIndex == -1)
{
throw std::runtime_error("Invalid recipient user ID");
}
User* user = users.getValueAt(userIndex);
user->addNotification(notification);
}
}
/*
Function: saveUsers
Description: Saves users and their notifications from the datastore to persistent storage.
Collects notifications from all users into a single map before saving.
Parameters:
- None
Returns:
- void
*/
void UserManagementService::saveUsers()
{
util::FileManager<User> userFileManager(config::file::USER_FILE);
util::FileManager<Notification> notificationFileManager(config::file::NOTIFICATION_FILE);
auto& users = m_dataStore.getUsers();
util::Map<std::string, Notification*> notifications;
for (int userIndex = 0; userIndex < users.getSize(); userIndex++)
{
User* user = users.getValueAt(userIndex);
auto& userNotifications = user->getNotifications();
for (int notificationIndex = 0; notificationIndex < userNotifications.getSize(); notificationIndex++)
{
notifications[userNotifications.getKeyAt(notificationIndex)] =
userNotifications.getValueAt(notificationIndex);
}
}
userFileManager.save(users);
notificationFileManager.save(notifications);
} }
/* /*
@@ -270,7 +232,9 @@ Return type: util::Map<std::string, User*>
*/ */
util::Map<std::string, User*> UserManagementService::getUsers() util::Map<std::string, User*> UserManagementService::getUsers()
{ {
return m_dataStore.getUsers(); DataStoreLockGuard lock(m_dataStore);
auto users = util::getObjects(m_dataStore.getUsers());
return users;
} }
/* /*
@@ -281,10 +245,12 @@ Return type: User*
*/ */
User* UserManagementService::getUser(const std::string& userID) User* UserManagementService::getUser(const std::string& userID)
{ {
int index = m_dataStore.getUsers().find(userID); DataStoreLockGuard lock(m_dataStore);
auto& trackedUsersMap = m_dataStore.getUsers();
int index = trackedUsersMap.find(userID);
if (index != -1) if (index != -1)
{ {
return m_dataStore.getUsers().getValueAt(index); return trackedUsersMap.getValueAt(index).data;
} }
return nullptr; return nullptr;
} }
@@ -300,10 +266,12 @@ void UserManagementService::removeUser(const std::string& userID)
InventoryManagementService inventoryManagementService; InventoryManagementService inventoryManagementService;
PaymentManagementService paymentManagementService; PaymentManagementService paymentManagementService;
ServiceManagementService serviceManagementService; ServiceManagementService serviceManagementService;
int index = m_dataStore.getUsers().find(userID); DataStoreLockGuard lock(m_dataStore);
auto& trackedUsersMap = m_dataStore.getUsers();
int index = trackedUsersMap.find(userID);
if (index != -1) if (index != -1)
{ {
User* user = m_dataStore.getUsers().getValueAt(index); User* user = trackedUsersMap.getValueAt(index).data;
if (user != nullptr) if (user != nullptr)
{ {
if (user->getUserType() == util::UserType::CUSTOMER) if (user->getUserType() == util::UserType::CUSTOMER)
@@ -314,21 +282,37 @@ void UserManagementService::removeUser(const std::string& userID)
{ {
serviceManagementService.cancelTechnicianJobs(userID); serviceManagementService.cancelTechnicianJobs(userID);
} }
user->setState(util::State::INACTIVE);
inventoryManagementService.detach(user); inventoryManagementService.detach(user);
paymentManagementService.detach(user); paymentManagementService.detach(user);
serviceManagementService.detach(user); serviceManagementService.detach(user);
user->setState(util::State::INACTIVE);
trackedUsersMap.getValueAt(index).state = RecordState::MODIFIED;
m_dataStore.saveUsers();
} }
} }
} }
/*
Function: getUsers
Description: Retrieves all active users of the specified type from
the DataStore.
Parameters:
- type: The user type to filter by
(ADMIN, CUSTOMER, or TECHNICIAN).
Returns:
- util::Map<std::string, User*>:
Collection of active users matching the specified type,
keyed by user ID.
*/
util::Map<std::string, User*> UserManagementService::getUsers(util::UserType type) util::Map<std::string, User*> UserManagementService::getUsers(util::UserType type)
{ {
util::Map<std::string, User*>& currentUsers = m_dataStore.getUsers(); DataStoreLockGuard lock(m_dataStore);
auto& trackedUsersMap = m_dataStore.getUsers();
util::Map<std::string, User*> currentUsers = util::getObjects(trackedUsersMap);
util::Map<std::string, User*> filteredUsersMap; util::Map<std::string, User*> filteredUsersMap;
for (int iterator = 0; iterator < currentUsers.getSize(); iterator++) for (int index = 0; index < currentUsers.getSize(); index++)
{ {
User* currentUser = currentUsers.getValueAt(iterator); User* currentUser = currentUsers.getValueAt(index);
if (currentUser && currentUser->getState() == util::State::ACTIVE && currentUser->getUserType() == type) if (currentUser && currentUser->getState() == util::State::ACTIVE && currentUser->getUserType() == type)
{ {
filteredUsersMap.insert(currentUser->getId(), currentUser); filteredUsersMap.insert(currentUser->getId(), currentUser);
@@ -31,6 +31,4 @@ public:
util::Vector<Notification*> getUserNotifications(const std::string& userID); util::Vector<Notification*> getUserNotifications(const std::string& userID);
void deleteNotification(const std::string& notificationID, const std::string& userID); void deleteNotification(const std::string& notificationID, const std::string& userID);
void ensureAdminExists(); void ensureAdminExists();
void loadUsers();
void saveUsers();
}; };
@@ -27,8 +27,11 @@ void UserInterface::run()
{ {
try try
{ {
m_controller.loadSystemData(); if (!m_controller.initialize())
m_controller.runSystemChecks(); {
std::cout << "Error: Failed to initialize the system!";
return;
}
bool isMenuActive = true; bool isMenuActive = true;
while (isMenuActive) while (isMenuActive)
{ {
@@ -49,7 +52,7 @@ void UserInterface::run()
util::pressEnter(); util::pressEnter();
} }
} }
m_controller.saveSystemData(); m_controller.shutdown();
} }
catch (const std::invalid_argument& exception) catch (const std::invalid_argument& exception)
{ {