Merged PR 1044: Admin-Management-1560, Inventory-Management-1552

**Admin Management**
**ADM001 - Add Technician:** Allows admins to create technician accounts for job assignments.
**ADM002 - Remove Technician or Customer:** Allows admins to remove technician or customer accounts from the system.
**ADM003 - Login:** Allows admins and technicians to securely log in to access system features.
**ADM004 - Logout:** Allows admins and technicians to securely log out of the system.
**ADM005 - Change Password:** Allows admins and technicians to update their account password for security.
**ADM006 - Create Combo Package:** Allows admins to create discounted combo service packages for customers.
**ADM007 - Remove Combo Package:** Allows admins to remove outdated combo packages from the system.

**Inventory Management**
**INV001 - View Stock Levels:** Allows admins to view current inventory stock levels and track spare part availability.
**INV002 - Add Stock:** Allows admins to add new inventory items or update stock quantities.
**INV003 - Remove Stock:** Allows admins to remove inventory items from the system.
**INV004 - Check Stock Availability:** Allows admins to check the availability of a specific stock item.

Related work items: #1552, #1560, #1573, #1574, #1575, #1576, #1582, #1583, #1584, #1585, #1586, #1587, #1588, #1668, #1669, #1672, #1673
This commit is contained in:
Avinash Rajesh
2026-05-25 19:00:53 +05:30
committed by Joel Thomas
21 changed files with 1362 additions and 198 deletions
@@ -10,6 +10,8 @@ Date:19-May-2026
#include "Controller.h"
#include "Enums.h"
#include "User.h"
#include "ComboPackage.h"
#include "User.h"
/*
Function: login
@@ -72,8 +74,19 @@ const User* Controller::getAuthenticatedUser()
return m_authenticationManagementService.getAuthenticatedUser();
}
void Controller::createTechnician(const std::string& username, const std::string& name, const std::string& password, const std::string& email, const std::string& phone)
/*
Function: createTechnician
Description: Creates a new technician account with provided details by
delegating to the user management service.
Parameter: const std::string& username - technician's username
const std::string& password - technician's password
const std::string& email - technician's email address
const std::string& phoneNumber - technician's phone number
Return type: void
*/
void Controller::createTechnician(const std::string& username, const std::string& name, const std::string& password, const std::string& email, const std::string& phoneNumber)
{
m_userManagementService.createUser(username, name, password, email, phoneNumber, util::UserType::TECHNICIAN);
}
/*
@@ -98,9 +111,26 @@ util::Map<std::string, const Service*> Controller::getServices()
return util::Map<std::string, const Service*>();
}
/*
Function: getComboPackages
Description: Retrieves all available combo packages from the service
management service and constructs a read-only map.
Parameter: None
Return type: util::Map<std::string, const ComboPackage*>
*/
util::Map<std::string, const ComboPackage*> Controller::getComboPackages()
{
return util::Map<std::string, const ComboPackage*>();
util::Map<std::string, ComboPackage*> currentAvailableComboPackages = m_serviceManagementService.getComboPackages();
util::Map<std::string, const ComboPackage*> readOnlyComboPackages;
for (int iterator = 0; iterator < currentAvailableComboPackages.getSize(); iterator++)
{
ComboPackage* currentComboPackage = currentAvailableComboPackages.getValueAt(iterator);
if (currentComboPackage)
{
readOnlyComboPackages.insert(currentComboPackage->getId(), currentComboPackage);
}
}
return readOnlyComboPackages;
}
/*
@@ -131,22 +161,70 @@ void Controller::purchaseComboPackage(const std::string& comboPackageID, const s
m_serviceManagementService.purchaseComboPackage(comboPackageID, vehicleNumber, vehicleBrand, vehicleModel);
}
/*
Function: getInventoryItems
Description: Retrieves all inventory items from the inventory management service
and constructs a read-only map for external use.
Parameter: None
Return type: util::Map<std::string, const InventoryItem*>
*/
util::Map<std::string, const InventoryItem*> Controller::getInventoryItems()
{
return util::Map<std::string, const InventoryItem*>();
auto inventoryItems = m_inventoryManagementService.getInventoryItems();
util::Map<std::string, const InventoryItem*> readOnlyInventoryItems;
int inventoryItemsMapSize = inventoryItems.getSize();
for (int index = 0; index < inventoryItemsMapSize; index++)
{
readOnlyInventoryItems.insert(inventoryItems.getKeyAt(index), inventoryItems.getValueAt(index));
}
return readOnlyInventoryItems;
}
/*
Function: getInventoryItem
Description: Retrieves a specific inventory item by its ID from the inventory management service.
Parameter: const std::string& inventoryItemID - ID of the inventory item
Return type: const InventoryItem*
*/
const InventoryItem* Controller::getInventoryItem(const std::string& inventoryItemID)
{
return nullptr;
return m_inventoryManagementService.getInventoryItem(inventoryItemID);
}
/*
Function: addInventoryItem
Description: Adds a new inventory item with specified details to the inventory management service.
Parameter: const std::string& partName - name of the part
int quantity - quantity of the part
double price - price of the part
Return type: void
*/
void Controller::addInventoryItem(const std::string& partName, int quantity, double price)
{
m_inventoryManagementService.addInventoryItem(partName, quantity, price);
}
/*
Function: removeInventoryItem
Description: Removes an inventory item from the inventory management service by its ID.
Parameter: const std::string& inventoryItemID - ID of the inventory item
Return type: void
*/
void Controller::removeInventoryItem(const std::string& inventoryItemID)
{
m_inventoryManagementService.removeInventoryItem(inventoryItemID);
}
/*
Function: addInventoryItemStock
Description: Adds stock to an existing inventory item in the inventory management service.
Parameter: const std::string& selectedItemId - ID of the inventory item
int quantity - quantity to add
Return type: void
*/
void Controller::addInventoryItemStock(const std::string& selectedItemId, int quantity)
{
m_inventoryManagementService.addInventoryItemStock(selectedItemId, quantity);
}
util::Map<std::string, const ServiceBooking*> Controller::getServiceBookings()
@@ -159,9 +237,22 @@ util::Map<std::string, const ServiceBooking*> Controller::getServiceBookingsByUs
return util::Map<std::string, const ServiceBooking*>();
}
/*
Function: getUsers
Description: Retrieves all users from the user management service and
constructs a read-only map.
Parameter: None
Return type: util::Map<std::string, const User*>
*/
util::Map<std::string, const User*> Controller::getUsers()
{
return util::Map<std::string, const User*>();
auto listOfUsers = m_userManagementService.getUsers();
util::Map<std::string, const User*> readOnlyUserList;
for (int iterator = 0; iterator < listOfUsers.getSize(); iterator++)
{
readOnlyUserList.insert(listOfUsers.getKeyAt(iterator), listOfUsers.getValueAt(iterator));
}
return readOnlyUserList;
}
util::Map<std::string, const User*> Controller::getUsers(util::UserType userType)
@@ -190,16 +281,49 @@ void Controller::completeJob(const std::string& jobID)
{
}
/*
Function: removeUser
Description: Removes a user by ID. Cancels associated service bookings
and technician jobs before removing the user from the system.
Parameter: const std::string& userID - ID of the user to remove
Return type: void
*/
void Controller::removeUser(const std::string& userID)
{
User* user = m_userManagementService.getUser(userID);
if (!user)
{
throw std::runtime_error("Error User not Found.\n");
}
m_serviceManagementService.cancelCustomerServiceBookings(userID);
m_serviceManagementService.cancelTechnicianJobs(userID);
m_userManagementService.removeUser(userID);
}
/*
Function: createComboPackage
Description: Creates a new combo package with specified services and discount
percentage by delegating to the service management service.
Parameter: const std::string& name - name of the combo package
const util::Vector<std::string>& serviceIDs - list of service IDs
double discountPercentage - discount percentage for the package
Return type: void
*/
void Controller::createComboPackage(const std::string& name, const util::Vector<std::string>& serviceIDs, double discountPercentage)
{
m_serviceManagementService.createComboPackage(name, serviceIDs, discountPercentage);
}
/*
Function: removeComboPackage
Description: Removes a combo package by ID by delegating to the service
management service.
Parameter: const std::string& comboPackageID - ID of the combo package
Return type: void
*/
void Controller::removeComboPackage(const std::string& comboPackageID)
{
m_serviceManagementService.removeComboPackage(comboPackageID);
}
util::Map<std::string, const Invoice*> Controller::getInvoicesByUser()
@@ -1,24 +1,26 @@
/*
File: Controller.h
Description: Header file declaring the Controller class, which coordinates
authentication, user management, service management, inventory,
and notifications across the Vehicle Service System.
Description: Header file declaring the Controller class, which manages
user authentication, inventory, services, bookings, job cards,
invoices, and notifications in the system.
Author: Trenser
Date:19-May-2026
*/
#pragma once
#include <string>
#include "AuthenticationManagementService.h"
#include "Enums.h"
#include "InventoryManagementService.h"
#include "Map.h"
#include "PaymentManagementService.h"
#include "ServiceManagementService.h"
#include "UserManagementService.h"
#include "InventoryManagementService.h"
#include "UserManagementService.h"
#include "ServiceManagementService.h"
#include "PaymentManagementService.h"
#include "ServiceManagementService.h"
#include "ServiceManagementService.h"
#include "ServiceManagementService.h"
#include "UserManagementService.h"
#include "UserManagementService.h"
#include "UserManagementService.h"
#include <string>
class Service;
class ComboPackage;
@@ -52,6 +54,7 @@ public:
util::Map<std::string, const InventoryItem*> getInventoryItems();
const InventoryItem* getInventoryItem(const std::string& inventoryItemID);
void addInventoryItem(const std::string& partName, int quantity, double price);
void addInventoryItemStock(const std::string& selectedItemId, int quantity);
void removeInventoryItem(const std::string& inventoryItemID);
util::Map<std::string, const ServiceBooking*> getServiceBookings();
util::Map<std::string, const ServiceBooking*> getServiceBookingsByUser(const std::string userID);
@@ -1,10 +1,10 @@
/*
File: JobCard.cpp
Description: Implements the JobCard class which represents a technicians job assignment in the Vehicle Service Management System.
Provides constructors, accessors, and mutators for job details such as ID, booking, service, technician,
assigned date, completion date, and job status.
Description: Implementation file containing the method definitions of the
JobCard class, including constructors, getters, and setters
for job card attributes.
Author: Trenser
Date: 19-May-2026
Date:19-May-2026
*/
#include <sstream>
@@ -18,12 +18,10 @@ int JobCard::m_uid = 0;
/*
Function: JobCard
Description: Default constructor that initializes a new job card with a unique ID,
null booking, null service, null technician, and default job status.
Parameters:
- None
Returns:
- A new JobCard object.
Description: Default constructor that initializes a new job card with
a unique ID and default values.
Parameter: None
Return type: Constructor
*/
JobCard::JobCard()
: m_id("JC" + std::to_string(++m_uid)),
@@ -1,9 +1,10 @@
/*
File: JobCard.h
Description: Declares the JobCard class which represents a technicians job assignment in the Vehicle Service Management System.
Each job card includes booking details, associated service, technician information, assigned and completion dates, and job status.
Description: Header file declaring the JobCard class, which represents
a service job card containing booking, service, technician,
and status details.
Author: Trenser
Date: 19-May-2026
Date:19-May-2026
*/
#pragma once
@@ -29,7 +30,6 @@ private:
util::Timestamp m_assignedDate;
util::ServiceJobStatus m_status;
util::Timestamp m_completionDate;
public:
JobCard();
JobCard(const std::string& bookingId,
@@ -41,8 +41,6 @@ Parameters:
- vehicleNumber: Vehicle registration number.
- vehicleBrand: Brand of the vehicle.
- vehicleModel: Model of the vehicle.
- assignedTechnicianId: ID of the assigned technician.
- assignedTechnician: Name of the assigned technician.
- discountPercentage: Discount applied to the booking.
Returns:
- A new ServiceBooking object.
@@ -161,6 +159,12 @@ const util::Vector<std::string>& ServiceBooking::getServiceIDs() const
return m_serviceIDs;
}
/*
Function: getServices
Description: Retrieves the services associated with the booking.
Parameter: None
Return type: const util::Map<std::string, Service*>&
*/
/*
Function: getServices
Description: Retrieves the services associated with the booking.
@@ -1,11 +1,12 @@
/*
File: AuthenticationManagementService.cpp
Description: Implementation file containing the method definitions of the
AuthenticationManagementService class, including login, logout,
password change, and retrieval of the authenticated user.
AuthenticationManagementService class, including logout and
password change logic.
Author: Trenser
Date:19-May-2026
*/
#include <stdexcept>
#include "AuthenticationManagementService.h"
#include "User.h"
@@ -6,6 +6,7 @@ Description: Header file declaring the AuthenticationManagementService class, wh
Author: Trenser
Date:19-May-2026
*/
#pragma once
#include <string>
#include "DataStore.h"
@@ -20,86 +20,9 @@ Date: 22-May-2026
#include "Utility.h"
#include "Vector.h"
util::Map<std::string, User*> InventoryManagementService::m_observers{};
/*
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)
{
if (user)
{
const std::string& userID = user->getId();
if (m_observers.find(userID) == -1)
{
m_observers[userID] = user;
}
}
}
/*
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)
{
if (user)
{
const std::string& userID = user->getId();
if (m_observers.find(userID) != -1)
{
m_observers.remove(userID);
}
}
}
/*
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)
{
if (m_observers.find(user->getId()) != -1)
{
Notification* notification =
Factory::getObject<Notification>(
user->getId(),
user,
"InventoryManagementService: " + title,
message,
util::Timestamp()
);
if (notification)
{
user->addNotification(notification);
}
else
{
throw std::runtime_error("Failed to create notification");
}
}
}
}
/*
Function: sendLowStockAlertsToAdmins (static helper)
Description: Sends low stock alert notifications to all admin users for a given inventory item.
@@ -251,3 +174,164 @@ void InventoryManagementService::saveObservers()
{
util::saveObservers(config::file::INVENTORYMANAGEMENTOBSERVERS, this);
}
/*
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)
{
InventoryItem* newItem = Factory::getObject<InventoryItem>(partName, quantity, price);
m_dataStore.getInventoryItems().insert(newItem->getId(), newItem);
}
/*
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)
{
int index = m_dataStore.getInventoryItems().find(selectedItemId);
if (index != -1)
{
InventoryItem* item = m_dataStore.getInventoryItems().getValueAt(index);
if (item != nullptr)
{
int totalQuantity = item->getQuantity() + quantity;
item->setQuantity(totalQuantity);
}
}
}
/*
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()
{
return m_dataStore.getInventoryItems();
}
/*
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)
{
int index = m_dataStore.getInventoryItems().find(inventoryItemID);
if (index != -1)
{
InventoryItem* item = m_dataStore.getInventoryItems().getValueAt(index);
if (item != nullptr)
{
item->setState(util::State::INACTIVE);
}
}
}
/*
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)
{
int index = m_dataStore.getInventoryItems().find(inventoryItemID);
if (index != -1)
{
return m_dataStore.getInventoryItems().getValueAt(index);
}
return nullptr;
}
/*
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)
{
if (user)
{
const std::string& userID = user->getId();
if (m_observers.find(userID) == -1)
{
m_observers[userID] = user;
}
}
}
/*
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)
{
if (user)
{
const std::string& userID = user->getId();
if (m_observers.find(userID) != -1)
{
m_observers.remove(userID);
}
}
}
/*
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)
{
if (m_observers.find(user->getId()) != -1)
{
Notification* notification =
Factory::getObject<Notification>(
user->getId(),
user,
"InventoryManagementService: " + title,
message,
util::Timestamp()
);
if (notification)
{
user->addNotification(notification);
}
else
{
throw std::runtime_error("Failed to create notification");
}
}
}
}
@@ -1,9 +1,10 @@
/*
File: InventoryManagementService.h
Description: Declares the InventoryManagementService class which manages inventory operations in the Vehicle Service Management System.
Provides functionality to retrieve, add, and remove inventory items, send low stock alerts, and handle notifications using the Observer pattern.
Description: Header file declaring the InventoryManagementService class,
which manages inventory items, stock updates, and notifications
related to low stock alerts. Inherits from NotificationManagementService.
Author: Trenser
Date: 19-May-2026
Date:19-May-2026
*/
#pragma once
@@ -27,6 +28,7 @@ public:
InventoryItem* getInventoryItem(const std::string& inventoryItemID);
void addInventoryItem(const std::string& partName, int quantity, double price);
void removeInventoryItem(const std::string& inventoryItemID);
void addInventoryItemStock(const std::string& selectedItemId, int quantity);
void sendLowStockAlerts();
void sendNotification(User* user, const std::string& title, const std::string& message) override;
void attach(User* user) override;
@@ -11,11 +11,15 @@ Date:19-May-2026
#include "AuthenticationManagementService.h"
#include "ComboPackage.h"
#include "Config.h"
#include "DataStore.h"
#include "Factory.h"
#include "FileManager.h"
#include "InventoryItem.h"
#include "JobCard.h"
#include "Service.h"
#include "ServiceBooking.h"
#include "ServiceBooking.h"
#include "ServiceManagementService.h"
#include "Timestamp.h"
#include "User.h"
@@ -500,3 +504,224 @@ void ServiceManagementService::saveObservers()
{
util::saveObservers(config::file::SERVICEMANAGEMENTOBSERVERS, this);
}
/*
Function: cancelCustomerServiceBookings
Description: Cancels all service bookings associated with a given customer or technician.
Updates booking status, resets customer/technician assignments, sends notifications,
and restocks inventory items.
Parameter: const std::string& userID - ID of the customer or technician
Return type: void
*/
void ServiceManagementService::cancelCustomerServiceBookings(const std::string& userID)
{
const int INCREMENT_VALUE = 1;
auto& users = m_dataStore.getUsers();
int userIndex = users.find(userID);
if (userIndex == -1)
{
throw std::runtime_error("User not found: " + userID);
}
User* user = users.getValueAt(userIndex);
if (user == nullptr)
{
throw std::runtime_error("User not found: " + userID);
}
util::UserType type = user->getUserType();
auto& bookings = DataStore::getInstance().getServiceBookings();
for (int bookingIterator = 0; bookingIterator < bookings.getSize(); bookingIterator++)
{
ServiceBooking* booking = bookings.getValueAt(bookingIterator);
if (booking != nullptr &&
(booking->getCustomerId() == userID || booking->getAssignedTechnicianId() == userID))
{
if (booking->getStatus() == util::ServiceJobStatus::PENDING ||
booking->getStatus() == util::ServiceJobStatus::STARTED)
{
if (type == util::UserType::CUSTOMER)
{
booking->setStatus(util::ServiceJobStatus::CANCELLED);
booking->setCustomer(nullptr);
booking->setCustomerId("");
User* assignedTechnician = booking->getAssignedTechnician();
std::string title = "Customer Service Cancelled";
std::string message = "The customer has cancelled their service booking. Your assigned job card has been cancelled and the inventory has been restocked.";
sendNotification(assignedTechnician, title, message);
}
else if (type == util::UserType::TECHNICIAN)
{
booking->setStatus(util::ServiceJobStatus::PENDING);
std::string title = "Technician Unavailable";
std::string message = "Your assigned technician is no longer available. Your booking has been reset to pending, and we will reassign a new technician shortly.";
sendNotification(booking->getCustomer(), title, message);
}
booking->setAssignedTechnician(nullptr);
booking->setAssignedTechnicianId("");
const auto& ListOfServices = booking->getServices();
for (int serviceIterator = 0; serviceIterator < ListOfServices.getSize(); serviceIterator++)
{
Service* service = ListOfServices.getValueAt(serviceIterator);
if (service != nullptr)
{
const auto& items = service->getRequiredInventoryItems();
for (int itemIterator = 0; itemIterator < items.getSize(); itemIterator++)
{
InventoryItem* item = items.getValueAt(itemIterator);
if (item != nullptr)
{
item->setQuantity(item->getQuantity() + INCREMENT_VALUE);
}
}
}
}
}
}
}
}
/*
Function: cancelTechnicianJobs
Description: Cancels all jobs assigned to a technician. Updates job status, sends notifications,
and restocks inventory items used in the service.
Parameter: const std::string& technicianID - ID of the technician
Return type: void
*/
void ServiceManagementService::cancelTechnicianJobs(const std::string& technicianID)
{
const int INCREMENT_VALUE = 1;
auto& jobs = m_dataStore.getJobCards();
for (int jobIterator = 0; jobIterator < jobs.getSize(); jobIterator++)
{
JobCard* job = jobs.getValueAt(jobIterator);
if (job != nullptr && job->getTechnicianId() == technicianID)
{
if (job->getStatus() == util::ServiceJobStatus::PENDING || job->getStatus() == util::ServiceJobStatus::STARTED)
{
job->setStatus(util::ServiceJobStatus::CANCELLED);
std::string title = "Job Cancelled";
std::string message = "The Job has cancelled. Your job card has been cancelled and the inventory has been restocked.";
sendNotification(job->getTechnician(), title, message);
Service* service = job->getService();
if (service != nullptr)
{
const auto& items = service->getRequiredInventoryItems();
for (int itemIterator = 0; itemIterator < items.getSize(); itemIterator++)
{
InventoryItem* item = items.getValueAt(itemIterator);
if (item != nullptr)
{
item->setQuantity(item->getQuantity() + INCREMENT_VALUE);
}
}
}
}
}
}
}
/*
Function: createComboPackage
Description: Creates a new combo package with two services and a discount percentage.
Validates service IDs, ensures uniqueness, and inserts the new package into the DataStore.
Parameter: const std::string& packageName - name of the combo package
const util::Vector<std::string>& serviceIDsInNewCombo - list of service IDs
double discountPercentage - discount percentage for the package
Return type: void
*/
void ServiceManagementService::createComboPackage(const std::string& packageName, const util::Vector<std::string>& serviceIDsInNewCombo, double discountPercentage)
{
if (packageName.empty())
{
throw std::invalid_argument("The Combo Package Name cannot be empty.\n");
}
if (serviceIDsInNewCombo.getSize() < 2 || serviceIDsInNewCombo.getSize() > 2)
{
throw std::invalid_argument("Combo package must contain only two services.");
}
if (discountPercentage < 0.0 || discountPercentage > 100.0)
{
throw std::invalid_argument("Discount percentage must be between 0 and 100.");
}
auto& servicesMap = m_dataStore.getServices();
for (int index = 0; index < serviceIDsInNewCombo.getSize(); index++)
{
const std::string serviceid = serviceIDsInNewCombo[index];
if (servicesMap.find(serviceid) == -1)
{
throw std::runtime_error("Service ID not found: " + serviceid);
}
}
auto& comboPackageMap = m_dataStore.getComboPackages();
for (int iterator = 0; iterator < comboPackageMap.getSize(); iterator++)
{
ComboPackage* existingCombos = comboPackageMap.getValueAt(iterator);
const util::Map<std::string, Service*>& servicesInsideExistingCombos = existingCombos->getServices();
if (servicesInsideExistingCombos.getSize() == serviceIDsInNewCombo.getSize())
{
bool isIdentical = true;
for (int serviceIterator = 0; serviceIterator < serviceIDsInNewCombo.getSize(); serviceIterator++)
{
const std::string& id = serviceIDsInNewCombo[serviceIterator];
if (servicesInsideExistingCombos.find(id) == -1)
{
isIdentical = false;
break;
}
}
if (isIdentical)
{
throw std::runtime_error("A combo package with the same services already exists.");
}
}
}
util::Map<std::string, Service*> selectedServices;
for (int iteratorOne = 0; iteratorOne < serviceIDsInNewCombo.getSize(); iteratorOne++)
{
const std::string& serviceId = serviceIDsInNewCombo[iteratorOne];
int serviceIndex = servicesMap.find(serviceId);
if (serviceIndex == -1)
{
throw std::runtime_error("Service ID not found: " + serviceId);
}
selectedServices.insert(serviceId, servicesMap.getValueAt(serviceIndex));
}
ComboPackage* newComboPackage = Factory::getObject<ComboPackage>(packageName, discountPercentage, selectedServices);
comboPackageMap.insert(newComboPackage->getId(), newComboPackage);
}
/*
Function: getComboPackages
Description: Retrieves all combo packages stored in the DataStore.
Parameter: None
Return type: util::Map<std::string, ComboPackage*>
*/
util::Map<std::string, ComboPackage*> ServiceManagementService::getComboPackages()
{
return m_dataStore.getComboPackages();
}
/*
Function: removeComboPackage
Description: Removes a combo package by marking it inactive. Throws an exception if the package ID is not found.
Parameter: const std::string& comboPackageID - ID of the combo package
Return type: void
*/
void ServiceManagementService::removeComboPackage(const std::string& comboPackageID)
{
bool removed = false;
util::Map<std::string, ComboPackage*>& currentComboPackages = m_dataStore.getComboPackages();
for (int iterator = 0; iterator < currentComboPackages.getSize(); iterator++)
{
ComboPackage* currentComboPackage = currentComboPackages.getValueAt(iterator);
if (currentComboPackage && currentComboPackage->getId() == comboPackageID)
{
currentComboPackage->setState(util::State::INACTIVE);
removed = true;
break;
}
}
if (!removed)
{
throw std::runtime_error("Combo package with ID '" + comboPackageID + "' not found.");
}
}
@@ -6,6 +6,7 @@ Description: Header file declaring the ServiceManagementService class, which man
Author: Trenser
Date:19-May-2026
*/
#pragma once
#include <string>
#include "Map.h"
@@ -38,7 +39,7 @@ public:
void completeJob(const std::string& jobID);
void cancelCustomerServiceBookings(const std::string& customerID);
void cancelTechnicianJobs(const std::string& technicianID);
void createComboPackage(const std::string& name, const util::Vector<std::string>& serviceIDs, double discountPercentage);
void createComboPackage(const std::string& packageName, const util::Vector<std::string>& serviceIDs, double discountPercentage);
void removeComboPackage(const std::string& comboPackageID);
void sendNotification(User* user, const std::string& title, const std::string& message) override;
void attach(User* user) override;
@@ -6,7 +6,6 @@ Description: Implementation file containing the method definitions of the
Author: Trenser
Date:19-May-2026
*/
#include <stdexcept>
#include "Config.h"
#include "Enums.h"
#include "Factory.h"
@@ -18,6 +17,7 @@ Date:19-May-2026
#include "User.h"
#include "UserManagementService.h"
#include "Vector.h"
#include <stdexcept>
/*
@@ -244,3 +244,49 @@ void UserManagementService::saveUsers()
userFileManager.save(users);
notificationFileManager.save(notifications);
}
/*
Function: getUsers
Description: Retrieves all users stored in the DataStore.
Parameter: None
Return type: util::Map<std::string, User*>
*/
util::Map<std::string, User*> UserManagementService::getUsers()
{
return m_dataStore.getUsers();
}
/*
Function: getUser
Description: Retrieves a specific user by ID from the DataStore.
Parameter: const std::string& userID - ID of the user
Return type: User*
*/
User* UserManagementService::getUser(const std::string& userID)
{
int index = m_dataStore.getUsers().find(userID);
if (index != -1)
{
return m_dataStore.getUsers().getValueAt(index);
}
return nullptr;
}
/*
Function: removeUser
Description: Marks a user as inactive in the DataStore instead of deleting them.
Parameter: const std::string& userID - ID of the user to remove
Return type: void
*/
void UserManagementService::removeUser(const std::string& userID)
{
int index = m_dataStore.getUsers().find(userID);
if (index != -1)
{
User* user = m_dataStore.getUsers().getValueAt(index);
if (user != nullptr)
{
user->setState(util::State::INACTIVE);
}
}
}
@@ -33,8 +33,10 @@ namespace util
enum class ServiceJobStatus
{
PENDING,
STARTED,
COMPLETED
COMPLETED,
CANCELLED
};
enum class State
@@ -192,10 +194,14 @@ namespace util
{
switch (status)
{
case ServiceJobStatus::PENDING:
return "PENDING";
case ServiceJobStatus::STARTED:
return "STARTED";
case ServiceJobStatus::COMPLETED:
return "COMPLETED";
case ServiceJobStatus::CANCELLED:
return "CANCELLED";
}
throw std::invalid_argument("Invalid ServiceJobStatus");
}
@@ -220,6 +226,14 @@ namespace util
{
return ServiceJobStatus::COMPLETED;
}
if (value == "PENDING")
{
return ServiceJobStatus::PENDING;
}
if (value == "CANCELLED")
{
return ServiceJobStatus::CANCELLED;
}
throw std::invalid_argument("Invalid ServiceJobStatus string");
}
@@ -1,18 +1,18 @@
/*
File: Utility.h
Description: Header file declaring utility functions used across the system,
including cost calculation for services and combo packages.
Description: Header file declaring utility functions used across the system
Author: Trenser
Date:19-May-2026
*/
#pragma once
#include "ComboPackage.h"
#include "DataStore.h"
#include "FileHelper.h"
#include "InventoryItem.h"
#include "InventoryItem.h"
#include "NotificationManagementService.h"
#include "Service.h"
#include "ComboPackage.h"
namespace util
{
@@ -8,34 +8,54 @@ Author: Trenser
Date: 19-May-2026
*/
#include <iomanip>
#include <iostream>
#include "AdminMenu.h"
#include "ComboPackage.h"
#include "Enums.h"
#include "InputHelper.h"
#include "OutputHelper.h"
#include "InventoryItem.h"
#include "MenuHelper.h"
#include "OutputHelper.h"
#include "Service.h"
#include "User.h"
#include "Utility.h"
#include "Validator.h"
/*
Function: showMenu
Description: Displays the admin menu in a loop until the user chooses to logout.
Handles exceptions and ensures smooth user interaction.
Parameters:
- None
Returns:
- void
Description: Displays the admin menu and handles user input until logout is selected.
Parameter: None
Return type: void
*/
void AdminMenu::showMenu()
{
bool isMenuActive = true;
while (isMenuActive)
while (true)
{
try
{
int choice;
util::clear();
std::cout << "" << std::endl;
std::cout << "Admin Menu"
<< "\n1. View Stock Levels"
<< "\n2. Add Inventory Item"
<< "\n3. Remove Inventory Item"
<< "\n4. Check Stock Availability"
<< "\n5. Assign Job to Technician"
<< "\n6. Add Technician"
<< "\n7. Remove Customer/Technician"
<< "\n8. Create Service"
<< "\n9. Remove Service"
<< "\n10. Create Combo Package"
<< "\n11. Remove Combo Package"
<< "\n12. View Notifications"
<< "\n13. Change Password"
<< "\n14. Logout"
<< "\nEnter a choice: ";
util::read(choice);
if (!handleOperation(choice))
{
isMenuActive = false;
break;
}
}
catch (const std::exception& e)
@@ -46,34 +66,228 @@ void AdminMenu::showMenu()
}
}
/*
Function: handleOperation
Description: Executes the corresponding admin operation based on the selected menu choice.
Parameter: int choice - selected menu option
Return type: bool - true if menu continues, false if logout
*/
bool AdminMenu::handleOperation(int choice)
{
switch (choice)
{
case 1:
viewStockLevels();
break;
case 2:
addInventoryItem();
break;
case 3:
removeInventoryItem();
break;
case 4:
checkStockAvailability();
break;
case 5:
assignJob();
break;
case 6:
addTechnician();
break;
case 7:
removeUser();
break;
case 8:
createService();
break;
case 9:
removeService();
break;
case 10:
createComboPackages();
break;
case 11:
removeComboPackage();
break;
case 12:
viewNotifications();
break;
case 13:
changePassword();
break;
case 14:
logout();
return false;
default:
std::cout << "Enter a valid choice!" << std::endl;
util::pressEnter();
}
return true;
}
/*
Function: logout
Description: Logs out the currently authenticated admin user.
Parameter: None
Return type: void
*/
void AdminMenu::logout()
{
m_controller.logout();
}
/*
Function: changePassword
Description: Allows the admin to change their password after validation.
Parameter: None
Return type: void
*/
void AdminMenu::changePassword()
{
changePasswordHelper(m_controller);
}
/*
Function: viewStockLevels
Description: Displays all active inventory items with their details
including ID, part name, quantity, and price.
Parameter: None
Return type: void
*/
void AdminMenu::viewStockLevels()
{
util::clear();
auto inventoryItems = m_controller.getInventoryItems();
std::cout << std::left << std::setw(15) << "Item ID"
<< std::setw(25) << "Part Name"
<< std::setw(10) << "Quantity"
<< std::setw(10) << "Price"
<< std::endl;
for (int iterator = 0; iterator < inventoryItems.getSize(); ++iterator)
{
const InventoryItem* item = inventoryItems.getValueAt(iterator);
if (item != nullptr)
{
if (item->getState() != util::State::INACTIVE)
{
std::cout << std::left << std::setw(15) << item->getId()
<< std::setw(25) << item->getPartName()
<< std::setw(10) << item->getQuantity()
<< std::setw(10) << item->getPrice()
<< std::endl;
}
}
}
}
/*
Function: addInventoryItem
Description: Allows the admin to either add a new inventory item
or increase the quantity of an existing item.
Parameter: None
Return type: void
*/
void AdminMenu::addInventoryItem()
{
util::clear();
int choice, quantity;
double price;
std::string partName;
std::cout << "1. Add new item \n2. Add Quantity\nEnter your choice : ";
util::read(choice);
switch (choice)
{
case 1:
{
std::cout << "--------Enter Item Details----------\n";
std::cout << "Part Name : ";
util::read(partName);
std::cout << "Quantity : ";
util::read(quantity);
std::cout << "Price : ";
util::read(price);
m_controller.addInventoryItem(partName, quantity, price);
std::cout << "New Item " << partName << " added to the Inventory.\n";
break;
}
case 2:
{
auto inventoryItems = m_controller.getInventoryItems();
addQuantityToItem(inventoryItems, m_controller);
break;
}
}
util::pressEnter();
}
/*
Function: removeInventoryItem
Description: Removes an active inventory item by marking it inactive
after user selection.
Parameter: None
Return type: void
*/
void AdminMenu::removeInventoryItem()
{
util::clear();
auto inventoryItems = m_controller.getInventoryItems();
auto activeItems = filterActiveItems(inventoryItems);
int activeItemsSize = activeItems.getSize();
if (activeItemsSize == 0)
{
std::cout << "No items available in Inventory." << std::endl;
util::pressEnter();
return;
}
displayInventoryWithItems(activeItems);
int itemIndex;
std::cout << "Enter the index of the item to remove: ";
util::read(itemIndex);
if (itemIndex < 1 || itemIndex > activeItemsSize)
{
std::cout << "Invalid index selected." << std::endl;
util::pressEnter();
return;
}
const InventoryItem* selectedItem = activeItems.getValueAt(itemIndex - 1);
if (selectedItem != nullptr)
{
if(selectedItem->getState() != util::State::INACTIVE)
{
std::string selectedItemId = selectedItem->getId();
m_controller.removeInventoryItem(selectedItemId);
std::cout << "Item " << selectedItem->getPartName() << " removed successfully." << std::endl;
}
}
util::pressEnter();
}
/*
Function: checkStockAvailability
Description: Checks if a specific inventory item is available
and displays its details if active.
Parameter: None
Return type: void
*/
void AdminMenu::checkStockAvailability()
{
util::clear();
std::string itemId;
std::cout << "Enter the Item Id : ";
util::read(itemId);
const InventoryItem* selectedItem = m_controller.getInventoryItem(itemId);
if (selectedItem != nullptr)
{
if (selectedItem->getState() != util::State::INACTIVE)
{
std::cout << "Item Details\n";
std::cout << "---------------------------------------------\n";
std::cout << "Item ID : " << selectedItem->getId() << "\n";
std::cout << "Part Name : " << selectedItem->getPartName() << "\n";
std::cout << "Quantity : " << selectedItem->getQuantity() << "\n";
}
}
util::pressEnter();
}
void AdminMenu::assignJob()
@@ -88,20 +302,168 @@ void AdminMenu::removeService()
{
}
/*
Function: addTechnician
Description: Adds a new technician after validating username, password, email, and phone number.
Parameter: None
Return type: void
*/
void AdminMenu::addTechnician()
{
util::clear();
std::string username, name, password, email, phoneNumber;
std::cout << std::left << std::setw(25) << "Enter Technician Username: ";
util::read(username);
std::cout << std::left << std::setw(25) << "Enter Technician Name: ";
util::read(name);
std::cout << std::setw(25) << "Enter Technician Password: ";
util::read(password);
if(!util::isPasswordValid(password))
{
std::cout << "Error: Password is invalid!";
util::pressEnter();
return;
}
std::cout << std::setw(25) << "Enter Technician Email: ";
util::read(email);
if(!util::isEmailValid(email))
{
std::cout << "Error: Email is invalid!";
util::pressEnter();
return;
}
std::cout << std::setw(25) << "Enter Technician Phone: ";
util::read(phoneNumber);
if(!util::isPhoneNumberValid(phoneNumber))
{
std::cout << "Error: Phone Number is invalid!";
util::pressEnter();
return;
}
m_controller.createTechnician(username, name, password, email, phoneNumber);
std::cout << "\nTechnician Added Successfully.\n";
util::pressEnter();
}
/*
Function: removeUser
Description: Removes a selected active user (customer or technician) from the system.
Parameter: None
Return type: void
*/
void AdminMenu::removeUser()
{
util::clear();
int indexChoice;
auto listOfUsers = m_controller.getUsers();
auto listOfActiveUsers = filterActiveUsers(listOfUsers);
int activeUserCount = listOfActiveUsers.getSize();
if (activeUserCount < 1)
{
std::cout << "No Active users." << std::endl;
util::pressEnter();
return;
}
displayAllActiveUsers(listOfActiveUsers, activeUserCount);
std::cout << "Enter the index of the user to delete : ";
util::read(indexChoice);
if (indexChoice < 1 || indexChoice > activeUserCount)
{
std::cout << "Error Invaild index.\n" << std::endl;
util::pressEnter();
return;
}
const User* userToRemove = listOfActiveUsers.getValueAt(indexChoice - 1);
if (userToRemove != nullptr)
{
std::string userIdToRemove = userToRemove->getId();
m_controller.removeUser(userIdToRemove);
std::cout << userToRemove->getUserName() << " removed Successfully.\n";
}
util::pressEnter();
}
/*
Function: createComboPackages
Description: Creates a new combo package by selecting two active services and applying a discount.
Parameter: None
Return type: void
*/
void AdminMenu::createComboPackages()
{
util::clear();
auto serviceList = m_controller.getServices();
const int NUMBER_OF_SERVICE_PER_PACKAGE = 2;
util::Vector<std::string> selectedServiceID;
for (int iterator = 0; iterator < NUMBER_OF_SERVICE_PER_PACKAGE; iterator++)
{
const Service* chosenService = nullptr;
while (true)
{
chosenService = selectServiceFromServices(serviceList);
if (chosenService == nullptr)
{
std::cout << "Failed to create combo package!";
util::pressEnter();
return;
}
bool alreadyChosen = false;
for (int iteratorOne = 0; iteratorOne < selectedServiceID.getSize(); iteratorOne++)
{
if (selectedServiceID[iteratorOne] == chosenService->getId())
{
alreadyChosen = true;
break;
}
}
if (alreadyChosen)
{
std::cout << "Service already selected. Please choose a different one." << std::endl;
continue;
}
selectedServiceID.push_back(chosenService->getId());
util::clear();
break;
}
}
std::string packageName;
double discountPercentage;
std::cout << "Enter combo package name: ";
util::read(packageName);
std::cout << "Enter discount percentage: ";
util::read(discountPercentage);
if (discountPercentage < 0.0 || discountPercentage > 100.0)
{
std::cout << "Error: Discount percentage must be between 0 and 100." << std::endl;
util::pressEnter();
return;
}
m_controller.createComboPackage(packageName, selectedServiceID, discountPercentage);
std::cout << "Combo package '" << packageName << "' created successfully." << std::endl;
util::pressEnter();
}
/*
Function: removeComboPackage
Description: Removes a selected combo package from the system.
Parameter: None
Return type: void
*/
void AdminMenu::removeComboPackage()
{
util::clear();
util::Map<std::string, const ComboPackage*> currentComboPackages = m_controller.getComboPackages();
std::string selectedComboPackageID = selectComboPackage(currentComboPackages);
if (selectedComboPackageID != "")
{
m_controller.removeComboPackage(selectedComboPackageID);
std::cout << "Combo Package removed successfully.\n";
}
else
{
std::cout << "Combo package removal failed.\n";
}
util::pressEnter();
}
/*
@@ -1,10 +1,10 @@
/*
File: AdminMenu.h
Description: Declares the AdminMenu class which provides the administrative console menu in the Vehicle Service Management System.
Supports operations such as inventory management, job assignment, service creation/removal, technician management,
combo package handling, notification viewing, and account management functions like logout and password change.
Description: Header file declaring the AdminMenu class, which provides
administrative operations such as inventory management,
user management, service configuration, and notifications.
Author: Trenser
Date: 19-May-2026
Date:19-May-2026
*/
#pragma once
@@ -8,8 +8,10 @@ Date: 21-May-2026
*/
#pragma once
#include <iostream>
#include <iomanip>
#include <string>
#include "Utility.h"
#include "Controller.h"
#include "InputHelper.h"
#include "Map.h"
@@ -125,6 +127,7 @@ Return type: void
*/
inline void changePasswordHelper(Controller& controller)
{
util::clear();
std::string newPassword;
while (true)
{
@@ -144,6 +147,61 @@ inline void changePasswordHelper(Controller& controller)
}
}
/*
Function: filterActiveUsers
Description: Filters out inactive users and returns a map of active users.
Parameter: const util::Map<std::string, const User*>& listOfUsers - all users
Return type: util::Map<std::string, const User*>
*/
inline util::Map<std::string, const User*> filterActiveUsers(const util::Map<std::string, const User*>& listOfUsers)
{
util::Map<std::string, const User*> activeUsers;
int inventorySize = listOfUsers.getSize();
for (int index = 0; index < inventorySize; index++)
{
const User* user = listOfUsers.getValueAt(index);
if (user != nullptr && user->getState() != util::State::INACTIVE)
{
activeUsers.insert(user->getId(), user);
}
}
return activeUsers;
}
/*
Function: displayAllActiveUsers
Description: Displays all active users in a tabular format with index, ID, username, and type.
Parameter: util::Map<std::string, const User*>& activeUsers - active users list
int activeUserCount - number of active users
Return type: void
*/
inline void displayAllActiveUsers(util::Map<std::string, const User*>& activeUsers, int activeUserCount)
{
std::cout << std::left << std::setw(10) << "Index"
<< std::setw(15) << "User ID"
<< std::setw(25) << "Username"
<< std::setw(25) << "User Type"
<< std::endl;
for (int iterator = 0; iterator < activeUserCount; iterator++)
{
const User* user = activeUsers.getValueAt(iterator);
if (user != nullptr)
{
std::cout << std::left << std::setw(10) << (iterator + 1)
<< std::setw(15) << user->getId()
<< std::setw(25) << user->getUserName()
<< std::setw(25) << util::getUserTypeString(user->getUserType())
<< std::endl;
}
else
{
std::cout << "No users found.\n";
util::pressEnter();
return;
}
}
}
/*
Function: selectServiceFromServices
Description: Displays active services and allows the customer to select one by index.
@@ -164,6 +222,11 @@ inline const Service* selectServiceFromServices(const util::Map<std::string, con
for (int index = 0; index < services.getSize(); index++)
{
const Service* currentService = services.getValueAt(index);
if (currentService == nullptr)
{
throw std::runtime_error("Warning: Encountered a null service\n");
continue;
}
if (currentService->getState() != util::State::ACTIVE)
{
continue;
@@ -285,3 +348,182 @@ inline bool getNotificationPreference(const std::string& serviceName)
}
}
/*
Function: filterActiveItems
Description: Filters out inactive inventory items and returns a map
containing only active items.
Parameter: const util::Map<std::string, const InventoryItem*>& inventoryItems -
map of all inventory items
Return type: util::Map<std::string, const InventoryItem*>
*/
inline util::Map<std::string, const InventoryItem*> filterActiveItems(const util::Map<std::string, const InventoryItem*>& inventoryItems)
{
util::Map<std::string, const InventoryItem*> activeItems;
int inventorySize = inventoryItems.getSize();
for (int index = 0; index < inventorySize; index++)
{
const InventoryItem* item = inventoryItems.getValueAt(index);
if (item != nullptr && item->getState() != util::State::INACTIVE)
{
activeItems.insert(item->getId(), item);
}
}
return activeItems;
}
/*
Function: displayInventoryWithItems
Description: Displays inventory items in a tabular format with index, ID,
part name, quantity, and price.
Parameter: util::Map<std::string, const InventoryItem*>& inventoryItems -
map of inventory items to display
Return type: void
*/
inline void displayInventoryWithItems(util::Map<std::string, const InventoryItem*>& inventoryItems)
{
int inventorySize = inventoryItems.getSize();
std::cout << std::left << std::setw(10) << "Index"
<< std::setw(15) << "Item ID"
<< std::setw(25) << "Part Name"
<< std::setw(10) << "Quantity"
<< std::setw(10) << "Price"
<< std::endl;
for (int iterator = 0; iterator < inventorySize; iterator++)
{
const InventoryItem* item = inventoryItems.getValueAt(iterator);
if (item != nullptr)
{
std::cout << std::left << std::setw(10) << (iterator + 1)
<< std::setw(15) << item->getId()
<< std::setw(25) << item->getPartName()
<< std::setw(10) << item->getQuantity()
<< std::setw(10) << item->getPrice()
<< std::endl;
}
}
}
/*
Function: addQuantityToItem
Description: Allows the admin to select an active inventory item and
increase its stock quantity.
Parameter: util::Map<std::string, const InventoryItem*>& inventoryItems -
map of inventory items
Controller& m_controller - controller instance to update stock
Return type: void
*/
inline void addQuantityToItem(util::Map<std::string, const InventoryItem*>& inventoryItems, Controller& m_controller)
{
int itemIndex;
int quantity;
auto activeItems = filterActiveItems(inventoryItems);
int activeSize = activeItems.getSize();
if (activeSize == 0)
{
std::cout << "No active items available in Inventory" << std::endl;
return;
}
displayInventoryWithItems(activeItems);
std::cout << "Enter the index of the item to update: ";
util::read(itemIndex);
if (itemIndex < 1 || itemIndex > activeSize)
{
std::cout << "Invalid index selected." << std::endl;
return;
}
std::cout << "Enter quantity to add: ";
util::read(quantity);
if (quantity < 0)
{
std::cout << "The quantity should be Greater than 0." << std::endl;
return;
}
const InventoryItem* selectedItem = activeItems.getValueAt(itemIndex - 1);
if (selectedItem != nullptr)
{
std::string selectedItemId = selectedItem->getId();
m_controller.addInventoryItemStock(selectedItemId, quantity);
std::cout << "Updated " << selectedItem->getPartName()
<< " stock. New quantity: " << selectedItem->getQuantity()
<< std::endl;
}
else
{
std::cout << "Error: Selected item could not be found." << std::endl;
}
}
/*
Function: displayComboPackagesWithIndex
Description: Displays combo packages with index, ID, name, and discount percentage.
Parameter: util::Map<int, const ComboPackage*>& currentComboPackageIndexMap - combo packages map
Return type: void
*/
inline void displayComboPackagesWithIndex(util::Map<int, const ComboPackage*>& currentComboPackageIndexMap)
{
for (int iterator = 0; iterator < currentComboPackageIndexMap.getSize(); iterator++)
{
const ComboPackage* currentComboPackage = currentComboPackageIndexMap.getValueAt(iterator);
if (currentComboPackage == nullptr)
{
throw std::runtime_error("Error accessing the combopackage.\n");
}
if (iterator == 0)
{
std::cout << std::left
<< std::setw(8) << "Index"
<< std::setw(10) << "ID"
<< std::setw(20) << "Package Name"
<< std::setw(15) << "Discount (%)"
<< "\n";
}
std::cout << std::left
<< std::setw(8) << currentComboPackageIndexMap.getKeyAt(iterator)
<< std::setw(10) << currentComboPackage->getId()
<< std::setw(20) << currentComboPackage->getPackageName()
<< std::setw(15) << currentComboPackage->getDiscountPercentage()
<< "\n";
}
}
/*
Function: selectComboPackage
Description: Allows the admin to select an active combo package by index.
Parameter: util::Map<std::string, const ComboPackage*>& currentComboPackages - combo packages list
Return type: std::string - ID of the selected combo package
*/
inline std::string selectComboPackage(util::Map<std::string, const ComboPackage*>& currentComboPackages)
{
util::Map<int, const ComboPackage*> currentComboPackageIndexMap;
if (currentComboPackages.getSize() == 0)
{
throw std::runtime_error("No combo packages are available.\n");
}
int currentIndex = 1, choice, selectedIndex;
for (int iterator = 0; iterator < currentComboPackages.getSize(); iterator++)
{
if (currentComboPackages.getValueAt(iterator)->getState() == util::State::INACTIVE)
{
continue;
}
currentComboPackageIndexMap.insert(currentIndex++, currentComboPackages.getValueAt(iterator));
}
if (currentComboPackageIndexMap.getSize() == 0)
{
throw std::runtime_error("No combo packages currently active.");
}
displayComboPackagesWithIndex(currentComboPackageIndexMap);
std::cout << "Enter your choice(Index): ";
util::read(choice);
selectedIndex = currentComboPackageIndexMap.find(choice);
if (selectedIndex != -1)
{
std::string selectedComboPackageID = currentComboPackageIndexMap.getValueAt(selectedIndex)->getId();
return selectedComboPackageID;
}
else
{
std::cout << "Enter a valid choice.\n";
return "";
}
}
@@ -1,15 +1,16 @@
/*
File: TechnicianMenu.cpp
Description: Implements the TechnicianMenu class which provides the technicians console interface
in the Vehicle Service Management System. Handles menu display, user input, and
technician-specific operations such as completing jobs and viewing notifications.
Description: Implementation file containing the method definitions of the
TechnicianMenu class, including menu handling, job completion,
notification viewing, password management, and logout logic.
Author: Trenser
Date: 19-May-2026
Date:19-May-2026
*/
#include "TechnicianMenu.h"
#include "InputHelper.h"
#include "OutputHelper.h"
#include "Validator.h"
#include "MenuHelper.h"
#include "MenuHelper.h"
/*
@@ -23,18 +24,22 @@ Returns:
*/
void TechnicianMenu::showMenu()
{
bool isMenuActive = true;
while (isMenuActive)
while (true)
{
try
{
int choice;
util::clear();
std::cout << "" << std::endl;
std::cout << "Technician Menu"
<< "\n1. Mark Job as Completed"
<< "\n2. View Notifications"
<< "\n3. Change Password"
<< "\n4. Logout"
<< "\nEnter a choice: ";
util::read(choice);
if (!handleOperation(choice))
{
isMenuActive = false;
break;
}
}
catch (const std::exception& e)
@@ -45,11 +50,36 @@ void TechnicianMenu::showMenu()
}
}
/*
Function: handleOperation
Description: Executes the corresponding technician operation based on the selected menu choice.
Parameter: int choice - selected menu option
Return type: bool - true if menu continues, false if logout
*/
bool TechnicianMenu::handleOperation(int choice)
{
switch (choice)
{
case 1:
completeJob();
break;
case 2:
viewNotifications();
break;
case 3:
changePassword();
break;
case 4:
logout();
return false;
default:
std::cout << "Enter a valid choice!" << std::endl;
util::pressEnter();
}
return true;
}
void TechnicianMenu::completeJob()
{
}
@@ -66,3 +96,26 @@ void TechnicianMenu::viewNotifications()
{
viewAndDeleteNotification(m_controller);
}
/*
Function: logout
Description: Logs out the currently authenticated technician user.
Parameter: None
Return type: void
*/
void TechnicianMenu::logout()
{
m_controller.logout();
}
/*
Function: changePassword
Description: Allows the technician to change their password after validation.
Parameter: None
Return type: void
*/
void TechnicianMenu::changePassword()
{
changePasswordHelper(m_controller);
}
@@ -1,9 +1,10 @@
/*
File: TechnicianMenu.h
Description: Declares the TechnicianMenu class which provides the technician-facing console menu in the Vehicle Service Management System.
Supports operations such as viewing assigned jobs, completing jobs, and managing notifications.
Description: Header file declaring the TechnicianMenu class, which provides
technician operations such as job completion, notification viewing,
password management, and logout functionality.
Author: Trenser
Date: 19-May-2026
Date:19-May-2026
*/
#pragma once
@@ -18,4 +19,6 @@ public:
void showMenu();
void completeJob();
void viewNotifications();
void logout();
void changePassword();
};
@@ -5,13 +5,13 @@ Description: Implementation file containing the method definitions of the
and customer registration logic.
Author: Trenser
Date:19-May-2026
*/
#include "UserInterface.h"
#include "Enums.h"
#include "InputHelper.h"
#include "OutputHelper.h"
#include "Enums.h"
#include "User.h"
#include "UserInterface.h"
#include "Validator.h"
/*
@@ -7,6 +7,7 @@ Description: Header file declaring the UserInterface class, which provides
Author: Trenser
Date:19-May-2026
*/
#pragma once
#include "Controller.h"
#include "AdminMenu.h"