Compare commits

..

9 Commits

Author SHA1 Message Date
joelthomastrenser 39251167c5 changes 2026-06-16 10:27:44 +05:30
joelthomastrenser b289ab4945 changes 2026-06-16 10:14:28 +05:30
joelthomastrenser 3456b2b3f1 docs 2026-06-16 03:46:02 +05:30
joelthomastrenser dbc9abae6c notification works 2026-06-16 03:37:29 +05:30
joelthomastrenser 9752a76cb2 Modularize 2026-06-16 03:20:49 +05:30
joelthomastrenser 505753cc77 disable working 2026-06-16 03:07:21 +05:30
joelthomastrenser 384a9b05b1 Somewhat working 2026-06-16 02:52:55 +05:30
joelthomastrenser e054076175 events 2026-06-16 01:54:17 +05:30
joelthomastrenser 329fc6e23f Move sharedmemory/ to core/ 2026-06-15 23:51:21 +05:30
18 changed files with 101 additions and 402 deletions
@@ -153,12 +153,9 @@
<ClCompile Include="core\sharedmemory\SharedMemory.cpp"> <ClCompile Include="core\sharedmemory\SharedMemory.cpp">
<Filter>Source Files\Core\SharedMemory</Filter> <Filter>Source Files\Core\SharedMemory</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="core\events\EventManager.cpp"> <ClCompile Include="EventManager.cpp">
<Filter>Source Files\Core\Events</Filter> <Filter>Source Files\Core\Events</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="views\Menu.cpp">
<Filter>Source Files\Views</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="utilities\InputHelper.h"> <ClInclude Include="utilities\InputHelper.h">
@@ -290,8 +287,5 @@
<ClInclude Include="core\events\EventManager.h"> <ClInclude Include="core\events\EventManager.h">
<Filter>Header Files\Core\Events</Filter> <Filter>Header Files\Core\Events</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="views\Menu.h">
<Filter>Header Files\Views</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>
@@ -234,17 +234,6 @@ void Controller::removeInventoryItem(const std::string& inventoryItemID)
m_inventoryManagementService.removeInventoryItem(inventoryItemID); m_inventoryManagementService.removeInventoryItem(inventoryItemID);
} }
/*
Function: removeServiceBooking
Description: Removes a service booking from the service management system by its booking ID.
Parameter: const std::string& bookingID - ID of the service booking
Return type: void
*/
void Controller::removeServiceBooking(const std::string& bookingID)
{
m_serviceManagementService.removeServiceBooking(bookingID);
}
/* /*
Function: addInventoryItemStock Function: addInventoryItemStock
Description: Adds stock to an existing inventory item in the inventory management service. Description: Adds stock to an existing inventory item in the inventory management service.
@@ -276,7 +265,6 @@ util::Map<std::string, const ServiceBooking*> Controller::getServiceBookings()
return readOnlyServiceBookings; return readOnlyServiceBookings;
} }
/* /*
Function: getServiceBookingsByUser Function: getServiceBookingsByUser
Description: Retrieves all service bookings for a specific user. Description: Retrieves all service bookings for a specific user.
@@ -58,7 +58,6 @@ public:
util::Map<std::string, const User*> getUsers(util::UserType userType); util::Map<std::string, const User*> getUsers(util::UserType userType);
void createJobCard(const std::string& bookingID, const std::string& technicianID, const std::string& serviceID); void createJobCard(const std::string& bookingID, const std::string& technicianID, const std::string& serviceID);
void createService(const std::string& name, const util::Vector<std::string>& inventoryItemIDs, double laborCost); void createService(const std::string& name, const util::Vector<std::string>& inventoryItemIDs, double laborCost);
void removeServiceBooking(const std::string& bookingID);
void removeService(const std::string& serviceID); void removeService(const std::string& serviceID);
util::Map<std::string, const JobCard*> getJobCardsByUser(); util::Map<std::string, const JobCard*> getJobCardsByUser();
void updateJobStatus(const std::string& jobID); void updateJobStatus(const std::string& jobID);
@@ -358,7 +358,7 @@ util::Map<std::string, TrackedRecord<ServiceBooking>>& DataStore::getServiceBook
{ {
throw std::runtime_error("Invalid service index."); throw std::runtime_error("Invalid service index.");
} }
auto& currentService = services.getValueAt(serviceIndex); auto currentService = services.getValueAt(serviceIndex);
servicesInBooking[currentServiceId] = currentService.data; servicesInBooking[currentServiceId] = currentService.data;
} }
serviceBooking->setServices(servicesInBooking); serviceBooking->setServices(servicesInBooking);
@@ -369,7 +369,7 @@ util::Map<std::string, TrackedRecord<ServiceBooking>>& DataStore::getServiceBook
{ {
throw std::runtime_error("Invalid user index."); throw std::runtime_error("Invalid user index.");
} }
auto& customer = users.getValueAt(userIndex); auto customer = users.getValueAt(userIndex);
serviceBooking->setCustomer(customer.data); serviceBooking->setCustomer(customer.data);
} }
if (!serviceBooking->getAssignedTechnicianId().empty()) if (!serviceBooking->getAssignedTechnicianId().empty())
@@ -379,7 +379,7 @@ util::Map<std::string, TrackedRecord<ServiceBooking>>& DataStore::getServiceBook
{ {
throw std::runtime_error("Invalid technician index."); throw std::runtime_error("Invalid technician index.");
} }
auto& technician = users.getValueAt(technicianIndex); auto technician = users.getValueAt(technicianIndex);
serviceBooking->setAssignedTechnician(technician.data); serviceBooking->setAssignedTechnician(technician.data);
} }
} }
@@ -415,7 +415,7 @@ util::Map<std::string, TrackedRecord<JobCard>>& DataStore::getJobCards()
{ {
throw std::runtime_error("Invalid booking ID: " + bookingId); throw std::runtime_error("Invalid booking ID: " + bookingId);
} }
auto& trackedBooking = serviceBookings.getValueAt(bookingIndex); auto trackedBooking = serviceBookings.getValueAt(bookingIndex);
jobCard->setBooking(trackedBooking.data); jobCard->setBooking(trackedBooking.data);
const std::string& serviceId = jobCard->getServiceId(); const std::string& serviceId = jobCard->getServiceId();
int serviceIndex = services.find(serviceId); int serviceIndex = services.find(serviceId);
@@ -423,7 +423,7 @@ util::Map<std::string, TrackedRecord<JobCard>>& DataStore::getJobCards()
{ {
throw std::runtime_error("Invalid service ID: " + serviceId); throw std::runtime_error("Invalid service ID: " + serviceId);
} }
auto& trackedService = services.getValueAt(serviceIndex); auto trackedService = services.getValueAt(serviceIndex);
jobCard->setService(trackedService.data); jobCard->setService(trackedService.data);
const std::string& technicianId = jobCard->getTechnicianId(); const std::string& technicianId = jobCard->getTechnicianId();
if (!technicianId.empty()) if (!technicianId.empty())
@@ -433,7 +433,7 @@ util::Map<std::string, TrackedRecord<JobCard>>& DataStore::getJobCards()
{ {
throw std::runtime_error("Invalid technician ID: " + technicianId); throw std::runtime_error("Invalid technician ID: " + technicianId);
} }
auto& trackedTechnician = users.getValueAt(technicianIndex); auto trackedTechnician = users.getValueAt(technicianIndex);
jobCard->setTechnician(trackedTechnician.data); jobCard->setTechnician(trackedTechnician.data);
} }
} }
@@ -691,7 +691,7 @@ void DataStore::saveObservers(MappingInfo& mapping, util::Map<std::string, User*
SharedMemory::setRecordCount(mapping, observerCount); SharedMemory::setRecordCount(mapping, observerCount);
for (size_t index = 0; index < observerCount; index++) for (size_t index = 0; index < observerCount; index++)
{ {
SerializedObserver serializedObserver{}; SerializedObserver serializedObserver;
User* user = observers.getValueAt(static_cast<int>(index)); User* user = observers.getValueAt(static_cast<int>(index));
strcpy_s(serializedObserver.id, sizeof(serializedObserver.id), user->getId().c_str()); strcpy_s(serializedObserver.id, sizeof(serializedObserver.id), user->getId().c_str());
SerializedObserver* destination = static_cast<SerializedObserver*>(SharedMemory::getRecordAddress(mapping, index)); SerializedObserver* destination = static_cast<SerializedObserver*>(SharedMemory::getRecordAddress(mapping, index));
@@ -220,12 +220,6 @@ void DataStore::refreshCache(util::Map<std::string, TrackedRecord<TObject>>& cac
if (oldIndex != -1) if (oldIndex != -1)
{ {
TrackedRecord<TObject>& oldRecord = oldCache.getValueAt(oldIndex); TrackedRecord<TObject>& oldRecord = oldCache.getValueAt(oldIndex);
if (oldRecord.state == RecordState::MODIFIED)
{
delete refreshedRecord.data;
cache.insert(id, oldRecord);
continue;
}
*oldRecord.data = *refreshedRecord.data; *oldRecord.data = *refreshedRecord.data;
oldRecord.slotIndex = refreshedRecord.slotIndex; oldRecord.slotIndex = refreshedRecord.slotIndex;
oldRecord.state = refreshedRecord.state; oldRecord.state = refreshedRecord.state;
@@ -14,29 +14,10 @@ Date:19-May-2026
#include "DataStoreLockGuard.h" #include "DataStoreLockGuard.h"
User* AuthenticationManagementService::m_authenticatedUser = nullptr; User* AuthenticationManagementService::m_authenticatedUser = nullptr;
bool AuthenticationManagementService::m_isAuthorized = false;
EventManager AuthenticationManagementService::m_eventManager; EventManager AuthenticationManagementService::m_eventManager;
HANDLE AuthenticationManagementService::m_accountDisabledEvent = NULL; HANDLE AuthenticationManagementService::m_accountDisabledEvent = NULL;
HANDLE AuthenticationManagementService::m_notificationsAvailableEvent = NULL; HANDLE AuthenticationManagementService::m_notificationsAvailableEvent = NULL;
/*
Function: ensureAuthorization
Description: Verifies that a user is currently authenticated before allowing
access to a protected operation. Throws an exception if no
authorized user session exists.
Parameter: None
Return type: void
Throws: std::runtime_error - if the user is not authorized
*/
void AuthenticationManagementService::ensureAuthorization()
{
if (!m_authenticatedUser || !m_isAuthorized)
{
throw std::runtime_error("You are not authorized to do this operation!");
}
}
/* /*
Function: login Function: login
Description: Authenticates a user by checking the provided username and password Description: Authenticates a user by checking the provided username and password
@@ -59,19 +40,18 @@ bool AuthenticationManagementService::login(const std::string& username, const s
if (password == user->getPassword()) if (password == user->getPassword())
{ {
m_authenticatedUser = user; m_authenticatedUser = user;
m_isAuthorized = true;
m_eventManager.initialize( m_eventManager.initialize(
user->getId(), user->getId(),
[]() []()
{ {
if (m_accountDisabledEvent) if (m_accountDisabledEvent)
{ {
AuthenticationManagementService::m_isAuthorized = false;
SetEvent(m_accountDisabledEvent); SetEvent(m_accountDisabledEvent);
} }
}, },
[]() []()
{ {
HANDLE eventHandle = OpenEventA(EVENT_MODIFY_STATE, FALSE, "VehicleServiceSystem_NotificationAvailable");
if (m_notificationsAvailableEvent) if (m_notificationsAvailableEvent)
{ {
SetEvent(m_notificationsAvailableEvent); SetEvent(m_notificationsAvailableEvent);
@@ -107,7 +87,6 @@ void AuthenticationManagementService::logout()
{ {
m_eventManager.shutdown(); m_eventManager.shutdown();
m_authenticatedUser = nullptr; m_authenticatedUser = nullptr;
m_isAuthorized = false;
m_accountDisabledEvent = NULL; m_accountDisabledEvent = NULL;
m_notificationsAvailableEvent = NULL; m_notificationsAvailableEvent = NULL;
} }
@@ -121,7 +100,6 @@ Return type: void
*/ */
void AuthenticationManagementService::changePassword(const std::string& newPassword) void AuthenticationManagementService::changePassword(const std::string& newPassword)
{ {
AuthenticationManagementService::ensureAuthorization();
DataStoreLockGuard lock(m_dataStore); DataStoreLockGuard lock(m_dataStore);
auto& trackedUsersMap = m_dataStore.getUsers(); auto& trackedUsersMap = m_dataStore.getUsers();
if (m_authenticatedUser == nullptr) if (m_authenticatedUser == nullptr)
@@ -146,8 +124,8 @@ Parameter: HANDLE accountDisabledEvent - account disabled event handle
HANDLE notificationAvailableEvent - notification event handle HANDLE notificationAvailableEvent - notification event handle
Return type: void Return type: void
*/ */
void AuthenticationManagementService::registerEvents(HANDLE accountDisabledEvent, HANDLE notificationAvailableEvent) void AuthenticationManagementService::registerEvents(HANDLE accountDisabledEvent, HANDLE notifictionAvailableEvent)
{ {
m_accountDisabledEvent = accountDisabledEvent; m_accountDisabledEvent = accountDisabledEvent;
m_notificationsAvailableEvent = notificationAvailableEvent; m_notificationsAvailableEvent = notifictionAvailableEvent;
} }
@@ -19,14 +19,12 @@ class AuthenticationManagementService
{ {
private: private:
static User* m_authenticatedUser; static User* m_authenticatedUser;
static bool m_isAuthorized;
static EventManager m_eventManager; static EventManager m_eventManager;
static HANDLE m_accountDisabledEvent; static HANDLE m_accountDisabledEvent;
static HANDLE m_notificationsAvailableEvent; static HANDLE m_notificationsAvailableEvent;
DataStore& m_dataStore; DataStore& m_dataStore;
public: public:
AuthenticationManagementService() : m_dataStore(DataStore::getInstance()) {} AuthenticationManagementService() : m_dataStore(DataStore::getInstance()) {}
static void ensureAuthorization();
bool login(const std::string& username, const std::string& password); bool login(const std::string& username, const std::string& password);
void logout(); void logout();
void changePassword(const std::string& newPassword); void changePassword(const std::string& newPassword);
@@ -14,7 +14,6 @@ Date: 22-May-2026
#include "Factory.h" #include "Factory.h"
#include "InventoryItem.h" #include "InventoryItem.h"
#include "InventoryManagementService.h" #include "InventoryManagementService.h"
#include "AuthenticationManagementService.h"
#include "Timestamp.h" #include "Timestamp.h"
#include "User.h" #include "User.h"
#include "Utility.h" #include "Utility.h"
@@ -103,7 +102,6 @@ Return type: void
*/ */
void InventoryManagementService::addInventoryItem(const std::string& partName, int quantity, double price) void InventoryManagementService::addInventoryItem(const std::string& partName, int quantity, double price)
{ {
AuthenticationManagementService::ensureAuthorization();
DataStoreLockGuard lock(m_dataStore); DataStoreLockGuard lock(m_dataStore);
auto& trackedInventoryItemMap = m_dataStore.getInventoryItems(); auto& trackedInventoryItemMap = m_dataStore.getInventoryItems();
InventoryItem* newItem = Factory::getObject<InventoryItem>(partName, quantity, price); InventoryItem* newItem = Factory::getObject<InventoryItem>(partName, quantity, price);
@@ -120,7 +118,6 @@ Return type: void
*/ */
void InventoryManagementService::addInventoryItemStock(const std::string& selectedItemId, int quantity) void InventoryManagementService::addInventoryItemStock(const std::string& selectedItemId, int quantity)
{ {
AuthenticationManagementService::ensureAuthorization();
DataStoreLockGuard lock(m_dataStore); DataStoreLockGuard lock(m_dataStore);
auto& trackedInventoryItemMap = m_dataStore.getInventoryItems(); auto& trackedInventoryItemMap = m_dataStore.getInventoryItems();
int index = trackedInventoryItemMap.find(selectedItemId); int index = trackedInventoryItemMap.find(selectedItemId);
@@ -147,7 +144,6 @@ Return type: util::Map<std::string, InventoryItem*>
*/ */
util::Map<std::string, InventoryItem*> InventoryManagementService::getInventoryItems() util::Map<std::string, InventoryItem*> InventoryManagementService::getInventoryItems()
{ {
AuthenticationManagementService::ensureAuthorization();
DataStoreLockGuard lock(m_dataStore); DataStoreLockGuard lock(m_dataStore);
auto& trackedInventoryItemMap = m_dataStore.getInventoryItems(); auto& trackedInventoryItemMap = m_dataStore.getInventoryItems();
auto inventoryMap = util::getObjects(trackedInventoryItemMap); auto inventoryMap = util::getObjects(trackedInventoryItemMap);
@@ -162,7 +158,6 @@ Return type: void
*/ */
void InventoryManagementService::removeInventoryItem(const std::string& inventoryItemID) void InventoryManagementService::removeInventoryItem(const std::string& inventoryItemID)
{ {
AuthenticationManagementService::ensureAuthorization();
DataStoreLockGuard lock(m_dataStore); DataStoreLockGuard lock(m_dataStore);
auto& trackedInventoryItemMap = m_dataStore.getInventoryItems(); auto& trackedInventoryItemMap = m_dataStore.getInventoryItems();
int index = trackedInventoryItemMap.find(inventoryItemID); int index = trackedInventoryItemMap.find(inventoryItemID);
@@ -188,7 +183,6 @@ Return type: InventoryItem*
*/ */
InventoryItem* InventoryManagementService::getInventoryItem(const std::string& inventoryItemID) InventoryItem* InventoryManagementService::getInventoryItem(const std::string& inventoryItemID)
{ {
AuthenticationManagementService::ensureAuthorization();
DataStoreLockGuard lock(m_dataStore); DataStoreLockGuard lock(m_dataStore);
auto& trackedInventoryItemMap = m_dataStore.getInventoryItems(); auto& trackedInventoryItemMap = m_dataStore.getInventoryItems();
int index = trackedInventoryItemMap.find(inventoryItemID); int index = trackedInventoryItemMap.find(inventoryItemID);
@@ -276,7 +270,6 @@ void InventoryManagementService::sendNotification(User* user, const std::string&
{ {
return; return;
} }
auto& trackedNotificationsMap = m_dataStore.getNotifications();
Notification* notification = Factory::getObject<Notification>( Notification* notification = Factory::getObject<Notification>(
user->getId(), user->getId(),
title, title,
@@ -286,6 +279,7 @@ void InventoryManagementService::sendNotification(User* user, const std::string&
{ {
throw std::runtime_error("Failed to create notification"); throw std::runtime_error("Failed to create notification");
} }
auto& trackedNotificationsMap = m_dataStore.getNotifications();
trackedNotificationsMap.insert(notification->getId(), util::createNewRecord(notification)); trackedNotificationsMap.insert(notification->getId(), util::createNewRecord(notification));
m_dataStore.saveNotifications(); m_dataStore.saveNotifications();
EventManager::sendNotificationAvailableEvent(user->getId()); EventManager::sendNotificationAvailableEvent(user->getId());
@@ -15,7 +15,6 @@ Date: 20-May-2026
#include "Invoice.h" #include "Invoice.h"
#include "JobCard.h" #include "JobCard.h"
#include "PaymentManagementService.h" #include "PaymentManagementService.h"
#include "AuthenticationManagementService.h"
#include "DataStoreLockGuard.h" #include "DataStoreLockGuard.h"
#include "Service.h" #include "Service.h"
#include "ServiceBooking.h" #include "ServiceBooking.h"
@@ -99,7 +98,6 @@ void PaymentManagementService::sendNotification(User* user, const std::string& t
{ {
return; return;
} }
auto& trackedNotificationsMap = m_dataStore.getNotifications();
Notification* notification = Factory::getObject<Notification>( Notification* notification = Factory::getObject<Notification>(
user->getId(), user->getId(),
title, title,
@@ -109,6 +107,7 @@ void PaymentManagementService::sendNotification(User* user, const std::string& t
{ {
throw std::runtime_error("Failed to create notification"); throw std::runtime_error("Failed to create notification");
} }
auto& trackedNotificationsMap = m_dataStore.getNotifications();
trackedNotificationsMap.insert(notification->getId(), util::createNewRecord(notification)); trackedNotificationsMap.insert(notification->getId(), util::createNewRecord(notification));
m_dataStore.saveNotifications(); m_dataStore.saveNotifications();
EventManager::sendNotificationAvailableEvent(user->getId()); EventManager::sendNotificationAvailableEvent(user->getId());
@@ -234,7 +233,6 @@ Returns:
*/ */
util::Map<std::string, Invoice*> PaymentManagementService::getInvoices(const std::string& customerID) util::Map<std::string, Invoice*> PaymentManagementService::getInvoices(const std::string& customerID)
{ {
AuthenticationManagementService::ensureAuthorization();
DataStoreLockGuard lock(m_dataStore); DataStoreLockGuard lock(m_dataStore);
auto& currentTrackedInvoices = m_dataStore.getInvoices(); auto& currentTrackedInvoices = m_dataStore.getInvoices();
util::Map<std::string, Invoice*> currentUserInvoices; util::Map<std::string, Invoice*> currentUserInvoices;
@@ -263,7 +261,6 @@ Throws:
*/ */
void PaymentManagementService::completePayment(const std::string& invoiceID, util::PaymentMode paymentMode) void PaymentManagementService::completePayment(const std::string& invoiceID, util::PaymentMode paymentMode)
{ {
AuthenticationManagementService::ensureAuthorization();
DataStoreLockGuard lock(m_dataStore); DataStoreLockGuard lock(m_dataStore);
auto& currentTrackedInvoices = m_dataStore.getInvoices(); auto& currentTrackedInvoices = m_dataStore.getInvoices();
int invoiceIndex = currentTrackedInvoices.find(invoiceID); int invoiceIndex = currentTrackedInvoices.find(invoiceID);
@@ -292,7 +289,7 @@ void PaymentManagementService::completePayment(const std::string& invoiceID, uti
} }
/* /*
Function: getAllInvoices Function: getAllInvoice
Description: Provides access to all invoices stored in the data store. Description: Provides access to all invoices stored in the data store.
Parameters: Parameters:
- none - none
@@ -301,7 +298,6 @@ Returns:
*/ */
util::Map<std::string, Invoice*> PaymentManagementService::getAllInvoices() util::Map<std::string, Invoice*> PaymentManagementService::getAllInvoices()
{ {
AuthenticationManagementService::ensureAuthorization();
DataStoreLockGuard lock(m_dataStore); DataStoreLockGuard lock(m_dataStore);
util::Map<std::string, Invoice*> invoices; util::Map<std::string, Invoice*> invoices;
invoices = util::getObjects(m_dataStore.getInvoices()); invoices = util::getObjects(m_dataStore.getInvoices());
@@ -321,7 +317,6 @@ Throws:
*/ */
void PaymentManagementService::confirmPayment(const std::string& invoiceID) void PaymentManagementService::confirmPayment(const std::string& invoiceID)
{ {
AuthenticationManagementService::ensureAuthorization();
DataStoreLockGuard lock(m_dataStore); DataStoreLockGuard lock(m_dataStore);
auto& currentTrackedInvoices = m_dataStore.getInvoices(); auto& currentTrackedInvoices = m_dataStore.getInvoices();
int invoiceIndex = currentTrackedInvoices.find(invoiceID); int invoiceIndex = currentTrackedInvoices.find(invoiceID);
@@ -26,33 +26,9 @@ Date:19-May-2026
#include "UserManagementService.h" #include "UserManagementService.h"
#include "DataStoreLockGuard.h" #include "DataStoreLockGuard.h"
#include "Utility.h" #include "Utility.h"
#include "DataStoreLockGuard.h"
#include "EventManager.h" #include "EventManager.h"
/*
Function: notifyAllAdmins
Description: Sends a notification to all users with the ADMIN role.
Iterates through the provided user collection and delivers
the specified notification to each administrator using the
ServiceManagementService notification mechanism.
Parameter: const std::string& title - notification title
Parameter: const std::string& message - notification message
Parameter: const util::Map<std::string, TrackedRecord<User>>& users - collection of tracked users
Parameter: ServiceManagementService* serviceManagementService - service used to dispatch notifications
Return type: void
*/
static void notifyAllAdmins(const std::string& title, const std::string& message, const util::Map<std::string, TrackedRecord<User>>& users, ServiceManagementService* serviceManagementService)
{
int numberOfUsers = users.getSize();
for (int index = 0; index < numberOfUsers; index++)
{
User* user = users.getValueAt(index).data;
if (user->getUserType() == util::UserType::ADMIN)
{
serviceManagementService->sendNotification(user, title, message);
}
}
}
/* /*
Function: purchaseService Function: purchaseService
Description: Creates a new service booking for the authenticated user. Validates Description: Creates a new service booking for the authenticated user. Validates
@@ -66,7 +42,6 @@ Return type: void
*/ */
void ServiceManagementService::purchaseService(const util::Vector<std::string>& serviceIDs, const std::string& vehicleNumber, const std::string& vehicleBrand, const std::string& vehicleModel) void ServiceManagementService::purchaseService(const util::Vector<std::string>& serviceIDs, const std::string& vehicleNumber, const std::string& vehicleBrand, const std::string& vehicleModel)
{ {
AuthenticationManagementService::ensureAuthorization();
AuthenticationManagementService m_authenticationManagementService; AuthenticationManagementService m_authenticationManagementService;
auto authenticatedUser = m_authenticationManagementService.getAuthenticatedUser(); auto authenticatedUser = m_authenticationManagementService.getAuthenticatedUser();
if (authenticatedUser == nullptr) if (authenticatedUser == nullptr)
@@ -97,8 +72,6 @@ void ServiceManagementService::purchaseService(const util::Vector<std::string>&
std::string title = "Service Booking succeeded"; std::string title = "Service Booking succeeded";
std::string message = "Your service booking has been successfully placed with ID " + serviceBooking->getId(); std::string message = "Your service booking has been successfully placed with ID " + serviceBooking->getId();
sendNotification(authenticatedUser, title, message); sendNotification(authenticatedUser, title, message);
m_dataStore.saveServiceBookings();
notifyAllAdmins("New Service Order Available", "A new service order has been placed with Service Booking ID " + serviceBooking->getId(), m_dataStore.getUsers(), this);
} }
/* /*
@@ -114,7 +87,6 @@ Return type: void
*/ */
void ServiceManagementService::purchaseComboPackage(const std::string& comboPackageID, const std::string& vehicleNumber, const std::string& vehicleBrand, const std::string& vehicleModel) void ServiceManagementService::purchaseComboPackage(const std::string& comboPackageID, const std::string& vehicleNumber, const std::string& vehicleBrand, const std::string& vehicleModel)
{ {
AuthenticationManagementService::ensureAuthorization();
AuthenticationManagementService m_authenticationManagementService; AuthenticationManagementService m_authenticationManagementService;
auto authenticatedUser = m_authenticationManagementService.getAuthenticatedUser(); auto authenticatedUser = m_authenticationManagementService.getAuthenticatedUser();
if (authenticatedUser == nullptr) if (authenticatedUser == nullptr)
@@ -140,8 +112,6 @@ void ServiceManagementService::purchaseComboPackage(const std::string& comboPack
std::string title = "Combo Package Service Booking succeeded"; std::string title = "Combo Package Service Booking succeeded";
std::string message = "Your service booking for the combo package has been successfully placed with ID " + serviceBooking->getId(); std::string message = "Your service booking for the combo package has been successfully placed with ID " + serviceBooking->getId();
sendNotification(authenticatedUser, title, message); sendNotification(authenticatedUser, title, message);
m_dataStore.saveServiceBookings();
notifyAllAdmins("New Combo Package Order Available", "A new combo package order has been placed with Service Booking ID " + serviceBooking->getId(), m_dataStore.getUsers(), this);
} }
util::Map<std::string, User*> ServiceManagementService::m_observers{}; util::Map<std::string, User*> ServiceManagementService::m_observers{};
@@ -218,7 +188,6 @@ void ServiceManagementService::sendNotification(User* user, const std::string& t
{ {
return; return;
} }
auto& trackedNotificationsMap = m_dataStore.getNotifications();
Notification* notification = Factory::getObject<Notification>( Notification* notification = Factory::getObject<Notification>(
user->getId(), user->getId(),
title, title,
@@ -228,6 +197,7 @@ void ServiceManagementService::sendNotification(User* user, const std::string& t
{ {
throw std::runtime_error("Failed to create notification"); throw std::runtime_error("Failed to create notification");
} }
auto& trackedNotificationsMap = m_dataStore.getNotifications();
trackedNotificationsMap.insert(notification->getId(), util::createNewRecord(notification)); trackedNotificationsMap.insert(notification->getId(), util::createNewRecord(notification));
m_dataStore.saveNotifications(); m_dataStore.saveNotifications();
EventManager::sendNotificationAvailableEvent(user->getId()); EventManager::sendNotificationAvailableEvent(user->getId());
@@ -463,7 +433,6 @@ Return type: void
*/ */
void ServiceManagementService::createComboPackage(const std::string& packageName, const util::Vector<std::string>& serviceIDsInNewCombo, double discountPercentage) void ServiceManagementService::createComboPackage(const std::string& packageName, const util::Vector<std::string>& serviceIDsInNewCombo, double discountPercentage)
{ {
AuthenticationManagementService::ensureAuthorization();
DataStoreLockGuard lock(m_dataStore); DataStoreLockGuard lock(m_dataStore);
if (packageName.empty()) if (packageName.empty())
{ {
@@ -533,7 +502,6 @@ Return type: util::Map<std::string, ComboPackage*>
*/ */
util::Map<std::string, ComboPackage*> ServiceManagementService::getComboPackages() util::Map<std::string, ComboPackage*> ServiceManagementService::getComboPackages()
{ {
AuthenticationManagementService::ensureAuthorization();
DataStoreLockGuard lock(m_dataStore); DataStoreLockGuard lock(m_dataStore);
util::Map<std::string, ComboPackage*> comboPackages; util::Map<std::string, ComboPackage*> comboPackages;
comboPackages = util::getObjects(m_dataStore.getComboPackages()); comboPackages = util::getObjects(m_dataStore.getComboPackages());
@@ -548,7 +516,6 @@ Return type: void
*/ */
void ServiceManagementService::removeComboPackage(const std::string& comboPackageID) void ServiceManagementService::removeComboPackage(const std::string& comboPackageID)
{ {
AuthenticationManagementService::ensureAuthorization();
DataStoreLockGuard lock(m_dataStore); DataStoreLockGuard lock(m_dataStore);
bool removed = false; bool removed = false;
auto& trackedComboPackages = m_dataStore.getComboPackages(); auto& trackedComboPackages = m_dataStore.getComboPackages();
@@ -581,7 +548,6 @@ Returns:
*/ */
util::Map<std::string, ServiceBooking*> ServiceManagementService::getServiceBookings() util::Map<std::string, ServiceBooking*> ServiceManagementService::getServiceBookings()
{ {
AuthenticationManagementService::ensureAuthorization();
DataStoreLockGuard lock(m_dataStore); DataStoreLockGuard lock(m_dataStore);
util::Map<std::string, ServiceBooking*> serviceBookings; util::Map<std::string, ServiceBooking*> serviceBookings;
serviceBookings = util::getObjects(m_dataStore.getServiceBookings()); serviceBookings = util::getObjects(m_dataStore.getServiceBookings());
@@ -598,7 +564,6 @@ Returns:
*/ */
ServiceBooking* ServiceManagementService::getServiceBooking(const std::string& serviceID) ServiceBooking* ServiceManagementService::getServiceBooking(const std::string& serviceID)
{ {
AuthenticationManagementService::ensureAuthorization();
auto currentServiceBookings = getServiceBookings(); auto currentServiceBookings = getServiceBookings();
for (int iterator = 0; iterator < currentServiceBookings.getSize(); iterator++) for (int iterator = 0; iterator < currentServiceBookings.getSize(); iterator++)
{ {
@@ -625,27 +590,14 @@ Throws:
*/ */
void ServiceManagementService::createJobCard(const std::string& bookingID, const std::string& technicianID, const std::string& serviceID) void ServiceManagementService::createJobCard(const std::string& bookingID, const std::string& technicianID, const std::string& serviceID)
{ {
AuthenticationManagementService::ensureAuthorization();
DataStoreLockGuard lock(m_dataStore); DataStoreLockGuard lock(m_dataStore);
UserManagementService m_userManagementService; UserManagementService m_userManagementService;
ServiceBooking* currentBooking = getServiceBooking(bookingID); ServiceBooking* currentBooking = getServiceBooking(bookingID);
auto& currentTrackedJobCards = m_dataStore.getJobCards();
if (currentBooking == nullptr) if (currentBooking == nullptr)
{ {
throw std::runtime_error("Service Booking not available"); throw std::runtime_error("Service Booking not available");
} }
if (currentBooking->getStatus() == util::ServiceJobStatus::CANCELLED)
{
throw std::runtime_error("Cannot create job card. Service Booking was cancelled!");
}
auto& currentTrackedJobCards = m_dataStore.getJobCards();
auto& currentTrackedInventoryItems = m_dataStore.getInventoryItems();
auto& currentTrackedServiceBookings = m_dataStore.getServiceBookings();
int currentTrackedServiceBookingIndex = currentTrackedServiceBookings.find(bookingID);
if (currentTrackedServiceBookingIndex == -1)
{
throw std::runtime_error("Invalid service booking id.");
}
auto& currentTrackedServiceBooking = currentTrackedServiceBookings.getValueAt(currentTrackedServiceBookingIndex);
auto& currentServices = currentBooking->getServices(); auto& currentServices = currentBooking->getServices();
if (currentServices.find(serviceID) == -1) if (currentServices.find(serviceID) == -1)
{ {
@@ -670,18 +622,10 @@ void ServiceManagementService::createJobCard(const std::string& bookingID, const
for (int iterator = 0; iterator < inventoryItems.getSize(); iterator++) for (int iterator = 0; iterator < inventoryItems.getSize(); iterator++)
{ {
InventoryItem* currentInventoryItem = inventoryItems.getValueAt(iterator); InventoryItem* currentInventoryItem = inventoryItems.getValueAt(iterator);
const std::string& currentInventoryItemId = inventoryItems.getKeyAt(iterator);
if (currentInventoryItem) if (currentInventoryItem)
{ {
int trackedCurrentInventoryItemIndex = currentTrackedInventoryItems.find(currentInventoryItemId);
if (trackedCurrentInventoryItemIndex == -1)
{
throw std::runtime_error("Invalid inventory item index.");
}
auto& trackedCurrentInventoryItem = currentTrackedInventoryItems.getValueAt(trackedCurrentInventoryItemIndex);
int currentStockQuantity = currentInventoryItem->getQuantity(); int currentStockQuantity = currentInventoryItem->getQuantity();
currentInventoryItem->setQuantity(currentStockQuantity - 1); currentInventoryItem->setQuantity(currentStockQuantity - 1);
trackedCurrentInventoryItem.state = RecordState::MODIFIED;
} }
} }
currentBooking->setAssignedTechnician(selectedTechnician); currentBooking->setAssignedTechnician(selectedTechnician);
@@ -690,7 +634,6 @@ void ServiceManagementService::createJobCard(const std::string& bookingID, const
{ {
currentBooking->setStatus(util::ServiceJobStatus::STARTED); currentBooking->setStatus(util::ServiceJobStatus::STARTED);
} }
currentTrackedServiceBooking.state = RecordState::MODIFIED;
std::string title = "Job card created"; std::string title = "Job card created";
std::string message = "Job card created for the service and you are assigned for that."; std::string message = "Job card created for the service and you are assigned for that.";
JobCard* jobCard = Factory::getObject<JobCard>(bookingID, currentBooking, currentService, serviceID, technicianID, selectedTechnician, util::Timestamp(), util::ServiceJobStatus::STARTED, util::Timestamp()); JobCard* jobCard = Factory::getObject<JobCard>(bookingID, currentBooking, currentService, serviceID, technicianID, selectedTechnician, util::Timestamp(), util::ServiceJobStatus::STARTED, util::Timestamp());
@@ -707,8 +650,6 @@ void ServiceManagementService::createJobCard(const std::string& bookingID, const
message = "A technician has been assigned to your Service Booking with ID " + bookingID; message = "A technician has been assigned to your Service Booking with ID " + bookingID;
sendNotification(currentBooking->getCustomer(), title, message); sendNotification(currentBooking->getCustomer(), title, message);
m_dataStore.saveJobCards(); m_dataStore.saveJobCards();
m_dataStore.saveServiceBookings();
m_dataStore.saveInventoryItems();
} }
/* /*
@@ -726,7 +667,6 @@ Throws:
*/ */
void ServiceManagementService::createService(const std::string& name, const util::Vector<std::string>& inventoryItemIDs, double laborCost) void ServiceManagementService::createService(const std::string& name, const util::Vector<std::string>& inventoryItemIDs, double laborCost)
{ {
AuthenticationManagementService::ensureAuthorization();
DataStoreLockGuard lock(m_dataStore); DataStoreLockGuard lock(m_dataStore);
util::Map<std::string, InventoryItem*> currentServiceInventoryItems; util::Map<std::string, InventoryItem*> currentServiceInventoryItems;
auto& trackedInventoryItems = m_dataStore.getInventoryItems(); auto& trackedInventoryItems = m_dataStore.getInventoryItems();
@@ -773,7 +713,6 @@ Returns:
*/ */
util::Map<std::string, Service*> ServiceManagementService::getServices() util::Map<std::string, Service*> ServiceManagementService::getServices()
{ {
AuthenticationManagementService::ensureAuthorization();
DataStoreLockGuard lock(m_dataStore); DataStoreLockGuard lock(m_dataStore);
util::Map<std::string, Service*> services; util::Map<std::string, Service*> services;
services = util::getObjects(m_dataStore.getServices()); services = util::getObjects(m_dataStore.getServices());
@@ -792,7 +731,6 @@ Throws:
*/ */
void ServiceManagementService::removeService(const std::string& serviceID) void ServiceManagementService::removeService(const std::string& serviceID)
{ {
AuthenticationManagementService::ensureAuthorization();
DataStoreLockGuard lock(m_dataStore); DataStoreLockGuard lock(m_dataStore);
auto& currentTrackedServices = m_dataStore.getServices(); auto& currentTrackedServices = m_dataStore.getServices();
auto& currentTrackedComboPackages = m_dataStore.getComboPackages(); auto& currentTrackedComboPackages = m_dataStore.getComboPackages();
@@ -830,61 +768,6 @@ void ServiceManagementService::removeService(const std::string& serviceID)
m_dataStore.saveComboPackages(); m_dataStore.saveComboPackages();
} }
/*
Function: removeServiceBooking
Description: Removes a pending service booking by its ID.
Cancels only if status is PENDING, otherwise throws exceptions
for invalid states. Sends notification to the customer and
persists changes.
Parameter: const std::string& bookingID - ID of the service booking
Return type: void
*/
void ServiceManagementService::removeServiceBooking(const std::string& bookingID)
{
DataStoreLockGuard lock(m_dataStore);
auto& trackedServiceBookings = m_dataStore.getServiceBookings();
bool serviceBookingRemoved = false;
for (int iterator = 0; iterator < trackedServiceBookings.getSize(); iterator++)
{
auto& currentTrackedServiceBooking = trackedServiceBookings.getValueAt(iterator);
ServiceBooking* currentServiceBooking = currentTrackedServiceBooking.data;
if (currentServiceBooking && currentServiceBooking->getId() == bookingID)
{
if (currentServiceBooking->getStatus() == util::ServiceJobStatus::PENDING)
{
const std::string title = "Service Booking cancelled.";
const std::string message = "Service Booking of id " + bookingID + " successfully cancelled.";
currentServiceBooking->setStatus(util::ServiceJobStatus::CANCELLED);
currentTrackedServiceBooking.state = RecordState::MODIFIED;
serviceBookingRemoved = true;
sendNotification(currentServiceBooking->getCustomer(), title, message);
break;
}
else if(currentServiceBooking->getStatus() == util::ServiceJobStatus::COMPLETED)
{
throw std::runtime_error("Unable to cancel completed service booking.");
}
else if (currentServiceBooking->getStatus() == util::ServiceJobStatus::STARTED)
{
throw std::runtime_error("Unable to cancel started service booking.");
}
else if (currentServiceBooking->getStatus() == util::ServiceJobStatus::IN_PROGRESS)
{
throw std::runtime_error("Unable to cancel currently Inprogress service booking.");
}
else
{
throw std::runtime_error("Service Booking already cancelled.");
}
}
}
if (!serviceBookingRemoved)
{
throw std::runtime_error("Unable to cancel service booking.");
}
m_dataStore.saveServiceBookings();
}
/* /*
Function: getServiceBookings (overloaded) Function: getServiceBookings (overloaded)
Description: Retrieves all service bookings for a specific customer. Description: Retrieves all service bookings for a specific customer.
@@ -895,7 +778,6 @@ Returns:
*/ */
util::Map<std::string, ServiceBooking*> ServiceManagementService::getServiceBookings(const std::string& customerID) util::Map<std::string, ServiceBooking*> ServiceManagementService::getServiceBookings(const std::string& customerID)
{ {
AuthenticationManagementService::ensureAuthorization();
util::Map<std::string, ServiceBooking*> currentServiceBookings = getServiceBookings(); util::Map<std::string, ServiceBooking*> currentServiceBookings = getServiceBookings();
util::Map<std::string, ServiceBooking*> currentUserServiceBookings; util::Map<std::string, ServiceBooking*> currentUserServiceBookings;
if (currentServiceBookings.getSize() != 0) if (currentServiceBookings.getSize() != 0)
@@ -922,7 +804,6 @@ Returns:
*/ */
util::Map<std::string, JobCard*> ServiceManagementService::getJobCards(const std::string& technicianID) util::Map<std::string, JobCard*> ServiceManagementService::getJobCards(const std::string& technicianID)
{ {
AuthenticationManagementService::ensureAuthorization();
DataStoreLockGuard lock(m_dataStore); DataStoreLockGuard lock(m_dataStore);
auto& trackedJobCards = m_dataStore.getJobCards(); auto& trackedJobCards = m_dataStore.getJobCards();
util::Map<std::string, JobCard*> technicianJobCards; util::Map<std::string, JobCard*> technicianJobCards;
@@ -977,11 +858,11 @@ Returns:
*/ */
void ServiceManagementService::updateJobStatus(const std::string& jobID) void ServiceManagementService::updateJobStatus(const std::string& jobID)
{ {
AuthenticationManagementService::ensureAuthorization();
DataStoreLockGuard lock(m_dataStore); DataStoreLockGuard lock(m_dataStore);
AuthenticationManagementService authenticationManagementService; AuthenticationManagementService authenticationManagementService;
PaymentManagementService paymentManagementService; PaymentManagementService paymentManagementService;
bool jobStatusUpdated = false, serviceBookingCompleted; bool jobStatusUpdated = false, serviceBookingCompleted;
JobCard* currentJob;
User* currentTechnician = authenticationManagementService.getAuthenticatedUser(); User* currentTechnician = authenticationManagementService.getAuthenticatedUser();
if (currentTechnician == nullptr) if (currentTechnician == nullptr)
{ {
@@ -1001,8 +882,7 @@ void ServiceManagementService::updateJobStatus(const std::string& jobID)
{ {
throw std::runtime_error("Unable to fetch current job."); throw std::runtime_error("Unable to fetch current job.");
} }
auto& trackedCurrentJob = trackedJobCards.getValueAt(jobIndex); currentJob = currentAssignedJobs.getValueAt(currentAssignedJobs.find(jobID));
JobCard* currentJob = trackedCurrentJob.data;
if (currentJob == nullptr) if (currentJob == nullptr)
{ {
throw std::runtime_error("Unable to fetch current job."); throw std::runtime_error("Unable to fetch current job.");
@@ -1010,13 +890,13 @@ void ServiceManagementService::updateJobStatus(const std::string& jobID)
if (currentJob->getStatus() == util::ServiceJobStatus::STARTED) if (currentJob->getStatus() == util::ServiceJobStatus::STARTED)
{ {
currentJob->setStatus(util::ServiceJobStatus::IN_PROGRESS); currentJob->setStatus(util::ServiceJobStatus::IN_PROGRESS);
trackedCurrentJob.state = RecordState::MODIFIED; trackedJobCards.getValueAt(jobIndex).state = RecordState::MODIFIED;
jobStatusUpdated = true; jobStatusUpdated = true;
} }
else if (currentJob->getStatus() == util::ServiceJobStatus::IN_PROGRESS) else if (currentJob->getStatus() == util::ServiceJobStatus::IN_PROGRESS)
{ {
currentJob->setStatus(util::ServiceJobStatus::COMPLETED); currentJob->setStatus(util::ServiceJobStatus::COMPLETED);
trackedCurrentJob.state = RecordState::MODIFIED; trackedJobCards.getValueAt(jobIndex).state = RecordState::MODIFIED;
jobStatusUpdated = true; jobStatusUpdated = true;
serviceBookingCompleted = hasCompletedAllJobs(currentJob->getBookingId(), currentAssignedJobs); serviceBookingCompleted = hasCompletedAllJobs(currentJob->getBookingId(), currentAssignedJobs);
if (serviceBookingCompleted) if (serviceBookingCompleted)
@@ -35,7 +35,6 @@ public:
void createJobCard(const std::string& bookingID, const std::string& technicianID, const std::string& serviceID); void createJobCard(const std::string& bookingID, const std::string& technicianID, const std::string& serviceID);
void createService(const std::string& name, const util::Vector<std::string>& inventoryItemIDs, double laborCost); void createService(const std::string& name, const util::Vector<std::string>& inventoryItemIDs, double laborCost);
void removeService(const std::string& serviceID); void removeService(const std::string& serviceID);
void removeServiceBooking(const std::string& bookingID);
util::Map<std::string, JobCard*> getJobCards(const std::string& technicianID); util::Map<std::string, JobCard*> getJobCards(const std::string& technicianID);
void updateJobStatus(const std::string& jobID); void updateJobStatus(const std::string& jobID);
void cancelCustomerServiceBookings(const std::string& customerID); void cancelCustomerServiceBookings(const std::string& customerID);
@@ -15,7 +15,6 @@ Date:19-May-2026
#include "Notification.h" #include "Notification.h"
#include "PaymentManagementService.h" #include "PaymentManagementService.h"
#include "ServiceManagementService.h" #include "ServiceManagementService.h"
#include "AuthenticationManagementService.h"
#include "User.h" #include "User.h"
#include "UserManagementService.h" #include "UserManagementService.h"
#include "Vector.h" #include "Vector.h"
@@ -115,7 +114,6 @@ Return type: void
*/ */
void UserManagementService::updateUserDetails(const std::string& userID, const std::string& email, const std::string& phone) void UserManagementService::updateUserDetails(const std::string& userID, const std::string& email, const std::string& phone)
{ {
AuthenticationManagementService::ensureAuthorization();
DataStoreLockGuard lock(m_dataStore); DataStoreLockGuard lock(m_dataStore);
auto& trackedUsersMap = m_dataStore.getUsers(); auto& trackedUsersMap = m_dataStore.getUsers();
auto usersMap = util::getObjects(trackedUsersMap); auto usersMap = util::getObjects(trackedUsersMap);
@@ -163,7 +161,6 @@ Throws:
*/ */
util::Vector<Notification*> UserManagementService::getUserNotifications(const std::string& userID) util::Vector<Notification*> UserManagementService::getUserNotifications(const std::string& userID)
{ {
AuthenticationManagementService::ensureAuthorization();
DataStoreLockGuard lock(m_dataStore); DataStoreLockGuard lock(m_dataStore);
auto& trackedUsersMap = m_dataStore.getUsers(); auto& trackedUsersMap = m_dataStore.getUsers();
if (trackedUsersMap.find(userID) == -1) if (trackedUsersMap.find(userID) == -1)
@@ -207,7 +204,6 @@ Throws:
*/ */
void UserManagementService::deleteNotification(const std::string& notificationID, const std::string& userID) void UserManagementService::deleteNotification(const std::string& notificationID, const std::string& userID)
{ {
AuthenticationManagementService::ensureAuthorization();
DataStoreLockGuard lock(m_dataStore); DataStoreLockGuard lock(m_dataStore);
auto& trackedUsersMap = m_dataStore.getUsers(); auto& trackedUsersMap = m_dataStore.getUsers();
auto& trackedNotificationsMap = m_dataStore.getNotifications(); auto& trackedNotificationsMap = m_dataStore.getNotifications();
@@ -269,7 +265,6 @@ Return type: void
*/ */
void UserManagementService::removeUser(const std::string& userID) void UserManagementService::removeUser(const std::string& userID)
{ {
AuthenticationManagementService::ensureAuthorization();
InventoryManagementService inventoryManagementService; InventoryManagementService inventoryManagementService;
PaymentManagementService paymentManagementService; PaymentManagementService paymentManagementService;
ServiceManagementService serviceManagementService; ServiceManagementService serviceManagementService;
@@ -163,13 +163,7 @@ Return type: void
void AdminMenu::handleNotificationEvent() void AdminMenu::handleNotificationEvent()
{ {
auto notifications = m_controller.getNotifications(); auto notifications = m_controller.getNotifications();
const User* authenticatedUser = m_controller.getAuthenticatedUser(); displayNewNotification(notifications);
std::string name;
if (authenticatedUser)
{
name = authenticatedUser->getName();
}
displayNewNotification(notifications, name);
} }
/* /*
@@ -338,23 +332,6 @@ void AdminMenu::removeInventoryItem()
std::string selectedItemId = selectedItem->getId(); std::string selectedItemId = selectedItem->getId();
m_controller.removeInventoryItem(selectedItemId); m_controller.removeInventoryItem(selectedItemId);
std::cout << "Item " << selectedItem->getPartName() << " removed successfully." << std::endl; std::cout << "Item " << selectedItem->getPartName() << " removed successfully." << std::endl;
const util::Map<std::string, const Service*>& listOfService = m_controller.getServices();
for (int serviceIndex = 0; serviceIndex < listOfService.getSize(); serviceIndex++)
{
const Service* service = listOfService.getValueAt(serviceIndex);
if (!service)
{
continue;
}
const util::Map<std::string, InventoryItem*>& requiredItems = service->getRequiredInventoryItems();
if (requiredItems.find(selectedItemId) != -1)
{
m_controller.removeService(service->getId());
std::cout << "Service " << service->getName()
<< " removed as the item "
<< selectedItem->getPartName() << " required for the service has been removed." << std::endl;
}
}
} }
} }
util::pressEnter(); util::pressEnter();
@@ -51,12 +51,11 @@ void CustomerMenu::showMenu()
<< "\n3. Update Profile" << "\n3. Update Profile"
<< "\n4. Change Password" << "\n4. Change Password"
<< "\n5. View Service History" << "\n5. View Service History"
<< "\n6. Cancel Service Booking" << "\n6. Complete Payments"
<< "\n7. Complete Payments" << "\n7. View Invoices"
<< "\n8. View Invoices" << "\n8. View Notifications"
<< "\n9. View Notifications" << "\n9. Configure Notifications"
<< "\n10. Configure Notifications" << "\n10. Logout"
<< "\n11. Logout"
<< "\nEnter a choice: "; << "\nEnter a choice: ";
util::read(choice); util::read(choice);
if (!handleOperation(choice)) if (!handleOperation(choice))
@@ -104,21 +103,18 @@ bool CustomerMenu::handleOperation(int choice)
viewServiceHistory(); viewServiceHistory();
break; break;
case 6: case 6:
cancelServiceBooking();
break;
case 7:
completePayments(); completePayments();
break; break;
case 8: case 7:
viewInvoices(); viewInvoices();
break; break;
case 9: case 8:
viewNotifications(); viewNotifications();
break; break;
case 10: case 9:
configureNotifications(); configureNotifications();
break; break;
case 11: case 10:
logout(); logout();
return false; return false;
default: default:
@@ -138,13 +134,7 @@ Return type: void
void CustomerMenu::handleNotificationEvent() void CustomerMenu::handleNotificationEvent()
{ {
auto notifications = m_controller.getNotifications(); auto notifications = m_controller.getNotifications();
const User* authenticatedUser = m_controller.getAuthenticatedUser(); displayNewNotification(notifications);
std::string name;
if (authenticatedUser)
{
name = authenticatedUser->getName();
}
displayNewNotification(notifications, name);
} }
/* /*
@@ -337,46 +327,6 @@ void CustomerMenu::viewServiceHistory()
util::pressEnter(); util::pressEnter();
} }
/*
Function: cancelServiceBooking
Description: Allows the customer to cancel a pending service booking.
Displays the list of active bookings, lets the user select one,
and removes it from the system. If no bookings are available,
an appropriate message is shown.
Parameter: None
Return type: void
*/
void CustomerMenu::cancelServiceBooking()
{
util::clear();
std::cout << "Cancel Service Booking\n";
const User* currentUser = m_controller.getAuthenticatedUser();
std::string currentUserID = currentUser->getId();
util::Map<std::string, const ServiceBooking*> serviceBookingsByCurrentUser = m_controller.getServiceBookingsByUser(currentUserID);
util::Map<int, const ServiceBooking*> serviceBookingsMap;
auto currentPendingServiceBookings = filterActiveServiceBookings(serviceBookingsByCurrentUser);
int bookingsSize = currentPendingServiceBookings.getSize();
if (listServiceBookings(currentPendingServiceBookings, bookingsSize, serviceBookingsMap))
{
const ServiceBooking* selectedService = selectPendingServiceBookings(serviceBookingsMap);
if (selectedService)
{
m_controller.removeServiceBooking(selectedService->getId());
std::cout << "Cancelled Service booking of id " + selectedService->getId() << std::endl << std::endl;
}
else
{
std::cout << "Invalid service booking index.\n\n";
return;
}
}
else
{
std::cout << "No pending service bookings available.\n\n";
}
util::pressEnter();
}
/* /*
Function: completePayments Function: completePayments
Description: Allows the customer to complete pending payments for invoices. Description: Allows the customer to complete pending payments for invoices.
@@ -28,6 +28,5 @@ public:
void completePayments(); void completePayments();
void viewInvoices(); void viewInvoices();
void viewNotifications(); void viewNotifications();
void cancelServiceBooking();
void configureNotifications(); void configureNotifications();
}; };
@@ -67,7 +67,7 @@ Return type: void
*/ */
void Menu::eventListenerLoop() void Menu::eventListenerLoop()
{ {
HANDLE handles[3] = { NULL, NULL, NULL }; HANDLE handles[3];
handles[0] = m_accountDisabledEvent; handles[0] = m_accountDisabledEvent;
handles[1] = m_notificationAvailableEvent; handles[1] = m_notificationAvailableEvent;
handles[2] = m_shutdownEvent; handles[2] = m_shutdownEvent;
@@ -133,16 +133,10 @@ Return type: void
void Menu::handleAccountDisabledEvent() void Menu::handleAccountDisabledEvent()
{ {
m_isMenuActive.store(false); m_isMenuActive.store(false);
const User* authenticatedUser = m_controller.getAuthenticatedUser();
std::string messageTitle = "Account Disabled";
if (authenticatedUser)
{
messageTitle += " - " + authenticatedUser->getName();
}
MessageBoxA( MessageBoxA(
GetConsoleWindow(), GetConsoleWindow(),
"Your account has been disabled.", "Your account has been disabled.",
messageTitle.c_str(), "Account Disabled",
MB_OK | MB_OK |
MB_ICONWARNING | MB_ICONWARNING |
MB_SETFOREGROUND | MB_SETFOREGROUND |
@@ -28,7 +28,6 @@ Date: 21-May-2026
#include "Utility.h" #include "Utility.h"
#include "Validator.h" #include "Validator.h"
#include "Vector.h" #include "Vector.h"
#include "StringHelper.h"
/* /*
Function: displayAllServices Function: displayAllServices
@@ -588,7 +587,7 @@ inline void displayInvoices(util::Map<std::string, const Invoice*> currentUserIn
<< util::getPaymentStatusString(selectedInvoice->getStatus()) << std::endl; << util::getPaymentStatusString(selectedInvoice->getStatus()) << std::endl;
std::cout << std::left << std::setw(20) << "Payment Mode:" std::cout << std::left << std::setw(20) << "Payment Mode:"
<< util::getPaymentModeString(selectedInvoice->getPaymentMethod()) << std::endl; << util::getPaymentModeString(selectedInvoice->getPaymentMethod()) << std::endl;
auto& inventoryItemsInInvoice = selectedInvoice->getParts(); auto inventoryItemsInInvoice = selectedInvoice->getParts();
if (inventoryItemsInInvoice.isEmpty()) if (inventoryItemsInInvoice.isEmpty())
{ {
std::cout << "No inventory items used.\n\n"; std::cout << "No inventory items used.\n\n";
@@ -597,6 +596,7 @@ inline void displayInvoices(util::Map<std::string, const Invoice*> currentUserIn
std::cout << "\nItems Used:\n"; std::cout << "\nItems Used:\n";
std::cout << std::left std::cout << std::left
<< std::setw(20) << "ItemName" << std::setw(20) << "ItemName"
<< std::setw(10) << "Quantity"
<< std::setw(10) << "Price" << std::setw(10) << "Price"
<< std::endl; << std::endl;
std::cout << std::string(40, '-') << std::endl; std::cout << std::string(40, '-') << std::endl;
@@ -605,6 +605,7 @@ inline void displayInvoices(util::Map<std::string, const Invoice*> currentUserIn
InventoryItem* currentItem = inventoryItemsInInvoice.getValueAt(iterator); InventoryItem* currentItem = inventoryItemsInInvoice.getValueAt(iterator);
std::cout << std::left std::cout << std::left
<< std::setw(20) << currentItem->getPartName() << std::setw(20) << currentItem->getPartName()
<< std::setw(10) << currentItem->getQuantity()
<< std::setw(10) << currentItem->getPrice() << std::setw(10) << currentItem->getPrice()
<< std::endl; << std::endl;
} }
@@ -1055,21 +1056,6 @@ inline const Service* selectServiceFromServices(const util::Map<std::string, con
{ {
continue; continue;
} }
bool hasDepletedItem = false;
const util::Map<std::string, InventoryItem*>& requiredItems = currentService->getRequiredInventoryItems();
for (int itemIndex = 0; itemIndex < requiredItems.getSize(); itemIndex++)
{
const InventoryItem* item = requiredItems.getValueAt(itemIndex);
if (!item || item->getQuantity() < 1)
{
hasDepletedItem = true;
break;
}
}
if (hasDepletedItem)
{
continue;
}
activeServicesMap.insert(currentIndex, currentService); activeServicesMap.insert(currentIndex, currentService);
double partsCost = util::calculatePartsCost(currentService); double partsCost = util::calculatePartsCost(currentService);
std::cout << std::left std::cout << std::left
@@ -1144,9 +1130,7 @@ inline void displayAllComboPackages(util::Map<std::string, const ComboPackage*>
for (int index = 0; index < comboPackages.getSize(); index++) for (int index = 0; index < comboPackages.getSize(); index++)
{ {
const ComboPackage* currentComboPackage = comboPackages.getValueAt(index); const ComboPackage* currentComboPackage = comboPackages.getValueAt(index);
if (currentComboPackage) if (currentComboPackage && currentComboPackage->getState() != util::State::ACTIVE)
{
if (currentComboPackage->getState() != util::State::ACTIVE)
{ {
continue; continue;
} }
@@ -1156,7 +1140,6 @@ inline void displayAllComboPackages(util::Map<std::string, const ComboPackage*>
<< std::setw(15) << util::calculateComboServiceEstimatedCost(currentComboPackage) << std::setw(15) << util::calculateComboServiceEstimatedCost(currentComboPackage)
<< std::endl; << std::endl;
} }
}
} }
@@ -1181,9 +1164,7 @@ inline const ComboPackage* selectComboPackageFromPackages(const util::Map<std::s
for (int index = 0; index < comboPackages.getSize(); index++) for (int index = 0; index < comboPackages.getSize(); index++)
{ {
const ComboPackage* currentComboPackage = comboPackages.getValueAt(index); const ComboPackage* currentComboPackage = comboPackages.getValueAt(index);
if (currentComboPackage) if (currentComboPackage && currentComboPackage->getState() != util::State::ACTIVE)
{
if (currentComboPackage->getState() != util::State::ACTIVE)
{ {
continue; continue;
} }
@@ -1196,7 +1177,6 @@ inline const ComboPackage* selectComboPackageFromPackages(const util::Map<std::s
<< std::endl; << std::endl;
currentIndex++; currentIndex++;
} }
}
if (activeComboPackages.getSize() == 0) if (activeComboPackages.getSize() == 0)
{ {
std::cout << "No active combo packages available." << std::endl; std::cout << "No active combo packages available." << std::endl;
@@ -1435,10 +1415,9 @@ Description: Displays the most recent notification from the supplied
notification collection. notification collection.
Parameter: util::Vector<const Notification*> notifications - Parameter: util::Vector<const Notification*> notifications -
collection of notifications collection of notifications
const std::string& - The name of the user currently authenticated with the system
Return type: void Return type: void
*/ */
inline void displayNewNotification(util::Vector<const Notification*> notifications, const std::string& name) inline void displayNewNotification(util::Vector<const Notification*> notifications)
{ {
const Notification* notification = nullptr; const Notification* notification = nullptr;
size_t numberOfNotifications = notifications.getSize(); size_t numberOfNotifications = notifications.getSize();
@@ -1450,24 +1429,16 @@ inline void displayNewNotification(util::Vector<const Notification*> notificatio
} }
else else
{ {
if (util::extractNumber(notification->getId()) < util::extractNumber(notifications[index]->getId())) if (notification->getId() < notifications[index]->getId())
{ {
notification = notifications[index]; notification = notifications[index];
} }
} }
} }
if (notification)
{
std::string messageTitle = notification->getTitle();
if (!name.empty())
{
messageTitle += " - " + name;
}
MessageBoxA( MessageBoxA(
GetConsoleWindow(), GetConsoleWindow(),
notification->getMessage().c_str(), notification->getMessage().c_str(),
messageTitle.c_str(), notification->getTitle().c_str(),
MB_OK | MB_OK |
MB_ICONINFORMATION); MB_ICONINFORMATION);
}
} }
@@ -108,13 +108,7 @@ Return type: void
void TechnicianMenu::handleNotificationEvent() void TechnicianMenu::handleNotificationEvent()
{ {
auto notifications = m_controller.getNotifications(); auto notifications = m_controller.getNotifications();
const User* authenticatedUser = m_controller.getAuthenticatedUser(); displayNewNotification(notifications);
std::string name;
if (authenticatedUser)
{
name = authenticatedUser->getName();
}
displayNewNotification(notifications, name);
} }
/* /*