From 929f609f2436988a64baeacbf3f5dc6cb0594d6f Mon Sep 17 00:00:00 2001 From: Joel Thomas Date: Fri, 12 Jun 2026 03:19:43 +0530 Subject: [PATCH 01/10] Implement Model Refactoring 1959: Model Refactoring UserStory #1959 1. Replaced CSV-based User serialization and deserialization with SerializedUser record-based serialization for shared memory storage. 2. Implemented User::serialize() to convert User objects into fixed-size SerializedUser structures containing user details and enum values. 3. Implemented User::deserialize() to reconstruct User objects directly from SerializedUser records. 4. Updated User class interfaces to use SerializedUser types instead of std::string serialization APIs. 5. Removed legacy CSV serialization support, including CSV parsing logic and header generation functionality. 6. Added SerializedUser dependencies through SerializedRecords.h inclusion and forward declaration support. N/A Sreeja Reghukumar, please review --- .../models/User.cpp | 82 +++++++------------ .../models/User.h | 6 +- 2 files changed, 33 insertions(+), 55 deletions(-) diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.cpp index 0b4e86e..c4dc928 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.cpp @@ -8,6 +8,7 @@ Date: 19-May-2026 */ #include +#include "SerializedRecords.h" #include "User.h" #include "Notification.h" #include "Enums.h" @@ -28,7 +29,8 @@ Returns: User::User() : m_id("USR" + std::to_string(++m_uid)), m_type(util::UserType::CUSTOMER), - m_status(util::State::ACTIVE) {} + m_status(util::State::ACTIVE) { +} /* Function: User @@ -51,7 +53,8 @@ User::User(const std::string& userName, const std::string& password, const std:: m_phone(phone), m_email(email), m_type(role), - m_status(util::State::ACTIVE) {} + m_status(util::State::ACTIVE) { +} /* Function: User (parameterized constructor with ID) @@ -324,68 +327,43 @@ void User::setState(util::State status) /* Function: serialize -Description: Serializes the user into a CSV-formatted string. +Description: Serializes the User object into a SerializedUser record. Parameters: - None 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 << m_id << ',' - << m_userName << ',' - << m_password << ',' - << m_name << ',' - << m_phone << ',' - << m_email << ',' - << util::getUserTypeString(m_type) << ',' - << util::getStateString(m_status); - return serializedUser.str(); + SerializedUser serialized = {}; + strcpy_s(serialized.id, sizeof(serialized.id), m_id.c_str()); + strcpy_s(serialized.username, sizeof(serialized.username), m_userName.c_str()); + strcpy_s(serialized.password, sizeof(serialized.password), m_password.c_str()); + strcpy_s(serialized.name, sizeof(serialized.name), m_name.c_str()); + strcpy_s(serialized.phone, sizeof(serialized.phone), m_phone.c_str()); + strcpy_s(serialized.email, sizeof(serialized.email), m_email.c_str()); + serialized.userType = m_type; + serialized.status = m_status; + return serialized; } /* Function: deserialize -Description: Deserializes a CSV-formatted string into a User object. +Description: Deserializes a SerializedUser record into a User object. Parameters: - - record: const std::string&, serialized user record + - serializedUser: const SerializedUser&, serialized user record Returns: - 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; - std::string userTypeString, stateString; - std::istringstream serializedUser(record); - getline(serializedUser, id, ','); - getline(serializedUser, username, ','); - getline(serializedUser, password, ','); - getline(serializedUser, name, ','); - getline(serializedUser, phone, ','); - getline(serializedUser, email, ','); - getline(serializedUser, userTypeString, ','); - getline(serializedUser, stateString); - util::UserType userType = util::getUserType(userTypeString); - util::State status = util::getState(stateString); - return Factory::getObject(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"; + return Factory::getObject( + serializedUser.id, + serializedUser.username, + serializedUser.password, + serializedUser.name, + serializedUser.phone, + serializedUser.email, + serializedUser.userType, + serializedUser.status); } \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.h index 12923f6..1026bd3 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.h @@ -14,6 +14,7 @@ Date: 19-May-2026 #include "Enums.h" class Notification; +struct SerializedUser; class User : public Observer { @@ -51,7 +52,6 @@ public: void addNotification(Notification* notification) override; void setRole(util::UserType role); void setState(util::State status); - std::string serialize() const; - static User* deserialize(const std::string&); - static std::string getHeaders(); + SerializedUser serialize() const; + static User* deserialize(const SerializedUser& serializedUser); }; From 6dea303b923346001e5d97b96523b521e5498f0a Mon Sep 17 00:00:00 2001 From: Avinash Rajesh Date: Fri, 12 Jun 2026 11:09:35 +0530 Subject: [PATCH 02/10] Implement Model Refactoring 1951: Model Refactoring UserStory #1951 1. Replaced CSV-based serialization and deserialization in ComboPackage, JobCard, Service, and ServiceBooking models with fixed-size SerializedRecord structures for shared memory storage. 2. Implemented serialize() methods to convert objects into SerializedComboPackage, SerializedJobCard, SerializedService, and SerializedServiceBooking records. 3. Implemented deserialize() methods to reconstruct objects directly from SerializedRecord types instead of parsing CSV strings. 4. Updated model class interfaces to use SerializedRecord types, removing legacy CSV serialization APIs and header generation functions. 5. Added SerializedRecords.h dependencies and forward declarations for Serialized structures across affected models. N/A Sreeja Reghukumar --- .../models/User.cpp | 82 +++++++------------ .../models/User.h | 6 +- 2 files changed, 33 insertions(+), 55 deletions(-) diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.cpp index 0b4e86e..c4dc928 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.cpp @@ -8,6 +8,7 @@ Date: 19-May-2026 */ #include +#include "SerializedRecords.h" #include "User.h" #include "Notification.h" #include "Enums.h" @@ -28,7 +29,8 @@ Returns: User::User() : m_id("USR" + std::to_string(++m_uid)), m_type(util::UserType::CUSTOMER), - m_status(util::State::ACTIVE) {} + m_status(util::State::ACTIVE) { +} /* Function: User @@ -51,7 +53,8 @@ User::User(const std::string& userName, const std::string& password, const std:: m_phone(phone), m_email(email), m_type(role), - m_status(util::State::ACTIVE) {} + m_status(util::State::ACTIVE) { +} /* Function: User (parameterized constructor with ID) @@ -324,68 +327,43 @@ void User::setState(util::State status) /* Function: serialize -Description: Serializes the user into a CSV-formatted string. +Description: Serializes the User object into a SerializedUser record. Parameters: - None 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 << m_id << ',' - << m_userName << ',' - << m_password << ',' - << m_name << ',' - << m_phone << ',' - << m_email << ',' - << util::getUserTypeString(m_type) << ',' - << util::getStateString(m_status); - return serializedUser.str(); + SerializedUser serialized = {}; + strcpy_s(serialized.id, sizeof(serialized.id), m_id.c_str()); + strcpy_s(serialized.username, sizeof(serialized.username), m_userName.c_str()); + strcpy_s(serialized.password, sizeof(serialized.password), m_password.c_str()); + strcpy_s(serialized.name, sizeof(serialized.name), m_name.c_str()); + strcpy_s(serialized.phone, sizeof(serialized.phone), m_phone.c_str()); + strcpy_s(serialized.email, sizeof(serialized.email), m_email.c_str()); + serialized.userType = m_type; + serialized.status = m_status; + return serialized; } /* Function: deserialize -Description: Deserializes a CSV-formatted string into a User object. +Description: Deserializes a SerializedUser record into a User object. Parameters: - - record: const std::string&, serialized user record + - serializedUser: const SerializedUser&, serialized user record Returns: - 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; - std::string userTypeString, stateString; - std::istringstream serializedUser(record); - getline(serializedUser, id, ','); - getline(serializedUser, username, ','); - getline(serializedUser, password, ','); - getline(serializedUser, name, ','); - getline(serializedUser, phone, ','); - getline(serializedUser, email, ','); - getline(serializedUser, userTypeString, ','); - getline(serializedUser, stateString); - util::UserType userType = util::getUserType(userTypeString); - util::State status = util::getState(stateString); - return Factory::getObject(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"; + return Factory::getObject( + serializedUser.id, + serializedUser.username, + serializedUser.password, + serializedUser.name, + serializedUser.phone, + serializedUser.email, + serializedUser.userType, + serializedUser.status); } \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.h index 12923f6..1026bd3 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.h @@ -14,6 +14,7 @@ Date: 19-May-2026 #include "Enums.h" class Notification; +struct SerializedUser; class User : public Observer { @@ -51,7 +52,6 @@ public: void addNotification(Notification* notification) override; void setRole(util::UserType role); void setState(util::State status); - std::string serialize() const; - static User* deserialize(const std::string&); - static std::string getHeaders(); + SerializedUser serialize() const; + static User* deserialize(const SerializedUser& serializedUser); }; From 89fc66218116d8d9a72aac641ead194724835956 Mon Sep 17 00:00:00 2001 From: Joel Thomas Date: Fri, 12 Jun 2026 11:31:03 +0530 Subject: [PATCH 03/10] Implement Service Refactoring 1960: Service Refactoring UserStory #1960 1. Replaced the Controller load/save workflow with initialize() and shutdown() methods. 2. Moved startup checks such as admin verification, low stock alerts, and payment reminders into Controller::initialize(). 3. Updated UserInterface to use the new Controller initialization and shutdown flow. 4. Updated DataStore::getUsers() and DataStore::getNotifications() to load data directly from shared memory. 5. Added logic to rebuild user notification mappings when user data is loaded from shared memory. 6. Implemented user and notification persistence through DataStore::saveUsers() and DataStore::saveNotifications(). 7. Updated UserManagementService to use TrackedRecord-based shared memory records. 8. Added DataStore locking and unlocking to user management operations for synchronization. 9. Updated createUser(), updateUserDetails(), removeUser(), and deleteNotification() to persist changes through shared memory. 10. Removed legacy loadUsers() and saveUsers() implementations from UserManagementService. 11. Added required header dependencies for shared memory support. N/A Sreeja Reghukumar, please review --- .../Trenser.VehicleServiceSystem.vcxproj | 1 + .../controllers/Controller.cpp | 72 +++---- .../controllers/Controller.h | 5 +- .../datastores/DataStore.cpp | 21 +++ .../datastores/DataStoreLockGuard.h | 28 +++ .../datastores/sharedmemory/SharedMemory.cpp | 1 + .../services/UserManagementService.cpp | 177 ++++++++---------- .../services/UserManagementService.h | 2 - .../views/UserInterface.cpp | 9 +- 9 files changed, 163 insertions(+), 153 deletions(-) create mode 100644 Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStoreLockGuard.h diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj index 6a269f5..7c4bfd3 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj @@ -157,6 +157,7 @@ + diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp index 9bc1d86..487ecd5 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp @@ -588,63 +588,37 @@ void Controller::configureNotifications(bool paymentNotifications, bool serviceN } /* -Function: loadSystemData -Description: Loads all system data from persistent storage into memory. - Invokes the respective management services to load users, inventory items, services, - combo packages, service bookings, job cards, invoices, and observers. +Function: initialize +Description: Initializes the system and run system checks to ensure critical configurations, such as verifying admin existence. Parameters: - None Returns: - - void + - bool */ -void Controller::loadSystemData() +bool Controller::initialize() { - m_userManagementService.loadUsers(); - 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(); -} + auto& dataStore = DataStore::getInstance(); -/* -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(); - 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() -{ + if (!dataStore.initialize()) + { + return false; + } m_userManagementService.ensureAdminExists(); m_inventoryManagementService.sendLowStockAlerts(); 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(); +} diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h index 35241a0..7ec1c30 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h @@ -70,7 +70,6 @@ public: util::Vector getNotifications(); void deleteNotification(const std::string& notificationID); void configureNotifications(bool paymentNotifications, bool serviceNotifications); - void loadSystemData(); - void saveSystemData(); - void runSystemChecks(); + bool initialize(); + void shutdown(); }; \ No newline at end of file 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/datastores/DataStoreLockGuard.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStoreLockGuard.h new file mode 100644 index 0000000..2e04eb0 --- /dev/null +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStoreLockGuard.h @@ -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; +}; \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/sharedmemory/SharedMemory.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/sharedmemory/SharedMemory.cpp index 6a10c9f..4b151e3 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/sharedmemory/SharedMemory.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/sharedmemory/SharedMemory.cpp @@ -10,6 +10,7 @@ Created: 11-June-2026 */ #include "SharedMemory.h" +#include "Windows.h" #include "Config.h" /* diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp index 8ba68d0..3eeead8 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp @@ -20,6 +20,9 @@ Date:19-May-2026 #include "UserManagementService.h" #include "Vector.h" #include "Validator.h" +#include "Utility.h" +#include "TrackedRecord.h" +#include "DataStoreLockGuard.h" /* Function: ensureAdminExists @@ -31,12 +34,13 @@ Return type: void */ void UserManagementService::ensureAdminExists() { + DataStoreLockGuard lock(m_dataStore); 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; @@ -73,7 +77,9 @@ void UserManagementService::createUser(const std::string& username, const std::s InventoryManagementService inventoryManagementService; PaymentManagementService paymentManagementService; 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)) { 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"); } 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(); } /* @@ -107,19 +114,24 @@ 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); + DataStoreLockGuard lock(m_dataStore); + auto& trackedUsersMap = m_dataStore.getUsers(); + auto usersMap = util::getObjects(trackedUsersMap); + int index = trackedUsersMap.find(userID); if (index == -1) { 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)) { throw std::runtime_error("Email already exists!\n"); } + user->setEmail(email); + isModified = true; } 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"); } + user->setPhone(phone); + isModified = true; + } + if (isModified) + { + trackedUsersMap.getValueAt(index).state = RecordState::MODIFIED; + m_dataStore.saveUsers(); } - user->setEmail(email); - user->setPhone(phone); } /* @@ -144,12 +161,13 @@ Throws: */ util::Vector UserManagementService::getUserNotifications(const std::string& userID) { - auto& usersMap = m_dataStore.getUsers(); - if (usersMap.find(userID) == -1) + DataStoreLockGuard lock(m_dataStore); + auto& trackedUsersMap = m_dataStore.getUsers(); + if (trackedUsersMap.find(userID) == -1) { 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,6 +177,7 @@ util::Vector UserManagementService::getUserNotifications(const st { notificationsVector.push_back(notifications.getValueAt(index)); } + m_dataStore.unlockDataStore(); return notificationsVector; } else @@ -169,97 +188,41 @@ util::Vector UserManagementService::getUserNotifications(const st /* 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) + DataStoreLockGuard lock(m_dataStore); + 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"); } - User* user = usersMap[userID]; + 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"); } - notifications.remove(notificationID); -} - -/* -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); + int notificationIndex = trackedNotificationsMap.find(notificationID); + if (notificationIndex == -1) + { + throw std::runtime_error("No notification found with given NotificationID"); + } + notifications[notificationID]->setState(util::State::INACTIVE); + trackedNotificationsMap.getValueAt(notificationIndex).state = RecordState::MODIFIED; + m_dataStore.saveNotifications(); } /* @@ -270,7 +233,9 @@ Return type: util::Map */ util::Map UserManagementService::getUsers() { - return m_dataStore.getUsers(); + DataStoreLockGuard lock(m_dataStore); + auto users = util::getObjects(m_dataStore.getUsers()); + return users; } /* @@ -281,10 +246,12 @@ Return type: User* */ 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) { - return m_dataStore.getUsers().getValueAt(index); + return trackedUsersMap.getValueAt(index).data; } return nullptr; } @@ -300,35 +267,53 @@ void UserManagementService::removeUser(const std::string& userID) InventoryManagementService inventoryManagementService; PaymentManagementService paymentManagementService; 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) { - 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(); } } } -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(); + DataStoreLockGuard lock(m_dataStore); + 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); 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(); }; diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/UserInterface.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/UserInterface.cpp index 4596d9b..926fc9e 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/UserInterface.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/UserInterface.cpp @@ -27,8 +27,11 @@ void UserInterface::run() { try { - m_controller.loadSystemData(); - m_controller.runSystemChecks(); + if (!m_controller.initialize()) + { + std::cout << "Error: Failed to initialize the system!"; + return; + } bool isMenuActive = true; while (isMenuActive) { @@ -49,7 +52,7 @@ void UserInterface::run() util::pressEnter(); } } - m_controller.saveSystemData(); + m_controller.shutdown(); } catch (const std::invalid_argument& exception) { From 74dbbd9e82a1dc53e13f1e987b0a51d2d3be29e8 Mon Sep 17 00:00:00 2001 From: Avinash Rajesh Date: Fri, 12 Jun 2026 14:28:48 +0530 Subject: [PATCH 04/10] Implement Service Refactoring 1952: Service Refactoring UserStory #1952 1. Enhanced DataStore::getUsers to load SerializedUser records, refresh cache, and attach notifications to recipient users with validation for recipient IDs. 2. Updated DataStore::saveUsers to persist SerializedUser records and save notifications alongside user data. 3. Refactored AuthenticationManagementService::login to use DataStoreLockGuard and tracked user map with SerializedUser-backed records. 4. Modified AuthenticationManagementService::changePassword to ensure thread-safe updates, mark user record as MODIFIED, and persist changes via DataStore::saveUsers. 5. Added dependencies for Utility.h and DataStoreLockGuard.h in AuthenticationManagementService.cpp to support safe record handling. N/A Sreeja Reghukumar --- .../Trenser.VehicleServiceSystem.vcxproj | 1 + ...enser.VehicleServiceSystem.vcxproj.filters | 3 ++ .../datastores/DataStore.cpp | 18 ++++++++++++ .../datastores/DataStoreLockGuard.h | 28 +++++++++++++++++++ .../AuthenticationManagementService.cpp | 20 ++++++++++--- 5 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStoreLockGuard.h diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj index 6a269f5..7c4bfd3 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj @@ -157,6 +157,7 @@ + diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters index 7e74b19..94301c4 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters @@ -278,5 +278,8 @@ Header Files\DataStores\SharedMemory + + Header Files\DataStores + \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.cpp index 1cade32..f430184 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; } @@ -371,6 +387,8 @@ Returns: */ void DataStore::saveUsers() { + saveRecords(m_users, m_userCache); + saveNotifications(); } /* diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStoreLockGuard.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStoreLockGuard.h new file mode 100644 index 0000000..2e04eb0 --- /dev/null +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStoreLockGuard.h @@ -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; +}; \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/AuthenticationManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/AuthenticationManagementService.cpp index dc3a94c..27be89f 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/AuthenticationManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/AuthenticationManagementService.cpp @@ -10,6 +10,8 @@ Date:19-May-2026 #include #include "AuthenticationManagementService.h" #include "User.h" +#include "Utility.h" +#include "DataStoreLockGuard.h" User* AuthenticationManagementService::m_authenticatedUser = nullptr; @@ -24,11 +26,12 @@ Return type: bool - true if login successful, false otherwise */ bool AuthenticationManagementService::login(const std::string& username, const std::string& password) { - util::Map users = m_dataStore.getUsers(); - int usersMapSize = users.getSize(); - for (int index = 0; index < usersMapSize; index++) + DataStoreLockGuard lock(m_dataStore); + auto& trackedUserMap = m_dataStore.getUsers(); + int trackedUserMapSize = trackedUserMap.getSize(); + for (int index = 0; index < trackedUserMapSize; index++) { - User* user = users.getValueAt(index); + User* user = trackedUserMap.getValueAt(index).data; if (username == user->getUserName()) { if (password == user->getPassword()) @@ -74,9 +77,18 @@ Return type: void */ void AuthenticationManagementService::changePassword(const std::string& newPassword) { + DataStoreLockGuard lock(m_dataStore); + auto& trackedUsersMap = m_dataStore.getUsers(); + int index = trackedUsersMap.find(m_authenticatedUser->getId()); + if (index == -1) + { + throw std::runtime_error("User does not exist!\n"); + } if (m_authenticatedUser == nullptr) { throw std::runtime_error("There is no user currently logged in!"); } m_authenticatedUser->setPassword(newPassword); + trackedUsersMap.getValueAt(index).state = RecordState::MODIFIED; + m_dataStore.saveUsers(); } From d44cc86af0f1010b8240d0d65f94623d00007261 Mon Sep 17 00:00:00 2001 From: Avinash Rajesh Date: Mon, 15 Jun 2026 14:43:48 +0530 Subject: [PATCH 05/10] Implement the review fixes --- .../services/AuthenticationManagementService.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/AuthenticationManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/AuthenticationManagementService.cpp index 27be89f..71d66b6 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/AuthenticationManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/AuthenticationManagementService.cpp @@ -79,15 +79,15 @@ void AuthenticationManagementService::changePassword(const std::string& newPassw { DataStoreLockGuard lock(m_dataStore); auto& trackedUsersMap = m_dataStore.getUsers(); + if (m_authenticatedUser == nullptr) + { + throw std::runtime_error("There is no user currently logged in!"); + } int index = trackedUsersMap.find(m_authenticatedUser->getId()); if (index == -1) { throw std::runtime_error("User does not exist!\n"); } - if (m_authenticatedUser == nullptr) - { - throw std::runtime_error("There is no user currently logged in!"); - } m_authenticatedUser->setPassword(newPassword); trackedUsersMap.getValueAt(index).state = RecordState::MODIFIED; m_dataStore.saveUsers(); From b5c8b1ee9bdc97071c4d92cefc68e852c881c20f Mon Sep 17 00:00:00 2001 From: Joel Thomas Date: Mon, 15 Jun 2026 14:46:37 +0530 Subject: [PATCH 06/10] Implement review fixes --- .../services/UserManagementService.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp index 3eeead8..9b1c61c 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp @@ -177,7 +177,6 @@ util::Vector UserManagementService::getUserNotifications(const st { notificationsVector.push_back(notifications.getValueAt(index)); } - m_dataStore.unlockDataStore(); return notificationsVector; } else From 5f4ee72ffef2ddd1f168359bfd3f072c4799e529 Mon Sep 17 00:00:00 2001 From: Joel Thomas Date: Fri, 12 Jun 2026 17:36:15 +0530 Subject: [PATCH 07/10] Implement Notification Model Refactoring 1953: Model Refactoring UserStory #1953 1. Replaced CSV-based Notification serialization and deserialization with SerializedNotification record-based serialization for shared memory storage. 2. Implemented Notification::serialize() to convert Notification objects into fixed-size SerializedNotification structures. 3. Implemented Notification::deserialize() to reconstruct Notification objects directly from SerializedNotification records. 4. Added Notification state persistence by introducing util::State support in constructors, serialization, and deserialization flows. 5. Updated Notification class interfaces to use SerializedNotification types instead of std::string serialization APIs. 6. Removed legacy CSV serialization support, including CSV parsing logic and header generation functionality. 7. Added SerializedNotification dependencies through SerializedRecords.h inclusion and forward declaration support. 8. Initialized Notification objects with ACTIVE state by default and added state getter/setter APIs. N/A Sreeja Reghukumar, please review --- .../models/Notification.cpp | 109 +++++++++--------- .../models/Notification.h | 12 +- 2 files changed, 62 insertions(+), 59 deletions(-) diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Notification.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Notification.cpp index 0bae917..ad1b416 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Notification.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Notification.cpp @@ -7,6 +7,7 @@ Date: 19-May-2026 */ #include +#include "SerializedRecords.h" #include "Notification.h" #include "StringHelper.h" #include "Factory.h" @@ -23,7 +24,8 @@ Returns: */ Notification::Notification() : m_id("NOT" + std::to_string(++m_uid)), - m_recipient(nullptr) {} + m_recipient(nullptr), m_state(util::State::ACTIVE) { +} /* Function: Notification @@ -43,7 +45,9 @@ Notification::Notification(const std::string& recipientUserId, User* recipient, m_recipient(recipient), m_title(title), m_message(message), - m_createdAt(createdAt) {} + m_state(util::State::ACTIVE), + m_createdAt(createdAt) { +} /* Function: Notification (parameterized constructor with ID) @@ -58,13 +62,14 @@ Parameters: Returns: - 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) +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) : m_id(id), m_recipientUserId(recipientUserId), m_recipient(nullptr), m_title(title), m_message(message), - m_createdAt(createdAt) + m_createdAt(createdAt), + m_state(state) { int idNumber = util::extractNumber(m_id); if (idNumber > m_uid) @@ -79,7 +84,7 @@ Description: Retrieves the unique ID of the notification. Returns: - const std::string& representing the notification ID. */ -const std::string& Notification::getId() const +const std::string& Notification::getId() const { return m_id; } @@ -139,6 +144,17 @@ const util::Timestamp& Notification::getCreatedAt() const 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 Description: Sets the unique ID of the notification. @@ -217,71 +233,54 @@ void Notification::setCreatedAt(const util::Timestamp& 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 -Description: Serializes the notification into a CSV-formatted string. +Description: Serializes the Notification object into a SerializedNotification record. Parameters: - None Returns: - - std::string: Serialized notification record + - SerializedNotification: Serialized representation of the notification */ -std::string Notification::serialize() const +SerializedNotification Notification::serialize() const { - std::ostringstream serializedNotification; - serializedNotification << m_id << ',' - << m_recipientUserId << ',' - << m_title << ',' - << m_message << ',' - << m_createdAt.toString(); - return serializedNotification.str(); + SerializedNotification serialized = {}; + strcpy_s(serialized.id, sizeof(serialized.id), m_id.c_str()); + strcpy_s(serialized.recipientUserId, sizeof(serialized.recipientUserId), m_recipientUserId.c_str()); + strcpy_s(serialized.title, sizeof(serialized.title), m_title.c_str()); + strcpy_s(serialized.message, sizeof(serialized.message), m_message.c_str()); + serialized.createdAt = m_createdAt; + serialized.state = m_state; + return serialized; } /* Function: deserialize -Description: Deserializes a CSV-formatted string into a Notification object. +Description: Deserializes a SerializedNotification record into a Notification object. Parameters: - - record: const std::string&, serialized notification record + - serializedNotification: const SerializedNotification&, serialized notification record Returns: - Notification*: Pointer to the deserialized Notification object -Throws: - - std::runtime_error if timestamp parsing fails */ -Notification* Notification::deserialize(const std::string& record) +Notification* Notification::deserialize(const SerializedNotification& serializedNotification) { - 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( - id, - recipientUserId, - title, - message, - createdAtTimestamp - ); -} - -/* -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"; + serializedNotification.id, + serializedNotification.recipientUserId, + serializedNotification.title, + serializedNotification.message, + serializedNotification.createdAt, + serializedNotification.state); } \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Notification.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Notification.h index 57869fa..d92bc2c 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Notification.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Notification.h @@ -9,8 +9,10 @@ Date: 19-May-2026 #pragma once #include #include "Timestamp.h" +#include "Enums.h" class User; +struct SerializedNotification; class Notification { @@ -22,10 +24,11 @@ private: std::string m_title; std::string m_message; util::Timestamp m_createdAt; + util::State m_state; public: Notification(); 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); + 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); const std::string& getId() const; const std::string& getRecipientUserId() const; User* getRecipient() const; @@ -38,7 +41,8 @@ public: void setTitle(const std::string& title); void setMessage(const std::string& message); void setCreatedAt(const util::Timestamp& createdAt); - std::string serialize() const; - static Notification* deserialize(const std::string&); - static std::string getHeaders(); + util::State getState() const; + void setState(util::State state); + SerializedNotification serialize() const; + static Notification* deserialize(const SerializedNotification&); }; From 67ac7f66258cd8cefeea0b3b81ab4f5d09974448 Mon Sep 17 00:00:00 2001 From: Joel Thomas Date: Fri, 12 Jun 2026 19:23:56 +0530 Subject: [PATCH 08/10] Implement Service Refactoring 1954: Implement Service Refactoring UserStory #1954 1. Refactored notification handling to persist notifications directly in the datastore instead of maintaining notification collections within User objects. 2. Removed recipient User pointer dependencies from Notification and retained recipient user identification through recipientUserId. 3. Implemented generic observer persistence support in DataStore with shared helper methods for loading and saving observer subscriptions. 4. Added datastore-backed observer management for ServiceManagementService, PaymentManagementService, and InventoryManagementService. 5. Updated attach() and detach() operations to load, modify, and persist observer subscriptions using shared memory mappings. 6. Refactored sendNotification() implementations to create and persist Notification records directly to the datastore for subscribed observers. 7. Updated UserManagementService notification retrieval and deletion logic to operate on datastore notification records filtered by recipient user ID. 8. Removed notification ownership and observer-specific notification APIs from User and Observer classes. 9. Added configurable shared memory growth factor support and updated mapping expansion logic to use centralized configuration values. 10. Removed obsolete NotificationManagementService implementation and updated project configuration references. 11. Added DataStoreLockGuard integration for observer and notification persistence operations to ensure synchronized datastore access. N/A Sreeja Reghukumar, please review --- .../Trenser.VehicleServiceSystem.vcxproj | 1 - ...enser.VehicleServiceSystem.vcxproj.filters | 6 +- .../core/patterns/Observer.h | 1 - .../datastores/DataStore.cpp | 89 +++++++++++++++---- .../datastores/DataStore.h | 2 + .../datastores/sharedmemory/SharedMemory.cpp | 2 +- .../models/Notification.cpp | 35 +------- .../models/Notification.h | 5 +- .../models/User.cpp | 44 --------- .../models/User.h | 5 +- .../services/InventoryManagementService.cpp | 50 ++++++----- .../NotificationManagementService.cpp | 1 - .../services/PaymentManagementService.cpp | 49 +++++----- .../services/ServiceManagementService.cpp | 77 +++++++--------- .../services/ServiceManagementService.h | 2 - .../services/UserManagementService.cpp | 26 +++--- .../utilities/Config.h | 1 + 17 files changed, 186 insertions(+), 210 deletions(-) delete mode 100644 Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/NotificationManagementService.cpp diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj index 7c4bfd3..b9a6f28 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj @@ -140,7 +140,6 @@ - diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters index 7e74b19..e9b5831 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters @@ -114,9 +114,6 @@ Source Files\DataStores - - Source Files\Services - Source Files\Core\Patterns @@ -278,5 +275,8 @@ Header Files\DataStores\SharedMemory + + Header Files + \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/patterns/Observer.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/patterns/Observer.h index 7fd7262..e9eb955 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/patterns/Observer.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/patterns/Observer.h @@ -13,5 +13,4 @@ class Observer { public: virtual ~Observer() = default; - virtual void addNotification(Notification* notification) = 0; }; \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.cpp index bda9ac0..9f72555 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.cpp @@ -230,20 +230,6 @@ 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; } @@ -340,6 +326,37 @@ util::Map>& DataStore::getInvoices() 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: Collection of observer records +Throws: + - std::runtime_error if an observer references an invalid user ID +*/ +util::Map DataStore::getObservers(MappingInfo& mapping) +{ + auto& users = getUsers(); + util::Map observers; + SharedMemory::ensureLatestMapping(mapping); + size_t recordCount = SharedMemory::getRecordCount(mapping); + for (size_t index = 0; index < recordCount; index++) + { + const SerializedObserver* observer = static_cast(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 Description: Retrieves all service management observer records from the datastore. @@ -350,7 +367,7 @@ Returns: */ util::Map DataStore::getServiceManagementObservers() { - return util::Map(); + return getObservers(m_serviceManagementObservers); } /* @@ -363,7 +380,7 @@ Returns: */ util::Map DataStore::getPaymentManagementObservers() { - return util::Map(); + return getObservers(m_paymentManagementObservers); } /* @@ -376,7 +393,7 @@ Returns: */ util::Map DataStore::getInventoryManagementObservers() { - return util::Map(); + return getObservers(m_inventoryManagementObservers); } /* @@ -390,7 +407,6 @@ Returns: void DataStore::saveUsers() { saveRecords(m_users, m_userCache); - saveNotifications(); } /* @@ -478,16 +494,49 @@ 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&, collection of observer records +Returns: + - None +*/ +void DataStore::saveObservers(MappingInfo& mapping, util::Map& observers) +{ + size_t observerCount = static_cast(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(index)); + strcpy_s(serializedObserver.id, sizeof(serializedObserver.id), user->getId().c_str()); + SerializedObserver* destination = static_cast(SharedMemory::getRecordAddress(mapping, index)); + *destination = serializedObserver; + } +} + /* Function: saveServiceManagementObservers Description: Persists all service management observer records to the datastore. Parameters: - - observers: util::Map>&, collection of observer records + - observers: util::Map&, collection of observer records Returns: - None */ void DataStore::saveServiceManagementObservers(util::Map& observers) { + saveObservers(m_serviceManagementObservers, observers); } /* @@ -500,6 +549,7 @@ Returns: */ void DataStore::savePaymentManagementObservers(util::Map& observers) { + saveObservers(m_paymentManagementObservers, observers); } /* @@ -512,6 +562,7 @@ Returns: */ void DataStore::saveInventoryManagementObservers(util::Map& observers) { + saveObservers(m_inventoryManagementObservers, observers); } /* diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.h index 3950b11..62c585d 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.h @@ -86,6 +86,8 @@ private: void saveRecords(MappingInfo& mapping, util::Map>& records); template void clearCache(util::Map>&cache); template void refreshCache(util::Map>&cache, util::Map>&refreshedCache); + util::Map getObservers(MappingInfo& mapping); + void saveObservers(MappingInfo& mapping, util::Map& observers); }; /* diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/sharedmemory/SharedMemory.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/sharedmemory/SharedMemory.cpp index 4b151e3..0c5c7b1 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/sharedmemory/SharedMemory.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/sharedmemory/SharedMemory.cpp @@ -320,7 +320,7 @@ bool SharedMemory::ensureCapacityForInsert(MappingInfo& mapping) { return true; } - return resizeMapping(mapping, capacity * 2); + return resizeMapping(mapping, capacity * config::file::GROWTH_FACTOR); } /* diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Notification.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Notification.cpp index ad1b416..83532ec 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Notification.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Notification.cpp @@ -1,7 +1,7 @@ /* File: Notification.cpp 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, recipient, title, message, and timestamp. + Provides constructors, accessors, and mutators for notification details such as ID, recipientID, title, message, and timestamp. Author: Trenser Date: 19-May-2026 */ @@ -23,9 +23,8 @@ Returns: - A new Notification object. */ Notification::Notification() - : m_id("NOT" + std::to_string(++m_uid)), - m_recipient(nullptr), m_state(util::State::ACTIVE) { -} + : m_id("NOT" + std::to_string(++m_uid)), + m_state(util::State::ACTIVE) {} /* Function: Notification @@ -39,10 +38,9 @@ Parameters: Returns: - A new Notification object. */ -Notification::Notification(const std::string& recipientUserId, User* recipient, const std::string& title, const std::string& message, const util::Timestamp& createdAt) +Notification::Notification(const std::string& recipientUserId, const std::string& title, const std::string& message, const util::Timestamp& createdAt) : m_id("NOT" + std::to_string(++m_uid)), m_recipientUserId(recipientUserId), - m_recipient(recipient), m_title(title), m_message(message), m_state(util::State::ACTIVE), @@ -65,7 +63,6 @@ Returns: 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) : m_id(id), m_recipientUserId(recipientUserId), - m_recipient(nullptr), m_title(title), m_message(message), m_createdAt(createdAt), @@ -100,17 +97,6 @@ const std::string& Notification::getRecipientUserId() const 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 Description: Retrieves the title of the notification. @@ -181,19 +167,6 @@ void Notification::setRecipientUserId(const std::string& 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 Description: Sets the title of the notification. diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Notification.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Notification.h index d92bc2c..a102cc6 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Notification.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Notification.h @@ -20,24 +20,21 @@ private: static int m_uid; std::string m_id; std::string m_recipientUserId; - User* m_recipient; std::string m_title; std::string m_message; util::Timestamp m_createdAt; util::State m_state; public: Notification(); - Notification(const std::string& recipientUserId, User* recipient, const std::string& title, const std::string& message, const util::Timestamp& createdAt); + Notification(const std::string& recipientUserId, 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); const std::string& getId() const; const std::string& getRecipientUserId() const; - User* getRecipient() const; const std::string& getTitle() const; const std::string& getMessage() const; const util::Timestamp& getCreatedAt() const; void setId(const std::string& id); void setRecipientUserId(const std::string& recipientUserId); - void setRecipient(User* recipient); void setTitle(const std::string& title); void setMessage(const std::string& message); void setCreatedAt(const util::Timestamp& createdAt); diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.cpp index c4dc928..5794259 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.cpp @@ -89,23 +89,6 @@ 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 Description: Retrieves the unique ID of the user. @@ -172,17 +155,6 @@ const std::string& User::getEmail() const return m_email; } -/* -Function: getNotifications -Description: Retrieves the map of notifications associated with the user. -Returns: - - util::Map& representing the notifications. -*/ -util::Map& User::getNotifications() -{ - return m_notifications; -} - /* Function: getUserType Description: Retrieves the role of the user. @@ -283,22 +255,6 @@ void User::setEmail(const std::string& email) m_email = email; } -/* -Function: addNotification -Description: Adds a new notification to the user’s 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 Description: Sets the role of the user. diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.h index 1026bd3..1a0f93f 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.h @@ -26,21 +26,19 @@ private: std::string m_name; std::string m_phone; std::string m_email; - util::Map m_notifications; util::UserType m_type; util::State m_status; public: 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& 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(); + ~User() = default; const std::string& getId() const; const std::string& getUserName() const; const std::string& getPassword() const; const std::string& getName() const; const std::string& getPhone() const; const std::string& getEmail() const; - util::Map& getNotifications(); util::UserType getUserType() const; util::State getState() const; void setId(const std::string& id); @@ -49,7 +47,6 @@ public: void setName(const std::string& name); void setPhone(const std::string& phone); void setEmail(const std::string& email); - void addNotification(Notification* notification) override; void setRole(util::UserType role); void setState(util::State status); SerializedUser serialize() const; diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.cpp index d08d957..aed6f3a 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.cpp @@ -19,7 +19,7 @@ Date: 22-May-2026 #include "User.h" #include "Utility.h" #include "Vector.h" - +#include "DataStoreLockGuard.h" util::Map InventoryManagementService::m_observers{}; @@ -271,6 +271,9 @@ Returns: */ void InventoryManagementService::attach(User* user) { + DataStoreLockGuard lock(m_dataStore); + m_observers.clear(); + m_observers = m_dataStore.getInventoryManagementObservers(); if (user) { const std::string& userID = user->getId(); @@ -279,6 +282,7 @@ void InventoryManagementService::attach(User* user) m_observers[userID] = user; } } + m_dataStore.saveInventoryManagementObservers(m_observers); } /* @@ -291,6 +295,9 @@ Returns: */ void InventoryManagementService::detach(User* user) { + DataStoreLockGuard lock(m_dataStore); + m_observers.clear(); + m_observers = m_dataStore.getInventoryManagementObservers(); if (user) { const std::string& userID = user->getId(); @@ -299,6 +306,7 @@ void InventoryManagementService::detach(User* user) m_observers.remove(userID); } } + m_dataStore.saveInventoryManagementObservers(m_observers); } /* @@ -315,27 +323,27 @@ Throws: */ void InventoryManagementService::sendNotification(User* user, const std::string& title, const std::string& message) { - if (user) + if (!user) { - if (m_observers.find(user->getId()) != -1) - { - Notification* notification = - Factory::getObject( - user->getId(), - user, - title, - message, - util::Timestamp() - ); - if (notification) - { - user->addNotification(notification); - } - else - { - throw std::runtime_error("Failed to create notification"); - } - } + return; } + DataStoreLockGuard lock(m_dataStore); + m_observers = m_dataStore.getInventoryManagementObservers(); + if (m_observers.find(user->getId()) == -1) + { + return; + } + Notification* notification = Factory::getObject( + 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(); } diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/NotificationManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/NotificationManagementService.cpp deleted file mode 100644 index cc23059..0000000 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/NotificationManagementService.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "NotificationManagementService.h" diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp index 1fc1ff8..1ebb273 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp @@ -21,6 +21,7 @@ Date: 20-May-2026 #include "Timestamp.h" #include "User.h" #include "Utility.h" +#include "DataStoreLockGuard.h" util::Map PaymentManagementService::m_observers{}; @@ -34,6 +35,9 @@ Returns: */ void PaymentManagementService::attach(User* user) { + DataStoreLockGuard lock(m_dataStore); + m_observers.clear(); + m_observers = m_dataStore.getPaymentManagementObservers(); if (user) { const std::string& userID = user->getId(); @@ -42,6 +46,7 @@ void PaymentManagementService::attach(User* user) m_observers[userID] = user; } } + m_dataStore.savePaymentManagementObservers(m_observers); } /* @@ -54,6 +59,9 @@ Returns: */ void PaymentManagementService::detach(User* user) { + DataStoreLockGuard lock(m_dataStore); + m_observers.clear(); + m_observers = m_dataStore.getPaymentManagementObservers(); if (user) { const std::string& userID = user->getId(); @@ -62,6 +70,7 @@ void PaymentManagementService::detach(User* user) m_observers.remove(userID); } } + m_dataStore.savePaymentManagementObservers(m_observers); } /* @@ -78,28 +87,28 @@ Throws: */ void PaymentManagementService::sendNotification(User* user, const std::string& title, const std::string& message) { - if (user) + if (!user) { - if (m_observers.find(user->getId()) != -1) - { - Notification* notification = - Factory::getObject( - user->getId(), - user, - title, - message, - util::Timestamp() - ); - if (notification) - { - user->addNotification(notification); - } - else - { - throw std::runtime_error("Failed to create notification"); - } - } + return; } + DataStoreLockGuard lock(m_dataStore); + m_observers = m_dataStore.getPaymentManagementObservers(); + if (m_observers.find(user->getId()) == -1) + { + return; + } + Notification* notification = Factory::getObject( + 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(); } /* diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp index 1a9f753..102ba31 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp @@ -26,6 +26,7 @@ Date:19-May-2026 #include "User.h" #include "UserManagementService.h" #include "Utility.h" +#include "DataStoreLockGuard.h" /* Function: purchaseService @@ -122,6 +123,9 @@ Returns: */ void ServiceManagementService::attach(User* user) { + DataStoreLockGuard lock(m_dataStore); + m_observers.clear(); + m_observers = m_dataStore.getServiceManagementObservers(); if (user) { const std::string& userID = user->getId(); @@ -130,6 +134,7 @@ void ServiceManagementService::attach(User* user) m_observers[userID] = user; } } + m_dataStore.saveServiceManagementObservers(m_observers); } /* @@ -142,6 +147,9 @@ Returns: */ void ServiceManagementService::detach(User* user) { + DataStoreLockGuard lock(m_dataStore); + m_observers.clear(); + m_observers = m_dataStore.getServiceManagementObservers(); if (user) { const std::string& userID = user->getId(); @@ -150,6 +158,7 @@ void ServiceManagementService::detach(User* user) m_observers.remove(userID); } } + m_dataStore.saveServiceManagementObservers(m_observers); } /* @@ -166,52 +175,28 @@ Throws: */ void ServiceManagementService::sendNotification(User* user, const std::string& title, const std::string& message) { - if (user) - { - if (m_observers.find(user->getId()) != -1) - { - Notification* notification = - Factory::getObject( - user->getId(), - user, - title, - message, - util::Timestamp() - ); - if (notification) - { - user->addNotification(notification); - } - else - { - throw std::runtime_error("Failed to create notification"); - } - } - } -} - -/* -Function: getObserverIDs -Description: Retrieves the IDs of all observers currently attached to the - ServiceManagementService. -Parameters: - - None -Returns: - - util::Vector: Vector of observer user IDs -*/ -util::Vector ServiceManagementService::getObserverIDs() -{ - util::Vector 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; + if (!user) + { + return; + } + DataStoreLockGuard lock(m_dataStore); + m_observers = m_dataStore.getServiceManagementObservers(); + if (m_observers.find(user->getId()) == -1) + { + return; + } + Notification* notification = Factory::getObject( + 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(); } /* diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.h index b2a4384..f1ff966 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.h @@ -53,6 +53,4 @@ public: void saveServiceBookings(); void loadJobCards(); void saveJobCards(); - void loadObservers(); - void saveObservers(); }; diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp index 9b1c61c..1be3a40 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp @@ -170,12 +170,16 @@ util::Vector UserManagementService::getUserNotifications(const st User* user = trackedUsersMap[userID].data; if (user) { - auto& notifications = user->getNotifications(); - int numberOfNotifications = notifications.getSize(); + auto& trackedNotificationMap = m_dataStore.getNotifications(); + int numberOfNotifications = trackedNotificationMap.getSize(); util::Vector notificationsVector; for (int index = 0; index < numberOfNotifications; index++) { - notificationsVector.push_back(notifications.getValueAt(index)); + Notification* notification = trackedNotificationMap.getValueAt(index).data; + if (notification->getRecipientUserId() == userID && notification->getState() == util::State::ACTIVE) + { + notificationsVector.push_back(notification); + } } return notificationsVector; } @@ -208,20 +212,18 @@ void UserManagementService::deleteNotification(const std::string& notificationID { throw std::runtime_error("No user found with given UserID"); } - 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); if (notificationIndex == -1) { throw std::runtime_error("No notification found with given NotificationID"); } - notifications[notificationID]->setState(util::State::INACTIVE); - trackedNotificationsMap.getValueAt(notificationIndex).state = RecordState::MODIFIED; - m_dataStore.saveNotifications(); + Notification* notification = trackedNotificationsMap.getValueAt(notificationIndex).data; + if (notification->getRecipientUserId() == userID) + { + notification->setState(util::State::INACTIVE); + trackedNotificationsMap.getValueAt(notificationIndex).state = RecordState::MODIFIED; + m_dataStore.saveNotifications(); + } } /* diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Config.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Config.h index 2eef19d..a2995b4 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Config.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Config.h @@ -29,6 +29,7 @@ namespace config namespace file { const size_t INITIAL_CAPACITY = 100; + const size_t GROWTH_FACTOR = 2; constexpr const char* DIRECTORY = "files/"; constexpr const char* INVENTORYITEM_FILE = "files/InventoryItem.dat"; constexpr const char* USER_FILE = "files/User.dat"; From 404d217504f8aeb1be3ba6a191f1cec52e58dc9c Mon Sep 17 00:00:00 2001 From: Joel Thomas Date: Sun, 14 Jun 2026 14:11:03 +0530 Subject: [PATCH 09/10] Clean up legacy code - Remove FileManager and related file-based persistence logic - Remove obsolete observer persistence utilities - Remove unused service APIs and includes - Delete duplicate DataStore mutex stubs - Perform general dead-code cleanup --- .gitignore | 4 +- .../Trenser.VehicleServiceSystem.vcxproj | 1 - ...enser.VehicleServiceSystem.vcxproj.filters | 5 +- .../core/patterns/Observer.h | 2 - .../datastores/DataStore.cpp | 32 -- .../datastores/DataStore.h | 17 +- .../models/ComboPackage.h | 1 + .../services/InventoryManagementService.cpp | 90 ------ .../services/InventoryManagementService.h | 5 - .../services/NotificationManagementService.h | 1 - .../services/PaymentManagementService.cpp | 118 ------- .../services/PaymentManagementService.h | 5 - .../services/ServiceManagementService.cpp | 294 ------------------ .../services/ServiceManagementService.h | 9 - .../services/UserManagementService.cpp | 1 - .../utilities/FileHelper.h | 63 ---- .../utilities/FileManager.h | 119 ------- .../utilities/InputHelper.h | 2 +- .../utilities/Utility.h | 46 --- 19 files changed, 13 insertions(+), 802 deletions(-) delete mode 100644 Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/FileManager.h diff --git a/.gitignore b/.gitignore index fe37065..37b6ea3 100644 --- a/.gitignore +++ b/.gitignore @@ -427,5 +427,5 @@ FodyWeavers.xsd *.msm *.msp -# CSV Files -*.csv +# DAT Files +*.dat diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj index b9a6f28..34bfc34 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj @@ -181,7 +181,6 @@ - diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters index e9b5831..c13b320 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters @@ -242,9 +242,6 @@ Header Files\Utilities - - Header Files\Utilities - Header Files\Utilities @@ -276,7 +273,7 @@ Header Files\DataStores\SharedMemory - Header Files + Header Files\DataStores \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/patterns/Observer.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/patterns/Observer.h index e9eb955..98e6f97 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/patterns/Observer.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/patterns/Observer.h @@ -7,8 +7,6 @@ Date: 19-May-2026 #pragma once -class Notification; - class Observer { public: diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.cpp index 9f72555..52b3e57 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.cpp @@ -144,11 +144,6 @@ bool DataStore::initialize() success = false; break; } - if (!SharedMemory::createOrOpenMapping(m_payments)) - { - success = false; - break; - } if (!SharedMemory::createOrOpenMapping(m_serviceManagementObservers)) { success = false; @@ -193,7 +188,6 @@ void DataStore::shutdown() SharedMemory::closeMapping(m_serviceBookings); SharedMemory::closeMapping(m_jobCards); SharedMemory::closeMapping(m_invoices); - SharedMemory::closeMapping(m_payments); SharedMemory::closeMapping(m_serviceManagementObservers); SharedMemory::closeMapping(m_paymentManagementObservers); SharedMemory::closeMapping(m_inventoryManagementObservers); @@ -565,32 +559,6 @@ void DataStore::saveInventoryManagementObservers(util::Map& saveObservers(m_inventoryManagementObservers, observers); } -/* -Function: lockDataStore -Description: Acquires exclusive access to the datastore. -Parameters: - - None -Returns: - - bool: True if the datastore was successfully locked, otherwise false -*/ -bool DataStore::lockDataStore() -{ - return false; -} - -/* -Function: unlockDataStore -Description: Releases exclusive access to the datastore. -Parameters: - - None -Returns: - - bool: True if the datastore was successfully unlocked, otherwise false -*/ -bool DataStore::unlockDataStore() -{ - return false; -} - /* Function: lockDataStore Description: Acquires the datastore mutex, providing diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.h index 62c585d..34268f4 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.h @@ -12,14 +12,14 @@ Date: 19-May-2026 #include "MappingInfo.h" #include "TrackedRecord.h" #include "SharedMemory.h" -class User; -class Notification; -class Service; -class ComboPackage; -class InventoryItem; -class ServiceBooking; -class JobCard; -class Invoice; +#include "User.h" +#include "Notification.h" +#include "Service.h" +#include "ComboPackage.h" +#include "InventoryItem.h" +#include "ServiceBooking.h" +#include "JobCard.h" +#include "Invoice.h" class DataStore { @@ -39,7 +39,6 @@ private: MappingInfo m_serviceBookings; MappingInfo m_jobCards; MappingInfo m_invoices; - MappingInfo m_payments; MappingInfo m_serviceManagementObservers; MappingInfo m_paymentManagementObservers; MappingInfo m_inventoryManagementObservers; diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ComboPackage.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ComboPackage.h index 941c2b3..29be6a9 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ComboPackage.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ComboPackage.h @@ -12,6 +12,7 @@ Date: 19-May-2026 #include "Enums.h" class Service; +struct SerializedComboPackage; class ComboPackage { diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.cpp index aed6f3a..32e2453 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.cpp @@ -12,7 +12,6 @@ Date: 22-May-2026 #include "Config.h" #include "Enums.h" #include "Factory.h" -#include "FileManager.h" #include "InventoryItem.h" #include "InventoryManagementService.h" #include "Timestamp.h" @@ -90,95 +89,6 @@ void InventoryManagementService::sendLowStockAlerts() } } -/* -Function: getObserverIDs -Description: Retrieves the IDs of all observers currently attached to the - InventoryManagementService. -Parameters: - - None -Returns: - - util::Vector: Vector of observer user IDs -*/ -util::Vector InventoryManagementService::getObserverIDs() -{ - util::Vector 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; -} - -/* -Function: loadInventoryItems -Description: Loads inventory items from persistent storage into the datastore. - Uses FileManager to deserialize inventory items from the configured file. -Parameters: - - None -Returns: - - void -*/ -void InventoryManagementService::loadInventoryItems() -{ - util::FileManager inventoryItemFileManager(config::file::INVENTORYITEM_FILE); - auto& inventoryItems = m_dataStore.getInventoryItems(); - auto inventoryItemsMap = inventoryItemFileManager.load(); - int numberOfInventoryItems = inventoryItemsMap.getSize(); - for (int index = 0; index < numberOfInventoryItems; index++) - { - inventoryItems[inventoryItemsMap.getKeyAt(index)] = inventoryItemsMap.getValueAt(index); - } -} - -/* -Function: saveInventoryItems -Description: Saves inventory items from the datastore to persistent storage. - Uses FileManager to serialize inventory items into the configured file. -Parameters: - - None -Returns: - - void -*/ -void InventoryManagementService::saveInventoryItems() -{ - util::FileManager inventoryItemFileManager(config::file::INVENTORYITEM_FILE); - auto& inventoryItems = m_dataStore.getInventoryItems(); - inventoryItemFileManager.save(inventoryItems); -} - -/* -Function: loadObservers -Description: Loads observer IDs from persistent storage and attaches corresponding - users as observers to the InventoryManagementService. -Parameters: - - None -Returns: - - void -*/ -void InventoryManagementService::loadObservers() -{ - util::loadObservers(config::file::INVENTORYMANAGEMENTOBSERVERS, this, m_dataStore); -} - -/* -Function: saveObservers -Description: Saves the current observer IDs of the InventoryManagementService - to persistent storage for future retrieval. -Parameters: - - None -Returns: - - void -*/ -void InventoryManagementService::saveObservers() -{ - util::saveObservers(config::file::INVENTORYMANAGEMENTOBSERVERS, this); -} - /* Function: addInventoryItem Description: Creates a new inventory item using the Factory and inserts it diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.h index f5db383..2c3736c 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.h @@ -21,7 +21,6 @@ class InventoryManagementService : public NotificationManagementService private: DataStore& m_dataStore; static util::Map m_observers; - util::Vector getObserverIDs() override; public: InventoryManagementService() : m_dataStore(DataStore::getInstance()) {} util::Map getInventoryItems(); @@ -33,8 +32,4 @@ public: void sendNotification(User* user, const std::string& title, const std::string& message) override; void attach(User* user) override; void detach(User* user) override; - void loadInventoryItems(); - void saveInventoryItems(); - void loadObservers(); - void saveObservers(); }; diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/NotificationManagementService.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/NotificationManagementService.h index 33d214a..18d0dda 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/NotificationManagementService.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/NotificationManagementService.h @@ -19,5 +19,4 @@ public: virtual void sendNotification(User* recipient, const std::string& title, const std::string& message) = 0; virtual void attach(User* user) = 0; virtual void detach(User* user) = 0; - virtual util::Vector getObserverIDs() = 0; }; diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp index 1ebb273..b8b9af1 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp @@ -11,7 +11,6 @@ Date: 20-May-2026 #include "Config.h" #include "Enums.h" #include "Factory.h" -#include "FileManager.h" #include "InventoryItem.h" #include "Invoice.h" #include "JobCard.h" @@ -149,123 +148,6 @@ void PaymentManagementService::sendPaymentReminders() } } -/* -Function: getObserverIDs -Description: Retrieves the IDs of all observers currently attached to the - PaymentManagementService. -Parameters: - - None -Returns: - - util::Vector: Vector of observer user IDs -*/ -util::Vector PaymentManagementService::getObserverIDs() -{ - util::Vector 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; -} - -/* -Function: loadInvoices -Description: Loads invoices from persistent storage into the datastore. - Validates associated service bookings and inventory parts before - attaching them to each invoice. Throws exceptions if invalid IDs - are encountered. -Parameters: - - None -Returns: - - void -Throws: - - std::runtime_error if a booking ID or part ID is invalid -*/ -void PaymentManagementService::loadInvoices() -{ - util::FileManager invoiceFileManager(config::file::INVOICE_FILE); - auto& invoices = m_dataStore.getInvoices(); - auto& serviceBookings = m_dataStore.getServiceBookings(); - auto& inventoryItems = m_dataStore.getInventoryItems(); - auto invoicesMap = invoiceFileManager.load(); - for (int invoiceIndex = 0; invoiceIndex < invoicesMap.getSize(); invoiceIndex++) - { - Invoice* invoice = invoicesMap.getValueAt(invoiceIndex); - int bookingIndex = serviceBookings.find(invoice->getBookingId()); - if (bookingIndex == -1) - { - throw std::runtime_error("Invalid Booking ID"); - } - ServiceBooking* booking = serviceBookings.getValueAt(bookingIndex); - invoice->setBooking(booking); - util::Map invoiceParts; - auto& partIDs = invoice->getPartIDs(); - for (int partIndex = 0; partIndex < partIDs.getSize(); partIndex++) - { - const std::string& partID = partIDs[partIndex]; - int inventoryIndex = inventoryItems.find(partID); - if (inventoryIndex == -1) - { - throw std::runtime_error("Invalid Part ID"); - } - invoiceParts[partID] = inventoryItems.getValueAt(inventoryIndex); - } - invoice->setParts(invoiceParts); - invoices[invoice->getId()] = invoice; - } -} - -/* -Function: saveInvoices -Description: Saves invoices from the datastore to persistent storage. - Uses FileManager to serialize invoices into the configured file. -Parameters: - - None -Returns: - - void -*/ -void PaymentManagementService::saveInvoices() -{ - util::FileManager invoiceFileManager(config::file::INVOICE_FILE); - auto& invoices = m_dataStore.getInvoices(); - invoiceFileManager.save(invoices); -} - -/* -Function: loadObservers -Description: Loads observer IDs from persistent storage and attaches corresponding - users as observers to the PaymentManagementService. -Parameters: - - None -Returns: - - void -Throws: - - std::runtime_error if an observer ID is invalid (not found in datastore) -*/ -void PaymentManagementService::loadObservers() -{ - util::loadObservers(config::file::PAYMENTMANAGEMENTOBSERVERS, this, m_dataStore); -} - -/* -Function: saveObservers -Description: Saves the current observer IDs of the PaymentManagementService - to persistent storage for future retrieval. -Parameters: - - None -Returns: - - void -*/ -void PaymentManagementService::saveObservers() -{ - util::saveObservers(config::file::PAYMENTMANAGEMENTOBSERVERS, this); -} - /* Function: createInventoryItemsMap (static helper) Description: Builds a map of inventory items required for a given service and adds them to the booking’s inventory map. diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.h index 8961a2d..f6e2e75 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.h @@ -22,7 +22,6 @@ class PaymentManagementService : public NotificationManagementService private: DataStore& m_dataStore; static util::Map m_observers; - util::Vector getObserverIDs() override; public: PaymentManagementService() : m_dataStore(DataStore::getInstance()) {} void generateInvoice(ServiceBooking* booking); @@ -34,8 +33,4 @@ public: void sendNotification(User* user, const std::string& title, const std::string& message) override; void attach(User* user) override; void detach(User* user) override; - void loadInvoices(); - void saveInvoices(); - void loadObservers(); - void saveObservers(); }; diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp index 102ba31..e294249 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp @@ -14,7 +14,6 @@ Date:19-May-2026 #include "DataStore.h" #include "Enums.h" #include "Factory.h" -#include "FileManager.h" #include "InventoryItem.h" #include "JobCard.h" #include "NotificationManagementService.h" @@ -199,299 +198,6 @@ void ServiceManagementService::sendNotification(User* user, const std::string& t m_dataStore.saveNotifications(); } -/* -Function: loadServices -Description: Loads services from persistent storage into the datastore. - Validates required inventory items and attaches them to each service. -Parameters: - - None -Returns: - - void -Throws: - - std::runtime_error if an inventory item ID is invalid -*/ -void ServiceManagementService::loadServices() -{ - util::FileManager serviceFileManager(config::file::SERVICE_FILE); - auto& services = m_dataStore.getServices(); - auto& inventoryItems = m_dataStore.getInventoryItems(); - auto servicesMap = serviceFileManager.load(); - for (int serviceIndex = 0; serviceIndex < servicesMap.getSize(); serviceIndex++) - { - Service* service = servicesMap.getValueAt(serviceIndex); - services[service->getId()] = service; - util::Map inventoryItemsMap; - auto& inventoryItemIDs = service->getRequiredInventoryItemIDs(); - for (int inventoryItemIndex = 0; inventoryItemIndex < inventoryItemIDs.getSize(); inventoryItemIndex++) - { - const std::string& inventoryItemID = inventoryItemIDs[inventoryItemIndex]; - int index = inventoryItems.find(inventoryItemID); - if (index == -1) - { - throw std::runtime_error("Invalid Inventory Item ID"); - } - inventoryItemsMap[inventoryItemID] = inventoryItems.getValueAt(index); - } - service->setRequiredInventoryItems(inventoryItemsMap); - } -} - -/* -Function: saveServices -Description: Saves services from the datastore to persistent storage. - Uses FileManager to serialize services into the configured file. -Parameters: - - None -Returns: - - void -*/ -void ServiceManagementService::saveServices() -{ - util::FileManager serviceFileManager(config::file::SERVICE_FILE); - auto& services = m_dataStore.getServices(); - serviceFileManager.save(services); -} - -/* -Function: loadComboPackages -Description: Loads combo packages from persistent storage into the datastore. - Validates associated services and attaches them to each package. -Parameters: - - None -Returns: - - void -Throws: - - std::runtime_error if a service ID is invalid -*/ -void ServiceManagementService::loadComboPackages() -{ - util::FileManager comboPackageFileManager(config::file::COMBOPACKAGE_FILE); - auto& comboPackages = m_dataStore.getComboPackages(); - auto& services = m_dataStore.getServices(); - auto comboPackagesMap = comboPackageFileManager.load(); - for (int packageIndex = 0; packageIndex < comboPackagesMap.getSize(); packageIndex++) - { - ComboPackage* comboPackage = comboPackagesMap.getValueAt(packageIndex); - util::Map packageServices; - auto& serviceIDs = comboPackage->getServiceIDs(); - for (int serviceIndex = 0; serviceIndex < serviceIDs.getSize(); serviceIndex++) - { - const std::string& serviceID = serviceIDs[serviceIndex]; - int serviceMapIndex = services.find(serviceID); - if (serviceMapIndex == -1) - { - throw std::runtime_error("Invalid Service ID"); - } - packageServices[serviceID] = services.getValueAt(serviceMapIndex); - } - comboPackage->setServices(packageServices); - comboPackages[comboPackage->getId()] = comboPackage; - } -} - -/* -Function: saveComboPackages -Description: Saves combo packages from the datastore to persistent storage. - Uses FileManager to serialize combo packages into the configured file. -Parameters: - - None -Returns: - - void -*/ -void ServiceManagementService::saveComboPackages() -{ - util::FileManager comboPackageFileManager(config::file::COMBOPACKAGE_FILE); - auto& comboPackages = m_dataStore.getComboPackages(); - comboPackageFileManager.save(comboPackages); -} - -/* -Function: loadServiceBookings -Description: Loads service bookings from persistent storage into the datastore. - Validates associated services, customers, and technicians before - attaching them to each booking. -Parameters: - - None -Returns: - - void -Throws: - - std::runtime_error if a service ID, customer ID, or technician ID is invalid - - std::runtime_error if a user is not of the expected type (customer/technician) -*/ -void ServiceManagementService::loadServiceBookings() -{ - util::FileManager bookingFileManager(config::file::SERVICEBOOKING_FILE); - auto& serviceBookings = m_dataStore.getServiceBookings(); - auto& services = m_dataStore.getServices(); - auto& users = m_dataStore.getUsers(); - auto bookingsMap = bookingFileManager.load(); - for (int bookingIndex = 0; bookingIndex < bookingsMap.getSize(); bookingIndex++) - { - ServiceBooking* booking = bookingsMap.getValueAt(bookingIndex); - util::Map bookingServices; - auto& serviceIDs = booking->getServiceIDs(); - for (int serviceIndex = 0; serviceIndex < serviceIDs.getSize(); serviceIndex++) - { - const std::string& serviceID = serviceIDs[serviceIndex]; - int serviceMapIndex = services.find(serviceID); - if (serviceMapIndex == -1) - { - throw std::runtime_error("Invalid Service ID"); - } - - bookingServices[serviceID] = services.getValueAt(serviceMapIndex); - } - booking->setServices(bookingServices); - int customerIndex = users.find(booking->getCustomerId()); - if (customerIndex == -1) - { - throw std::runtime_error("Invalid Customer ID"); - } - User* customer = users.getValueAt(customerIndex); - if (customer->getUserType() != util::UserType::CUSTOMER) - { - throw std::runtime_error("User is not a customer"); - } - booking->setCustomer(customer); - const std::string& technicianId = booking->getAssignedTechnicianId(); - if (!technicianId.empty()) - { - int technicianIndex = users.find(technicianId); - if (technicianIndex == -1) - { - throw std::runtime_error("Invalid Technician ID"); - } - User* technician = users.getValueAt(technicianIndex); - if (technician->getUserType() != util::UserType::TECHNICIAN) - { - throw std::runtime_error("User is not a technician"); - } - booking->setAssignedTechnician(technician); - } - serviceBookings[booking->getId()] = booking; - } -} - -/* -Function: saveServiceBookings -Description: Saves service bookings from the datastore to persistent storage. - Uses FileManager to serialize bookings into the configured file. -Parameters: - - None -Returns: - - void -*/ -void ServiceManagementService::saveServiceBookings() -{ - util::FileManager bookingFileManager(config::file::SERVICEBOOKING_FILE); - auto& serviceBookings = m_dataStore.getServiceBookings(); - bookingFileManager.save(serviceBookings); -} - -/* -Function: loadJobCards -Description: Loads job cards from persistent storage into the datastore. - Validates associated bookings, services, and technicians before - attaching them to each job card. -Parameters: - - None -Returns: - - void -Throws: - - std::runtime_error if a booking ID, service ID, or technician ID is invalid - - std::runtime_error if a service does not belong to the booking - - std::runtime_error if a user is not a technician -*/ -void ServiceManagementService::loadJobCards() -{ - util::FileManager jobCardFileManager(config::file::JOBCARD_FILE); - auto& jobCards = m_dataStore.getJobCards(); - auto& serviceBookings = m_dataStore.getServiceBookings(); - auto& services = m_dataStore.getServices(); - auto& users = m_dataStore.getUsers(); - auto jobCardsMap = jobCardFileManager.load(); - for (int jobCardIndex = 0; jobCardIndex < jobCardsMap.getSize(); jobCardIndex++) - { - JobCard* jobCard = jobCardsMap.getValueAt(jobCardIndex); - int bookingIndex = serviceBookings.find(jobCard->getBookingId()); - if (bookingIndex == -1) - { - throw std::runtime_error("Invalid Booking ID"); - } - ServiceBooking* booking = serviceBookings.getValueAt(bookingIndex); - jobCard->setBooking(booking); - int serviceIndex = services.find(jobCard->getServiceId()); - if (serviceIndex == -1) - { - throw std::runtime_error("Invalid Service ID"); - } - Service* service = services.getValueAt(serviceIndex); - if (booking->getServices().find(jobCard->getServiceId()) == -1) - { - throw std::runtime_error("Service does not belong to booking"); - } - jobCard->setService(service); - int technicianIndex = users.find(jobCard->getTechnicianId()); - if (technicianIndex == -1) - { - throw std::runtime_error("Invalid Technician ID"); - } - User* technician = users.getValueAt(technicianIndex); - if (technician->getUserType() != util::UserType::TECHNICIAN) - { - throw std::runtime_error("User is not a technician"); - } - jobCard->setTechnician(technician); - jobCards[jobCard->getId()] = jobCard; - } -} - -/* -Function: saveJobCards -Description: Saves job cards from the datastore to persistent storage. - Uses FileManager to serialize job cards into the configured file. -Parameters: - - None -Returns: - - void -*/ -void ServiceManagementService::saveJobCards() -{ - util::FileManager jobCardFileManager(config::file::JOBCARD_FILE); - auto& jobCards = m_dataStore.getJobCards(); - jobCardFileManager.save(jobCards); -} - -/* -Function: loadObservers -Description: Loads observer IDs from persistent storage and attaches corresponding - users as observers to the ServiceManagementService. -Parameters: - - None -Returns: - - void -Throws: - - std::runtime_error if an observer ID is invalid (not found in datastore) -*/ -void ServiceManagementService::loadObservers() -{ - util::loadObservers(config::file::SERVICEMANAGEMENTOBSERVERS, this, m_dataStore); -} - -/* -Function: saveObservers -Description: Saves the current observer IDs of the ServiceManagementService - to persistent storage for future retrieval. -Parameters: - - None -Returns: - - void -*/ -void ServiceManagementService::saveObservers() -{ - util::saveObservers(config::file::SERVICEMANAGEMENTOBSERVERS, this); -} - /* Function: restoreInventory Description: Restores inventory quantities for all required items in the services associated diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.h index f1ff966..2fcfd6d 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.h @@ -23,7 +23,6 @@ class ServiceManagementService : public NotificationManagementService private: DataStore& m_dataStore; static util::Map m_observers; - util::Vector getObserverIDs() override; public: ServiceManagementService() : m_dataStore(DataStore::getInstance()) {} util::Map getServices(); @@ -45,12 +44,4 @@ public: void sendNotification(User* user, const std::string& title, const std::string& message) override; void attach(User* user) override; void detach(User* user) override; - void loadServices(); - void saveServices(); - void loadComboPackages(); - void saveComboPackages(); - void loadServiceBookings(); - void saveServiceBookings(); - void loadJobCards(); - void saveJobCards(); }; diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp index 1be3a40..e923e1c 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp @@ -11,7 +11,6 @@ Date:19-May-2026 #include "Config.h" #include "Enums.h" #include "Factory.h" -#include "FileManager.h" #include "InventoryManagementService.h" #include "Notification.h" #include "PaymentManagementService.h" diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/FileHelper.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/FileHelper.h index c8bf96f..f73fba4 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/FileHelper.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/FileHelper.h @@ -43,67 +43,4 @@ namespace util position++; } } - - /* - Function: loadRecords - Description: Loads records from a given file path into a vector of strings. - Skips the header line if present. Creates the file if it does not exist. - Parameters: - - filePath: const std::string&, path to the file - Returns: - - util::Vector: Vector containing all records (excluding header) - Throws: - - None (creates file if missing) - */ - inline util::Vector loadRecords(const std::string& filePath) - { - util::Vector records; - std::ifstream file(filePath); - if (!file.is_open()) - { - ensureDirectoryExists(filePath); - std::ofstream newFile(filePath); - newFile.close(); - file.open(filePath); - } - std::string line; - bool isHeader = true; - while (std::getline(file, line)) - { - if (isHeader) - { - isHeader = false; - continue; - } - records.push_back(line); - } - return records; - } - - /* - Function: saveRecords - Description: Saves records to a given file path. Overwrites existing content - and writes a header line followed by all records. - Parameters: - - filePath: const std::string&, path to the file - - records: const util::Vector&, vector of records to save - Returns: - - void - Throws: - - std::runtime_error if the file cannot be opened for writing - */ - inline void saveRecords(const std::string& filePath, const util::Vector& records) - { - std::ofstream file(filePath, std::ios::trunc); - if (!file.is_open()) - { - throw std::runtime_error("Failed to open file " + filePath); - } - file << "Values" << '\n'; - int numberOfRecords = records.getSize(); - for (int index = 0; index < numberOfRecords; index++) - { - file << records[index] << '\n'; - } - } } \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/FileManager.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/FileManager.h deleted file mode 100644 index 1ea66c7..0000000 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/FileManager.h +++ /dev/null @@ -1,119 +0,0 @@ -/* -File: FileManager.h -Description: Declares and implements a generic FileManager template class for - loading and saving objects to and from files. Uses serialization - and deserialization methods defined in the object type T. - Provides persistence support for system entities such as Users, - Services, InventoryItems, etc. -Author: Trenser -Date: 22-May-2026 -*/ - -#pragma once -#include -#include -#include -#include "Vector.h" -#include "Map.h" -#include "FileHelper.h" - -namespace util -{ - template using objects = util::Map; - - template - class FileManager - { - private: - std::string m_filePath; - public: - FileManager() : m_filePath("") {} - FileManager(const std::string& filePath) : m_filePath(filePath) {} - objects load(); - void save(const objects&); - }; - - /* - Function: load - Description: Loads records from the file into a map of objects. - Skips the header line, deserializes each record into an object of type T, - and stores them in a map keyed by object ID. - Parameters: - - None - Returns: - - util::Map containing deserialized objects - Throws: - - std::runtime_error if deserialization fails for any record - */ - template - objects FileManager::load() - { - objects records; - std::ifstream file(m_filePath); - if (!file.is_open()) - { - ensureDirectoryExists(m_filePath); - std::ofstream newFile(m_filePath); - newFile.close(); - file.open(m_filePath); - } - util::Vector lines; - std::string line; - while (std::getline(file, line)) - { - lines.push_back(line); - } - int numberOfLines = lines.getSize(); - bool isHeader = true; - for (int lineIndex = 0; lineIndex < numberOfLines; lineIndex++) - { - const auto& record = lines[lineIndex]; - if (isHeader) - { - isHeader = false; - continue; - } - auto object = T::deserialize(record); - if (!object) - { - throw std::runtime_error("Failed to deserialize record"); - } - records[object->getId()] = object; - } - return records; - } - - /* - Function: save - Description: Saves records to the file. Serializes each object of type T into a string, - writes a header line, and then writes all serialized records to the file. - Parameters: - - records: const util::Map&, map of objects to save - Returns: - - void - Throws: - - std::runtime_error if the file cannot be opened for writing - */ - template - void FileManager::save(const objects& records) - { - util::Vector lines; - lines.push_back(T::getHeaders()); - int numberOfRecords = records.getSize(); - for (int recordIndex = 0; recordIndex < numberOfRecords; recordIndex++) - { - const auto& record = records.getValueAt(recordIndex); - lines.push_back(record->serialize()); - } - std::ofstream file(m_filePath, std::ios::trunc); - if (!file.is_open()) - { - throw std::runtime_error("Failed to open file " + m_filePath); - } - int numberOfLines = lines.getSize(); - for (int lineIndex = 0; lineIndex < numberOfLines; lineIndex++) - { - file << lines[lineIndex] << '\n'; - } - } -} \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/InputHelper.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/InputHelper.h index dffc199..065a197 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/InputHelper.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/InputHelper.h @@ -28,7 +28,7 @@ namespace util if (!(std::cin >> value)) { std::cin.clear(); - std::cin.ignore(std::numeric_limits::max(), '\n'); + std::cin.ignore((std::numeric_limits::max)(), '\n'); throw std::runtime_error("Invalid console input"); } } diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Utility.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Utility.h index 9b6bc9d..56dd765 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Utility.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Utility.h @@ -54,52 +54,6 @@ namespace util return cost; } - /* - Function: loadObservers - Description: Loads observer IDs from a file and attaches the corresponding users - to the notification management service. Validates that each observer ID - exists in the datastore before attaching. - Parameters: - - filePath: const std::string&, path to the file containing observer IDs - - service: NotificationManagementService*, pointer to the notification service - - dataStore: DataStore&, reference to the datastore containing users - Returns: - - void - Throws: - - std::runtime_error if an observer ID is invalid (not found in datastore) - */ - inline void loadObservers(const std::string& filePath, NotificationManagementService* service, DataStore& dataStore) - { - auto observerIDs = util::loadRecords(filePath); - auto& users = dataStore.getUsers(); - for (int index = 0; index < observerIDs.getSize(); index++) - { - const std::string& observerID = observerIDs[index]; - int userIndex = users.find(observerID); - if (userIndex == -1) - { - throw std::runtime_error("Invalid Observer ID"); - } - service->attach(users.getValueAt(userIndex)); - } - } - - /* - Function: saveObservers - Description: Saves the current observer IDs from the notification management service - to a file for persistence. - Parameters: - - filePath: const std::string&, path to the file where observer IDs will be saved - - service: NotificationManagementService*, pointer to the notification service - Returns: - - void - */ - inline void saveObservers(const std::string& filePath, NotificationManagementService* service) - { - auto observerIDs = service->getObserverIDs(); - util::saveRecords(filePath, observerIDs); - } - template Map getObjects(const Map>& trackedRecords); From f484c62a1e7f06f888d9316a615ccb7b5b2b495c Mon Sep 17 00:00:00 2001 From: Joel Thomas Date: Sun, 14 Jun 2026 17:00:49 +0530 Subject: [PATCH 10/10] Fix cache refresh handling for unsaved records - Preserve NEW_RECORD entries during cache refresh - Prevent accidental deletion of pending datastore changes - Clean up only stale persisted records --- .../datastores/DataStore.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.h index 34268f4..265f8df 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.h @@ -230,9 +230,17 @@ void DataStore::refreshCache(util::Map>& cac for (int index = 0; index < oldCache.getSize(); ++index) { const std::string& id = oldCache.getKeyAt(index); + const TrackedRecord& localTrackedRecord = oldCache.getValueAt(index); if (cache.find(id) == -1) { - delete oldCache.getValueAt(index).data; + if (localTrackedRecord.state == RecordState::NEW_RECORD) + { + cache.insert(id, localTrackedRecord); + } + else + { + delete localTrackedRecord.data; + } } } } \ No newline at end of file