diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj index d7f333c..7ae72bd 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj @@ -102,7 +102,7 @@ true _DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - $(ProjectDir)models;$(ProjectDir)controllers;$(ProjectDir)factories;$(ProjectDir)views;$(ProjectDir)services;$(ProjectDir)utilities;$(ProjectDir)core\patterns;$(ProjectDir)datastores;$(ProjectDir)core\sharedmemory;%(AdditionalIncludeDirectories) + $(ProjectDir)models;$(ProjectDir)controllers;$(ProjectDir)factories;$(ProjectDir)views;$(ProjectDir)services;$(ProjectDir)utilities;$(ProjectDir)core\patterns;$(ProjectDir)datastores;$(ProjectDir)core\sharedmemory;$(ProjectDir)core\events;%(AdditionalIncludeDirectories) Console @@ -117,7 +117,7 @@ true NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true - $(ProjectDir)models;$(ProjectDir)controllers;$(ProjectDir)factories;$(ProjectDir)views;$(ProjectDir)services;$(ProjectDir)utilities;$(ProjectDir)core\patterns;$(ProjectDir)datastores;$(ProjectDir)core\sharedmemory;%(AdditionalIncludeDirectories) + $(ProjectDir)models;$(ProjectDir)controllers;$(ProjectDir)factories;$(ProjectDir)views;$(ProjectDir)services;$(ProjectDir)utilities;$(ProjectDir)core\patterns;$(ProjectDir)datastores;$(ProjectDir)core\sharedmemory;$(ProjectDir)core\events;%(AdditionalIncludeDirectories) Console @@ -126,6 +126,7 @@ + @@ -153,6 +154,7 @@ + diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters index d354bcb..714382b 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters @@ -70,6 +70,12 @@ {0769afb6-f57d-4ae3-a1cf-ceca6e606af0} + + {85029bdb-6941-41dc-a3a7-9e5841671d8c} + + + {1050aca7-6f2c-4ccb-a446-db9c898c3599} + @@ -147,6 +153,9 @@ Source Files\Core\SharedMemory + + Source Files\Core\Events + @@ -275,5 +284,8 @@ Header Files\Core\SharedMemory + + Header Files\Core\Events + \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/events/EventManager.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/events/EventManager.cpp new file mode 100644 index 0000000..568a0e6 --- /dev/null +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/events/EventManager.cpp @@ -0,0 +1,225 @@ +/* +File: EventManager.cpp +Description: Implementation file containing the method definitions of the + EventManager class, including listener management and + interprocess event publishing. +Author: Trenser +Date:15-Jun-2026 +*/ + +#include +#include +#include "EventManager.h" + +namespace +{ + const std::string USER_DISABLED_EVENT = "userDisabled_"; + + const std::string NOTIFICATION_AVAILABLE_EVENT = "notificationAvailable_"; +} + +/* +Function: EventManager +Description: Constructs an EventManager instance with default values. +Parameter: None +Return type: None +*/ +EventManager::EventManager() + : + m_userDisabledEvent(NULL), + m_notificationAvailableEvent(NULL), + m_shutdownEvent(NULL), + m_running(false) {} + +/* +Function: ~EventManager +Description: Destroys the EventManager and performs final cleanup. +Parameter: None +Return type: None +*/ +EventManager::~EventManager() +{ + shutdown(); + if (m_listenerThread.joinable()) + { + m_listenerThread.join(); + } +} + +/* +Function: initialize +Description: Creates the user-specific events and starts the listener + thread. +Parameter: const std::string& userId - unique identifier of the user + std::function userDisabledCallback - callback for + user disable events + std::function notificationCallback - callback for + notification events +Return type: bool - true if initialization succeeds, false otherwise +*/ +bool EventManager::initialize(const std::string& userId, std::function userDisabledCallback, std::function notificationCallback) +{ + if (m_running.load()) + { + return false; + } + m_userDisabledCallback = userDisabledCallback; + m_notificationCallback = notificationCallback; + m_userDisabledEvent = CreateEventA(NULL, FALSE, FALSE, (USER_DISABLED_EVENT + userId).c_str()); + if (!m_userDisabledEvent) + { + return false; + } + if (GetLastError() == ERROR_ALREADY_EXISTS) + { + CloseHandle(m_userDisabledEvent); + m_userDisabledEvent = NULL; + throw std::runtime_error("Only one session allowed per user."); + } + m_notificationAvailableEvent = CreateEventA(NULL, FALSE, FALSE, (NOTIFICATION_AVAILABLE_EVENT + userId).c_str()); + if (!m_notificationAvailableEvent) + { + CloseHandle(m_userDisabledEvent); + m_userDisabledEvent = NULL; + return false; + } + m_shutdownEvent = CreateEventA(NULL, FALSE, FALSE, NULL); + if (!m_shutdownEvent) + { + CloseHandle(m_userDisabledEvent); + CloseHandle(m_notificationAvailableEvent); + m_userDisabledEvent = NULL; + m_notificationAvailableEvent = NULL; + return false; + } + m_running.store(true); + m_listenerThread = std::thread(&EventManager::run, this); + return true; +} + +/* +Function: shutdown +Description: Stops the listener thread and releases event resources. +Parameter: None +Return type: None +*/ +void EventManager::shutdown() +{ + if (!m_running.load()) + { + return; + } + m_running.store(false); + if (m_shutdownEvent) + { + SetEvent(m_shutdownEvent); + } + if (m_listenerThread.joinable()) + { + if (std::this_thread::get_id() != m_listenerThread.get_id()) + { + m_listenerThread.join(); + } + } + if (m_userDisabledEvent) + { + CloseHandle(m_userDisabledEvent); + m_userDisabledEvent = NULL; + } + if (m_notificationAvailableEvent) + { + CloseHandle(m_notificationAvailableEvent); + m_notificationAvailableEvent = NULL; + } + if (m_shutdownEvent) + { + CloseHandle(m_shutdownEvent); + m_shutdownEvent = NULL; + } +} + +/* +Function: run +Description: Waits for and dispatches user-related events. +Parameter: None +Return type: void +*/ +void EventManager::run() +{ + HANDLE handles[3]; + handles[0] = m_userDisabledEvent; + handles[1] = m_notificationAvailableEvent; + handles[2] = m_shutdownEvent; + while (m_running.load()) + { + DWORD result = WaitForMultipleObjects(3, handles, FALSE, INFINITE); + switch (result) + { + case WAIT_OBJECT_0: + try + { + if (m_userDisabledCallback) + { + m_userDisabledCallback(); + } + } + catch (const std::exception& exception) + { + std::cout << exception.what() << std::endl; + } + break; + case WAIT_OBJECT_0 + 1: + try + { + if (m_notificationCallback) + { + m_notificationCallback(); + } + } + catch (const std::exception& exception) + { + std::cout << exception.what() << std::endl; + } + break; + case WAIT_OBJECT_0 + 2: + return; + default: + break; + } + } +} + +/* +Function: sendUserDisabledEvent +Description: Publishes a user disabled event for a specific user. +Parameter: const std::string& userId - target user identifier +Return type: void +*/ +void EventManager::sendUserDisabledEvent(const std::string& userId) +{ + HANDLE eventHandle = CreateEventA(NULL, FALSE, FALSE, (USER_DISABLED_EVENT + userId).c_str()); + if (!eventHandle) + { + return; + } + SetEvent(eventHandle); + CloseHandle(eventHandle); +} + +/* +Function: sendNotificationAvailableEvent +Description: Publishes a notification available event for a specific + user. +Parameter: const std::string& userId - target user identifier +Return type: void +*/ +void EventManager::sendNotificationAvailableEvent(const std::string& userId) +{ + HANDLE eventHandle = CreateEventA(NULL, FALSE, FALSE, (NOTIFICATION_AVAILABLE_EVENT + userId).c_str()); + if (!eventHandle) + { + return; + } + SetEvent(eventHandle); + CloseHandle(eventHandle); +} \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/events/EventManager.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/events/EventManager.h new file mode 100644 index 0000000..01de6c4 --- /dev/null +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/events/EventManager.h @@ -0,0 +1,37 @@ +/* +File: EventManager.h +Description: Header file declaring the EventManager class, which manages + user-specific interprocess events for user disable and + notification availability updates. +Author: Trenser +Date:15-Jun-2026 +*/ + +#pragma once + +#include +#include +#include +#include +#include + +class EventManager +{ +private: + HANDLE m_userDisabledEvent; + HANDLE m_notificationAvailableEvent; + HANDLE m_shutdownEvent; + std::atomic m_running; + std::thread m_listenerThread; + std::function m_userDisabledCallback; + std::function m_notificationCallback; + void run(); + +public: + EventManager(); + ~EventManager(); + bool initialize(const std::string& userId, std::function userDisabledCallback, std::function notificationCallback); + void shutdown(); + static void sendUserDisabledEvent(const std::string& userId); + static void sendNotificationAvailableEvent(const std::string& userId); +}; \ 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 71d66b6..ac5682d 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/AuthenticationManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/AuthenticationManagementService.cpp @@ -8,12 +8,14 @@ Date:19-May-2026 */ #include +#include #include "AuthenticationManagementService.h" #include "User.h" #include "Utility.h" #include "DataStoreLockGuard.h" User* AuthenticationManagementService::m_authenticatedUser = nullptr; +EventManager AuthenticationManagementService::m_eventManager; /* Function: login @@ -37,6 +39,16 @@ bool AuthenticationManagementService::login(const std::string& username, const s if (password == user->getPassword()) { m_authenticatedUser = user; + m_eventManager.initialize( + user->getId(), + []() + { + std::cout << "USER_DISABLED event received" << std::endl; + }, + []() + { + std::cout << "NOTIFICATION_AVAILABLE event received" << std::endl; + }); return true; } return false; @@ -65,6 +77,7 @@ Return type: void */ void AuthenticationManagementService::logout() { + m_eventManager.shutdown(); m_authenticatedUser = nullptr; } diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/AuthenticationManagementService.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/AuthenticationManagementService.h index 47266a1..e1cb251 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/AuthenticationManagementService.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/AuthenticationManagementService.h @@ -9,6 +9,7 @@ Date:19-May-2026 #pragma once #include +#include "EventManager.h" #include "DataStore.h" class User; @@ -17,6 +18,7 @@ class AuthenticationManagementService { private: static User* m_authenticatedUser; + static EventManager m_eventManager; DataStore& m_dataStore; public: AuthenticationManagementService() : m_dataStore(DataStore::getInstance()) {} diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.cpp index 8e17739..a007ac1 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.cpp @@ -19,6 +19,7 @@ Date: 22-May-2026 #include "Utility.h" #include "Vector.h" #include "DataStoreLockGuard.h" +#include "EventManager.h" util::Map InventoryManagementService::m_observers{}; @@ -281,5 +282,6 @@ void InventoryManagementService::sendNotification(User* user, const std::string& auto& trackedNotificationsMap = m_dataStore.getNotifications(); trackedNotificationsMap.insert(notification->getId(), util::createNewRecord(notification)); m_dataStore.saveNotifications(); + EventManager::sendNotificationAvailableEvent(user->getId()); } diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp index dc42a5b..09bf1da 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp @@ -22,6 +22,7 @@ Date: 20-May-2026 #include "User.h" #include "Utility.h" #include "DataStoreLockGuard.h" +#include "EventManager.h" util::Map PaymentManagementService::m_observers{}; @@ -109,6 +110,7 @@ void PaymentManagementService::sendNotification(User* user, const std::string& t auto& trackedNotificationsMap = m_dataStore.getNotifications(); trackedNotificationsMap.insert(notification->getId(), util::createNewRecord(notification)); m_dataStore.saveNotifications(); + EventManager::sendNotificationAvailableEvent(user->getId()); } /* diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp index ed59380..cf438d0 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp @@ -27,6 +27,7 @@ Date:19-May-2026 #include "DataStoreLockGuard.h" #include "Utility.h" #include "DataStoreLockGuard.h" +#include "EventManager.h" /* Function: purchaseService @@ -199,6 +200,7 @@ void ServiceManagementService::sendNotification(User* user, const std::string& t auto& trackedNotificationsMap = m_dataStore.getNotifications(); trackedNotificationsMap.insert(notification->getId(), util::createNewRecord(notification)); m_dataStore.saveNotifications(); + EventManager::sendNotificationAvailableEvent(user->getId()); } /* diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp index e923e1c..ab85936 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp @@ -22,6 +22,7 @@ Date:19-May-2026 #include "Utility.h" #include "TrackedRecord.h" #include "DataStoreLockGuard.h" +#include "EventManager.h" /* Function: ensureAdminExists @@ -267,30 +268,38 @@ void UserManagementService::removeUser(const std::string& userID) InventoryManagementService inventoryManagementService; PaymentManagementService paymentManagementService; ServiceManagementService serviceManagementService; - DataStoreLockGuard lock(m_dataStore); - auto& trackedUsersMap = m_dataStore.getUsers(); - int index = trackedUsersMap.find(userID); - if (index != -1) + std::string removedUserID; { - User* user = trackedUsersMap.getValueAt(index).data; - if (user != nullptr) + DataStoreLockGuard lock(m_dataStore); + auto& trackedUsersMap = m_dataStore.getUsers(); + int index = trackedUsersMap.find(userID); + if (index != -1) { - if (user->getUserType() == util::UserType::CUSTOMER) + User* user = trackedUsersMap.getValueAt(index).data; + if (user != nullptr) { - serviceManagementService.cancelCustomerServiceBookings(userID); + if (user->getUserType() == util::UserType::CUSTOMER) + { + serviceManagementService.cancelCustomerServiceBookings(userID); + } + if (user->getUserType() == util::UserType::TECHNICIAN) + { + serviceManagementService.cancelTechnicianJobs(userID); + } + inventoryManagementService.detach(user); + paymentManagementService.detach(user); + serviceManagementService.detach(user); + user->setState(util::State::INACTIVE); + trackedUsersMap.getValueAt(index).state = RecordState::MODIFIED; + removedUserID = user->getId(); + m_dataStore.saveUsers(); } - if (user->getUserType() == util::UserType::TECHNICIAN) - { - serviceManagementService.cancelTechnicianJobs(userID); - } - inventoryManagementService.detach(user); - paymentManagementService.detach(user); - serviceManagementService.detach(user); - user->setState(util::State::INACTIVE); - trackedUsersMap.getValueAt(index).state = RecordState::MODIFIED; - m_dataStore.saveUsers(); } } + if (!removedUserID.empty()) + { + EventManager::sendUserDisabledEvent(removedUserID); + } } /*