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)
{