Merged PR 1195: Fix notification display and service dependency handling issues

**Changes:**
- Persist service bookings immediately after purchase to ensure data consistency.
- Enhanced notification display by appending authenticated user names to notification titles.
- Updated account disabled event handling to include authenticated user names in warning messages.
- Modified notification event handling in Admin, Customer, and Technician menus to pass authenticated user names.
- Improved service selection logic to skip services with depleted inventory items.
- Added dependency cleanup: services requiring a removed inventory item are automatically removed.
- Updated displayNewNotification to extract numeric IDs correctly and append authenticated user names to notification titles.
- Included StringHelper for improved string operations in notification handling.

#2080
#2081
#2082

Related work items: #2080, #2081, #2082
This commit is contained in:
Avinash Rajesh
2026-06-18 11:17:11 +05:30
committed by Joel Thomas
6 changed files with 80 additions and 13 deletions
@@ -98,6 +98,7 @@ 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); notifyAllAdmins("New Service Order Available", "A new service order has been placed with Service Booking ID " + serviceBooking->getId(), m_dataStore.getUsers(), this);
} }
@@ -163,7 +163,13 @@ Return type: void
void AdminMenu::handleNotificationEvent() void AdminMenu::handleNotificationEvent()
{ {
auto notifications = m_controller.getNotifications(); auto notifications = m_controller.getNotifications();
displayNewNotification(notifications); const User* authenticatedUser = m_controller.getAuthenticatedUser();
std::string name;
if (authenticatedUser)
{
name = authenticatedUser->getName();
}
displayNewNotification(notifications, name);
} }
/* /*
@@ -332,6 +338,23 @@ 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();
@@ -134,7 +134,13 @@ Return type: void
void CustomerMenu::handleNotificationEvent() void CustomerMenu::handleNotificationEvent()
{ {
auto notifications = m_controller.getNotifications(); auto notifications = m_controller.getNotifications();
displayNewNotification(notifications); const User* authenticatedUser = m_controller.getAuthenticatedUser();
std::string name;
if (authenticatedUser)
{
name = authenticatedUser->getName();
}
displayNewNotification(notifications, name);
} }
/* /*
@@ -133,10 +133,16 @@ 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.",
"Account Disabled", messageTitle.c_str(),
MB_OK | MB_OK |
MB_ICONWARNING | MB_ICONWARNING |
MB_SETFOREGROUND | MB_SETFOREGROUND |
@@ -28,6 +28,7 @@ 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
@@ -1056,6 +1057,21 @@ 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
@@ -1415,9 +1431,10 @@ 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) inline void displayNewNotification(util::Vector<const Notification*> notifications, const std::string& name)
{ {
const Notification* notification = nullptr; const Notification* notification = nullptr;
size_t numberOfNotifications = notifications.getSize(); size_t numberOfNotifications = notifications.getSize();
@@ -1429,16 +1446,24 @@ inline void displayNewNotification(util::Vector<const Notification*> notificatio
} }
else else
{ {
if (notification->getId() < notifications[index]->getId()) if (util::extractNumber(notification->getId()) < util::extractNumber(notifications[index]->getId()))
{ {
notification = notifications[index]; notification = notifications[index];
} }
} }
} }
MessageBoxA( if (notification)
GetConsoleWindow(), {
notification->getMessage().c_str(), std::string messageTitle = notification->getTitle();
notification->getTitle().c_str(), if (!name.empty())
MB_OK | {
MB_ICONINFORMATION); messageTitle += " - " + name;
} }
MessageBoxA(
GetConsoleWindow(),
notification->getMessage().c_str(),
messageTitle.c_str(),
MB_OK |
MB_ICONINFORMATION);
}
}
@@ -108,7 +108,13 @@ Return type: void
void TechnicianMenu::handleNotificationEvent() void TechnicianMenu::handleNotificationEvent()
{ {
auto notifications = m_controller.getNotifications(); auto notifications = m_controller.getNotifications();
displayNewNotification(notifications); const User* authenticatedUser = m_controller.getAuthenticatedUser();
std::string name;
if (authenticatedUser)
{
name = authenticatedUser->getName();
}
displayNewNotification(notifications, name);
} }
/* /*