From a2f72ec79d0132e9576ed6d80e8809920aed2757 Mon Sep 17 00:00:00 2001 From: Joel Thomas Date: Fri, 12 Jun 2026 03:31:05 +0530 Subject: [PATCH] Implement changes to user management service --- .../datastores/DataStore.cpp | 21 ++ .../services/UserManagementService.cpp | 195 +++++++++--------- .../services/UserManagementService.h | 2 - 3 files changed, 121 insertions(+), 97 deletions(-) diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.cpp index 1cade32..bda9ac0 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.cpp @@ -228,6 +228,22 @@ Returns: */ util::Map>& DataStore::getUsers() { + auto users = loadRecords(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; } @@ -241,6 +257,8 @@ Returns: */ util::Map>& DataStore::getNotifications() { + auto notifications = loadRecords(m_notifications); + refreshCache(m_notificationCache, notifications); return m_notificationCache; } @@ -371,6 +389,8 @@ Returns: */ void DataStore::saveUsers() { + saveRecords(m_users, m_userCache); + saveNotifications(); } /* @@ -383,6 +403,7 @@ Returns: */ void DataStore::saveNotifications() { + saveRecords(m_notifications, m_notificationCache); } /* diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp index 8ba68d0..89f97bc 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp @@ -20,6 +20,8 @@ Date:19-May-2026 #include "UserManagementService.h" #include "Vector.h" #include "Validator.h" +#include "Utility.h" +#include "TrackedRecord.h" /* Function: ensureAdminExists @@ -31,12 +33,13 @@ Return type: void */ void UserManagementService::ensureAdminExists() { + m_dataStore.lockDataStore(); auto& usersMap = m_dataStore.getUsers(); int usersMapSize = usersMap.getSize(); bool isAdminFound = false; 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) { isAdminFound = true; @@ -53,6 +56,7 @@ void UserManagementService::ensureAdminExists() config::admin::DEFAULT_ADMIN_PHONE, util::UserType::ADMIN); } + m_dataStore.unlockDataStore(); } /* @@ -73,27 +77,34 @@ void UserManagementService::createUser(const std::string& username, const std::s InventoryManagementService inventoryManagementService; PaymentManagementService paymentManagementService; ServiceManagementService serviceManagementService; - auto& usersMap = m_dataStore.getUsers(); + m_dataStore.lockDataStore(); + auto& trackedUsersMap = m_dataStore.getUsers(); + auto usersMap = util::getObjects(trackedUsersMap); if (util::isUsernameDuplicate(username, usersMap)) { + m_dataStore.unlockDataStore(); throw std::runtime_error("Username already exists"); } if (util::isEmailDuplicate(email, usersMap)) { + m_dataStore.unlockDataStore(); throw std::runtime_error("Email already exists"); } if (util::isPhoneDuplicate(phone, usersMap)) { + m_dataStore.unlockDataStore(); throw std::runtime_error("Phone already exists"); } User* newUser = Factory::getObject(username, password, name, phone, email, type); - usersMap.insert(newUser->getId(), newUser); + trackedUsersMap.insert(newUser->getId(), util::createNewRecord(newUser)); paymentManagementService.attach(newUser); serviceManagementService.attach(newUser); if (newUser->getUserType() == util::UserType::ADMIN) { inventoryManagementService.attach(newUser); } + m_dataStore.saveUsers(); + m_dataStore.unlockDataStore(); } /* @@ -107,29 +118,43 @@ Return type: void */ void UserManagementService::updateUserDetails(const std::string& userID, const std::string& email, const std::string& phone) { - auto& usersMap = m_dataStore.getUsers(); - int index = usersMap.find(userID); + m_dataStore.lockDataStore(); + auto& trackedUsersMap = m_dataStore.getUsers(); + auto usersMap = util::getObjects(trackedUsersMap); + int index = trackedUsersMap.find(userID); if (index == -1) { + m_dataStore.unlockDataStore(); 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 (util::isEmailDuplicate(email, usersMap)) { + m_dataStore.unlockDataStore(); throw std::runtime_error("Email already exists!\n"); } + user->setEmail(email); + isModified = true; } if (phone != user->getPhone()) { if (util::isPhoneDuplicate(phone, usersMap)) { + m_dataStore.unlockDataStore(); throw std::runtime_error("Phone number already exists!\n"); } + user->setPhone(phone); + isModified = true; } - user->setEmail(email); - user->setPhone(phone); + if (isModified) + { + trackedUsersMap.getValueAt(index).state = RecordState::MODIFIED; + m_dataStore.saveUsers(); + } + m_dataStore.unlockDataStore(); } /* @@ -144,12 +169,14 @@ Throws: */ util::Vector UserManagementService::getUserNotifications(const std::string& userID) { - auto& usersMap = m_dataStore.getUsers(); - if (usersMap.find(userID) == -1) + m_dataStore.lockDataStore(); + auto& trackedUsersMap = m_dataStore.getUsers(); + if (trackedUsersMap.find(userID) == -1) { + m_dataStore.unlockDataStore(); throw std::runtime_error("No user found with given UserID"); } - User* user = usersMap[userID]; + User* user = trackedUsersMap[userID].data; if (user) { auto& notifications = user->getNotifications(); @@ -159,107 +186,58 @@ util::Vector UserManagementService::getUserNotifications(const st { notificationsVector.push_back(notifications.getValueAt(index)); } + m_dataStore.unlockDataStore(); return notificationsVector; } else { + m_dataStore.unlockDataStore(); throw std::runtime_error("Invalid User object"); } } /* 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: - notificationID: The unique ID of the notification to be deleted. - userID: The unique ID of the user whose notification is to be deleted. Returns: - void 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) { - auto& usersMap = m_dataStore.getUsers(); - if (usersMap.find(userID) == -1) + m_dataStore.lockDataStore(); + auto& trackedUsersMap = m_dataStore.getUsers(); + auto& trackedNotificationsMap = m_dataStore.getNotifications(); + int userIndex = trackedUsersMap.find(userID); + if (userIndex == -1) { + m_dataStore.unlockDataStore(); throw std::runtime_error("No user found with given UserID"); } - User* user = usersMap[userID]; + User* user = trackedUsersMap.getValueAt(userIndex).data; auto& notifications = user->getNotifications(); if (notifications.find(notificationID) == -1) { + m_dataStore.unlockDataStore(); throw std::runtime_error("No notification found with given NotificationID"); } - notifications.remove(notificationID); -} + int notificationIndex = trackedNotificationsMap.find(notificationID); + if (notificationIndex == -1) + { + m_dataStore.unlockDataStore(); + throw std::runtime_error("No notification found with given NotificationID"); + } + notifications[notificationID]->setState(util::State::INACTIVE); + trackedNotificationsMap.getValueAt(notificationIndex).state = RecordState::MODIFIED; -/* -Function: loadUsers -Description: Loads users and notifications from persistent storage into the datastore. - Validates that each notification’s 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 userFileManager(config::file::USER_FILE); - util::FileManager 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++) - { - Notification* notification = notificationsMap.getValueAt(index); - 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 userFileManager(config::file::USER_FILE); - util::FileManager notificationFileManager(config::file::NOTIFICATION_FILE); - auto& users = m_dataStore.getUsers(); - util::Map 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); + m_dataStore.saveNotifications(); + m_dataStore.unlockDataStore(); } /* @@ -270,7 +248,10 @@ Return type: util::Map */ util::Map UserManagementService::getUsers() { - return m_dataStore.getUsers(); + m_dataStore.lockDataStore(); + auto users = util::getObjects(m_dataStore.getUsers()); + m_dataStore.unlockDataStore(); + return users; } /* @@ -281,11 +262,15 @@ Return type: User* */ User* UserManagementService::getUser(const std::string& userID) { - int index = m_dataStore.getUsers().find(userID); + m_dataStore.lockDataStore(); + auto& trackedUsersMap = m_dataStore.getUsers(); + int index = trackedUsersMap.find(userID); if (index != -1) { - return m_dataStore.getUsers().getValueAt(index); + m_dataStore.unlockDataStore(); + return trackedUsersMap.getValueAt(index).data; } + m_dataStore.unlockDataStore(); return nullptr; } @@ -300,39 +285,59 @@ void UserManagementService::removeUser(const std::string& userID) InventoryManagementService inventoryManagementService; PaymentManagementService paymentManagementService; ServiceManagementService serviceManagementService; - int index = m_dataStore.getUsers().find(userID); + m_dataStore.lockDataStore(); + auto& trackedUsersMap = m_dataStore.getUsers(); + int index = trackedUsersMap.find(userID); if (index != -1) { - User* user = m_dataStore.getUsers().getValueAt(index); + User* user = trackedUsersMap.getValueAt(index).data; if (user != nullptr) { if (user->getUserType() == util::UserType::CUSTOMER) { - serviceManagementService.cancelCustomerServiceBookings(userID); + serviceManagementService.cancelCustomerServiceBookings(userID); } if (user->getUserType() == util::UserType::TECHNICIAN) { serviceManagementService.cancelTechnicianJobs(userID); } - user->setState(util::State::INACTIVE); inventoryManagementService.detach(user); paymentManagementService.detach(user); serviceManagementService.detach(user); + user->setState(util::State::INACTIVE); + trackedUsersMap.getValueAt(index).state = RecordState::MODIFIED; + m_dataStore.saveUsers(); } } + m_dataStore.unlockDataStore(); } -util::Map UserManagementService::getUsers(util::UserType type) +/* +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: + Collection of active users matching the specified type, + keyed by user ID. +*/ +util::Map UserManagementService::getUsers(util::UserType type) { - util::Map& currentUsers = m_dataStore.getUsers(); + m_dataStore.lockDataStore(); + auto& trackedUsersMap = m_dataStore.getUsers(); + util::Map currentUsers = util::getObjects(trackedUsersMap); util::Map 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) { filteredUsersMap.insert(currentUser->getId(), currentUser); } } + m_dataStore.unlockDataStore(); return filteredUsersMap; } \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.h index b448872..28aa446 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.h @@ -31,6 +31,4 @@ public: util::Vector getUserNotifications(const std::string& userID); void deleteNotification(const std::string& notificationID, const std::string& userID); void ensureAdminExists(); - void loadUsers(); - void saveUsers(); };