Files
Training-VehicleService-May26/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.cpp
T
joelthomastrenser 8aaa4eeec0 Implement interprocess event handling for notifications and account disable
Changes:
- Implements #2061
- Introduce EventManager for user-specific Windows event publishing/listening
- Add real-time notification and account-disabled event propagation
- Register authentication events through Controller and AuthenticationManagementService
- Trigger notification events from Inventory, Payment, and Service Management modules
- Trigger account-disabled events when users are deactivated
- Extract common menu event listener logic into Menu base class
- Add notification popup handling for Admin, Customer, and Technician menus
- Refactor shared memory components into core/sharedmemory
- Update project structure and include paths for events and shared memory modules
2026-06-16 11:10:13 +05:30

288 lines
8.9 KiB
C++

/*
File: InventoryManagementService.cpp
Description: Implements the InventoryManagementService class, which manages inventory
items and observer relationships within the system. Provides methods
for loading and saving inventory items from persistent storage, as well
as attaching and persisting observers for notification handling.
Author: Trenser
Date: 22-May-2026
*/
#include <stdexcept>
#include "Config.h"
#include "Enums.h"
#include "Factory.h"
#include "InventoryItem.h"
#include "InventoryManagementService.h"
#include "Timestamp.h"
#include "User.h"
#include "Utility.h"
#include "Vector.h"
#include "DataStoreLockGuard.h"
#include "EventManager.h"
util::Map<std::string, User*> InventoryManagementService::m_observers{};
/*
Function: sendLowStockAlertsToAdmins (static helper)
Description: Sends low stock alert notifications to all admin users for a given inventory item.
Parameters:
- inventoryManagementService: InventoryManagementService&, service used to send notifications
- inventoryItem: const InventoryItem*, pointer to the low-stock inventory item
- adminUsers: const util::Vector<User*>&, list of admin users to notify
Returns:
- None
*/
static void sendLowStockAlertsToAdmins(InventoryManagementService& inventoryManagementService, const InventoryItem* inventoryItem, const util::Vector<User*>& adminUsers)
{
int adminUsersSize = adminUsers.getSize();
for (int index = 0; index < adminUsersSize; index++)
{
std::string title = "Low Stock Alert";
std::string message = "The inventory item with ID " + inventoryItem->getId() + " has very low quantity in the inventory";
inventoryManagementService.sendNotification(
adminUsers[index],
title,
message
);
}
}
/*
Function: sendLowStockAlerts
Description: Sends alerts to user for inventory items with low stock
Parameters:
- None
Returns:
- None
*/
void InventoryManagementService::sendLowStockAlerts()
{
DataStoreLockGuard lock(m_dataStore);
auto& trackedInventoryItemsMap = m_dataStore.getInventoryItems();
auto& trackedUserMap = m_dataStore.getUsers();
if (trackedInventoryItemsMap.isEmpty())
{
return;
}
int inventoryItemsSize = trackedInventoryItemsMap.getSize();
int usersMapSize = trackedUserMap.getSize();
util::Vector<User*> adminUsers;
for (int index = 0; index < usersMapSize; index++)
{
User* user = trackedUserMap.getValueAt(index).data;
if (user->getUserType() == util::UserType::ADMIN)
{
adminUsers.push_back(user);
}
}
int adminUsersSize = adminUsers.getSize();
if (adminUsersSize < 1)
{
throw std::runtime_error("The system has no admins present!");
}
for (int index = 0; index < inventoryItemsSize; index++)
{
InventoryItem* inventoryItem = trackedInventoryItemsMap.getValueAt(index).data;
if (inventoryItem && inventoryItem->getQuantity() < config::threshold::INVENTORY_LOW_STOCK_THRESHOLD)
{
sendLowStockAlertsToAdmins(*this, inventoryItem, adminUsers);
}
}
}
/*
Function: addInventoryItem
Description: Creates a new inventory item using the Factory and inserts it
into the DataStore.
Parameter: const std::string& partName - name of the part
int quantity - initial quantity of the part
double price - price of the part
Return type: void
*/
void InventoryManagementService::addInventoryItem(const std::string& partName, int quantity, double price)
{
DataStoreLockGuard lock(m_dataStore);
auto& trackedInventoryItemMap = m_dataStore.getInventoryItems();
InventoryItem* newItem = Factory::getObject<InventoryItem>(partName, quantity, price);
trackedInventoryItemMap.insert(newItem->getId(), util::createNewRecord(newItem));
m_dataStore.saveInventoryItems();
}
/*
Function: addInventoryItemStock
Description: Increases the stock quantity of an existing inventory item.
Parameter: const std::string& selectedItemId - ID of the inventory item
int quantity - quantity to add
Return type: void
*/
void InventoryManagementService::addInventoryItemStock(const std::string& selectedItemId, int quantity)
{
DataStoreLockGuard lock(m_dataStore);
auto& trackedInventoryItemMap = m_dataStore.getInventoryItems();
int index = trackedInventoryItemMap.find(selectedItemId);
if (index == -1)
{
throw std::runtime_error("Inventory update failed: Item ID '" + selectedItemId + "' not found.");
}
InventoryItem* item = trackedInventoryItemMap.getValueAt(index).data;
if (item == nullptr)
{
throw std::runtime_error("Inventory update failed. Item does not exist.\n");
}
int totalQuantity = item->getQuantity() + quantity;
item->setQuantity(totalQuantity);
trackedInventoryItemMap.getValueAt(index).state = RecordState::MODIFIED;
m_dataStore.saveInventoryItems();
}
/*
Function: getInventoryItems
Description: Retrieves all inventory items stored in the DataStore.
Parameter: None
Return type: util::Map<std::string, InventoryItem*>
*/
util::Map<std::string, InventoryItem*> InventoryManagementService::getInventoryItems()
{
DataStoreLockGuard lock(m_dataStore);
auto& trackedInventoryItemMap = m_dataStore.getInventoryItems();
auto inventoryMap = util::getObjects(trackedInventoryItemMap);
return inventoryMap;
}
/*
Function: removeInventoryItem
Description: Marks an inventory item as inactive instead of deleting it.
Parameter: const std::string& inventoryItemID - ID of the inventory item
Return type: void
*/
void InventoryManagementService::removeInventoryItem(const std::string& inventoryItemID)
{
DataStoreLockGuard lock(m_dataStore);
auto& trackedInventoryItemMap = m_dataStore.getInventoryItems();
int index = trackedInventoryItemMap.find(inventoryItemID);
if (index == -1)
{
throw std::runtime_error("Inventory removal failed: Item ID '" + inventoryItemID + "' not found.");
}
InventoryItem* item = trackedInventoryItemMap.getValueAt(index).data;
if (item == nullptr)
{
throw std::runtime_error("Inventory removal failed: Item ID does not exist.");
}
item->setState(util::State::INACTIVE);
trackedInventoryItemMap.getValueAt(index).state = RecordState::MODIFIED;
m_dataStore.saveInventoryItems();
}
/*
Function: getInventoryItem
Description: Retrieves a specific inventory item by its ID from the DataStore.
Parameter: const std::string& inventoryItemID - ID of the inventory item
Return type: InventoryItem*
*/
InventoryItem* InventoryManagementService::getInventoryItem(const std::string& inventoryItemID)
{
DataStoreLockGuard lock(m_dataStore);
auto& trackedInventoryItemMap = m_dataStore.getInventoryItems();
int index = trackedInventoryItemMap.find(inventoryItemID);
if (index == -1)
{
return nullptr;
}
InventoryItem* inventoryItem = trackedInventoryItemMap.getValueAt(index).data;
if (inventoryItem == nullptr)
{
throw std::runtime_error("Item ID does not exist.");
}
return inventoryItem;
}
/*
Function: attach
Description: Adds a user to the observer list for receiving inventory notifications.
Parameters:
- user: User*, pointer to the user to be attached as an observer
Returns:
- None
*/
void InventoryManagementService::attach(User* user)
{
DataStoreLockGuard lock(m_dataStore);
m_observers.clear();
m_observers = m_dataStore.getInventoryManagementObservers();
if (user)
{
const std::string& userID = user->getId();
if (m_observers.find(userID) == -1)
{
m_observers[userID] = user;
}
}
m_dataStore.saveInventoryManagementObservers(m_observers);
}
/*
Function: detach
Description: Removes a user from the observer list so they no longer receive inventory notifications.
Parameters:
- user: User*, pointer to the user to be detached from the observer list
Returns:
- None
*/
void InventoryManagementService::detach(User* user)
{
DataStoreLockGuard lock(m_dataStore);
m_observers.clear();
m_observers = m_dataStore.getInventoryManagementObservers();
if (user)
{
const std::string& userID = user->getId();
if (m_observers.find(userID) != -1)
{
m_observers.remove(userID);
}
}
m_dataStore.saveInventoryManagementObservers(m_observers);
}
/*
Function: sendNotification
Description: Sends a notification to a user if they are subscribed as an observer.
Parameters:
- user: User*, pointer to the user receiving the notification
- title: std::string, title of the notification
- message: std::string, body/content of the notification
Returns:
- None
Throws:
- std::runtime_error if notification creation fails
*/
void InventoryManagementService::sendNotification(User* user, const std::string& title, const std::string& message)
{
if (!user)
{
return;
}
DataStoreLockGuard lock(m_dataStore);
m_observers = m_dataStore.getInventoryManagementObservers();
if (m_observers.find(user->getId()) == -1)
{
return;
}
Notification* notification = Factory::getObject<Notification>(
user->getId(),
title,
message,
util::Timestamp());
if (!notification)
{
throw std::runtime_error("Failed to create notification");
}
auto& trackedNotificationsMap = m_dataStore.getNotifications();
trackedNotificationsMap.insert(notification->getId(), util::createNewRecord(notification));
m_dataStore.saveNotifications();
EventManager::sendNotificationAvailableEvent(user->getId());
}