Compare commits

..

8 Commits

Author SHA1 Message Date
joelthomastrenser 70bce90865 Merge branch 'feature-file-management' into feature 2026-05-22 17:21:03 +05:30
joelthomastrenser a32e5b07ae Merge branch 'feature-notification-management' into feature 2026-05-22 15:47:57 +05:30
joelthomastrenser 1a77e85daa Merge branch 'feature-admin-management' into feature 2026-05-22 14:19:36 +05:30
Avinash Rajesh dd738be4de Add standardized documentation headers 2026-05-22 12:59:36 +05:30
joelthomastrenser 401a5d8369 Merge branch 'feature-payment-management' into feature 2026-05-22 12:47:18 +05:30
joelthomastrenser 80e860bd12 Merge branch 'feature-inventory-management' into feature 2026-05-22 12:37:34 +05:30
joelthomastrenser 9eaf81ca3d Merge branch 'feature-service-management' into feature 2026-05-22 12:28:53 +05:30
joelthomastrenser ba5f96c22d Implement serialization/deserialization and persistent storage across services
- Add serialize/deserialize support for core models
- Add file-based load/save functions in management services
- Introduce FileManager, Config, Utility and helper utilities
- Persist observer IDs for notification services
- Resolve object relationships during load (services, bookings, invoices, job cards)
- Add controller-level loadSystemData/saveSystemData
- Load data at app startup and save on shutdown
2026-05-22 12:13:17 +05:30
41 changed files with 2023 additions and 4013 deletions
@@ -233,6 +233,12 @@
<ClInclude Include="models\ComboPackage.h"> <ClInclude Include="models\ComboPackage.h">
<Filter>Header Files\Models</Filter> <Filter>Header Files\Models</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="views\MenuHelper.h">
<Filter>Header Files\Views</Filter>
</ClInclude>
<ClInclude Include="utilities\Utility.h">
<Filter>Header Files\Utilities</Filter>
</ClInclude>
<ClInclude Include="utilities\Config.h"> <ClInclude Include="utilities\Config.h">
<Filter>Header Files\Utilities</Filter> <Filter>Header Files\Utilities</Filter>
</ClInclude> </ClInclude>
@@ -245,11 +251,5 @@
<ClInclude Include="utilities\FileHelper.h"> <ClInclude Include="utilities\FileHelper.h">
<Filter>Header Files\Utilities</Filter> <Filter>Header Files\Utilities</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="utilities\Utility.h">
<Filter>Header Files\Utilities</Filter>
</ClInclude>
<ClInclude Include="views\MenuHelper.h">
<Filter>Header Files\Views</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>
@@ -1,13 +1,13 @@
/* /*
File: Controller.cpp File: Controller.cpp
Description: Implementation file containing the method definitions of the Description: Implementation file containing the method definitions
Controller class, including authentication, user creation, of the Controller class, which manages user authentication,
service purchasing, and system checks. inventory, services, bookings, and notifications.
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#include "ComboPackage.h"
#include "Controller.h" #include "Controller.h"
#include "ComboPackage.h"
#include "Enums.h" #include "Enums.h"
#include "InventoryItem.h" #include "InventoryItem.h"
#include "Invoice.h" #include "Invoice.h"
@@ -15,14 +15,15 @@ Date:19-May-2026
#include "Service.h" #include "Service.h"
#include "ServiceBooking.h" #include "ServiceBooking.h"
#include "User.h" #include "User.h"
#include "User.h"
#include <stdexcept> #include <stdexcept>
/* /*
Function: login Function: login
Description: Authenticates a user by delegating to the authentication management service. Description: Authenticates a user based on provided credentials.
Parameter: const std::string& username - users username Parameter: const std::string& username - the username of the user
const std::string& password - users password const std::string& password - the password of the user
Return type: bool - true if login successful, false otherwise Return type: bool
*/ */
bool Controller::login(const std::string& username, const std::string& password) bool Controller::login(const std::string& username, const std::string& password)
{ {
@@ -31,7 +32,8 @@ bool Controller::login(const std::string& username, const std::string& password)
/* /*
Function: logout Function: logout
Description: Logs out the currently authenticated user. Description: Logs out the currently authenticated user by delegating
to the authentication management service.
Parameter: None Parameter: None
Return type: void Return type: void
*/ */
@@ -42,8 +44,9 @@ void Controller::logout()
/* /*
Function: changePassword Function: changePassword
Description: Changes the password of the currently authenticated user. Description: Updates the password of the authenticated user by delegating
Parameter: const std::string& newPassword - new password to set to the authentication management service.
Parameter: const std::string& newPassword - the new password to set
Return type: void Return type: void
*/ */
void Controller::changePassword(const std::string& newPassword) void Controller::changePassword(const std::string& newPassword)
@@ -51,28 +54,11 @@ void Controller::changePassword(const std::string& newPassword)
m_authenticationManagementService.changePassword(newPassword); m_authenticationManagementService.changePassword(newPassword);
} }
/*
Function: createCustomer
Description: Creates a new customer account with the provided details.
Parameter: const std::string& username - customers username
const std::string& name - customers name
const std::string& password - customers password
const std::string& email - customers email
const std::string& phone - customers phone number
Return type: void
*/
void Controller::createCustomer(const std::string& username, const std::string& name, const std::string& password, const std::string& email, const std::string& phone) void Controller::createCustomer(const std::string& username, const std::string& name, const std::string& password, const std::string& email, const std::string& phone)
{ {
m_userManagementService.createUser(username, name, password, email, phone, util::UserType::CUSTOMER); m_userManagementService.createUser(username, name, password, email, phone, util::UserType::CUSTOMER);
} }
/*
Function: getAuthenticatedUser
Description: Retrieves the currently authenticated user.
Parameter: None
Return type: const User* - pointer to the authenticated user
*/
const User* Controller::getAuthenticatedUser() const User* Controller::getAuthenticatedUser()
{ {
return m_authenticationManagementService.getAuthenticatedUser(); return m_authenticationManagementService.getAuthenticatedUser();
@@ -93,13 +79,6 @@ void Controller::createTechnician(const std::string& username, const std::string
m_userManagementService.createUser(username, name, password, email, phoneNumber, util::UserType::TECHNICIAN); m_userManagementService.createUser(username, name, password, email, phoneNumber, util::UserType::TECHNICIAN);
} }
/*
Function: updateUserDetails
Description: Updates the email and phone details of the currently authenticated user.
Parameter: const std::string& email - new email address
const std::string& phone - new phone number
Return type: void
*/
void Controller::updateUserDetails(const std::string& email, const std::string& phone) void Controller::updateUserDetails(const std::string& email, const std::string& phone)
{ {
User* authenticatedUser = m_authenticationManagementService.getAuthenticatedUser(); User* authenticatedUser = m_authenticationManagementService.getAuthenticatedUser();
@@ -110,14 +89,6 @@ void Controller::updateUserDetails(const std::string& email, const std::string&
m_userManagementService.updateUserDetails(authenticatedUser->getId(), email, phone); m_userManagementService.updateUserDetails(authenticatedUser->getId(), email, phone);
} }
/*
Function: getServices
Description: Retrieves all available services in read-only form.
Parameters:
- None
Returns:
- util::Map<std::string, const Service*> containing all services
*/
util::Map<std::string, const Service*> Controller::getServices() util::Map<std::string, const Service*> Controller::getServices()
{ {
util::Map<std::string, Service*> currentServices = m_serviceManagementService.getServices(); util::Map<std::string, Service*> currentServices = m_serviceManagementService.getServices();
@@ -151,29 +122,11 @@ util::Map<std::string, const ComboPackage*> Controller::getComboPackages()
return readOnlyComboPackages; return readOnlyComboPackages;
} }
/*
Function: purchaseService
Description: Purchases one or more services for a vehicle by delegating to the service management service.
Parameter: const util::Vector<std::string>& serviceIDs - IDs of services to purchase
const std::string& vehicleNumber - vehicle registration number
const std::string& vehicleBrand - brand of the vehicle
const std::string& vehicleModel - model of the vehicle
Return type: void
*/
void Controller::purchaseService(const util::Vector<std::string>& serviceIDs, const std::string& vehicleNumber, const std::string& vehicleBrand, const std::string& vehicleModel) void Controller::purchaseService(const util::Vector<std::string>& serviceIDs, const std::string& vehicleNumber, const std::string& vehicleBrand, const std::string& vehicleModel)
{ {
m_serviceManagementService.purchaseService(serviceIDs, vehicleNumber, vehicleBrand, vehicleModel); m_serviceManagementService.purchaseService(serviceIDs, vehicleNumber, vehicleBrand, vehicleModel);
} }
/*
Function: purchaseComboPackage
Description: Purchases a combo package for a vehicle by delegating to the service management service.
Parameter: const std::string& comboPackageID - ID of the combo package
const std::string& vehicleNumber - vehicle registration number
const std::string& vehicleBrand - brand of the vehicle
const std::string& vehicleModel - model of the vehicle
Return type: void
*/
void Controller::purchaseComboPackage(const std::string& comboPackageID, const std::string& vehicleNumber, const std::string& vehicleBrand, const std::string& vehicleModel) void Controller::purchaseComboPackage(const std::string& comboPackageID, const std::string& vehicleNumber, const std::string& vehicleBrand, const std::string& vehicleModel)
{ {
m_serviceManagementService.purchaseComboPackage(comboPackageID, vehicleNumber, vehicleBrand, vehicleModel); m_serviceManagementService.purchaseComboPackage(comboPackageID, vehicleNumber, vehicleBrand, vehicleModel);
@@ -188,12 +141,12 @@ Return type: util::Map<std::string, const InventoryItem*>
*/ */
util::Map<std::string, const InventoryItem*> Controller::getInventoryItems() util::Map<std::string, const InventoryItem*> Controller::getInventoryItems()
{ {
auto inventoryItems = m_inventoryManagementService.getInventoryItems(); auto inventoryIems = m_inventoryManagementService.getInventoryItems();
util::Map<std::string, const InventoryItem*> readOnlyInventoryItems; util::Map<std::string, const InventoryItem*> readOnlyInventoryItems;
int inventoryItemsMapSize = inventoryItems.getSize(); int inventoryItemsMapSize = inventoryIems.getSize();
for (int index = 0; index < inventoryItemsMapSize; index++) for (int index = 0; index < inventoryItemsMapSize; index++)
{ {
readOnlyInventoryItems.insert(inventoryItems.getKeyAt(index), inventoryItems.getValueAt(index)); readOnlyInventoryItems.insert(inventoryIems.getKeyAt(index), inventoryIems.getValueAt(index));
} }
return readOnlyInventoryItems; return readOnlyInventoryItems;
} }
@@ -245,14 +198,6 @@ void Controller::addInventoryItemStock(const std::string& selectedItemId, int qu
m_inventoryManagementService.addInventoryItemStock(selectedItemId, quantity); m_inventoryManagementService.addInventoryItemStock(selectedItemId, quantity);
} }
/*
Function: getServiceBookings
Description: Retrieves all service bookings in read-only form.
Parameters:
- None
Returns:
- util::Map<std::string, const ServiceBooking*> containing service bookings
*/
util::Map<std::string, const ServiceBooking*> Controller::getServiceBookings() util::Map<std::string, const ServiceBooking*> Controller::getServiceBookings()
{ {
auto serviceBookings = m_serviceManagementService.getServiceBookings(); auto serviceBookings = m_serviceManagementService.getServiceBookings();
@@ -264,14 +209,6 @@ util::Map<std::string, const ServiceBooking*> Controller::getServiceBookings()
return readOnlyServiceBookings; return readOnlyServiceBookings;
} }
/*
Function: getServiceBookingsByUser
Description: Retrieves all service bookings for a specific user.
Parameters:
- userID: std::string, the user ID
Returns:
- util::Map<std::string, const ServiceBooking*> containing bookings for the user
*/
util::Map<std::string, const ServiceBooking*> Controller::getServiceBookingsByUser(const std::string userID) util::Map<std::string, const ServiceBooking*> Controller::getServiceBookingsByUser(const std::string userID)
{ {
util::Map<std::string, const ServiceBooking*> readOnlyServiceBookingsByUserMap; util::Map<std::string, const ServiceBooking*> readOnlyServiceBookingsByUserMap;
@@ -301,14 +238,6 @@ util::Map<std::string, const User*> Controller::getUsers()
return readOnlyUserList; return readOnlyUserList;
} }
/*
Function: getUsers
Description: Retrieves users filtered by user type.
Parameters:
- userType: util::UserType, type of user (CUSTOMER, TECHNICIAN, ADMIN)
Returns:
- util::Map<std::string, const User*> containing users of the specified type
*/
util::Map<std::string, const User*> Controller::getUsers(util::UserType userType) util::Map<std::string, const User*> Controller::getUsers(util::UserType userType)
{ {
auto userMap = m_userManagementService.getUsers(userType); auto userMap = m_userManagementService.getUsers(userType);
@@ -320,57 +249,21 @@ util::Map<std::string, const User*> Controller::getUsers(util::UserType userType
return readOnlyUserMap; return readOnlyUserMap;
} }
/*
Function: createJobCard
Description: Creates a job card for a service booking assigned to a technician.
Parameters:
- bookingID: std::string, ID of the service booking
- technicianID: std::string, ID of the technician
- serviceID: std::string, ID of the service
Returns:
- void
*/
void Controller::createJobCard(const std::string& bookingID, const std::string& technicianID, const std::string& serviceID) void Controller::createJobCard(const std::string& bookingID, const std::string& technicianID, const std::string& serviceID)
{ {
m_serviceManagementService.createJobCard(bookingID, technicianID, serviceID); m_serviceManagementService.createJobCard(bookingID, technicianID, serviceID);
} }
/*
Function: createService
Description: Creates a new service with associated inventory items and labor cost.
Parameters:
- name: std::string, name of the service
- inventoryItemIDs: Vector of inventory item IDs
- laborCost: double, labor cost
Returns:
- void
*/
void Controller::createService(const std::string& name, const util::Vector<std::string>& inventoryItemIDs, double laborCost) void Controller::createService(const std::string& name, const util::Vector<std::string>& inventoryItemIDs, double laborCost)
{ {
m_serviceManagementService.createService(name, inventoryItemIDs, laborCost); m_serviceManagementService.createService(name, inventoryItemIDs, laborCost);
} }
/*
Function: removeService
Description: Removes a service from the system by ID.
Parameters:
- serviceID: std::string, ID of the service
Returns:
- void
*/
void Controller::removeService(const std::string& serviceID) void Controller::removeService(const std::string& serviceID)
{ {
m_serviceManagementService.removeService(serviceID); m_serviceManagementService.removeService(serviceID);
} }
/*
Function: getJobCardsByUser
Description: Retrieves job cards assigned to the authenticated technician.
Parameters:
- None
Returns:
- util::Map<std::string, const JobCard*> containing job cards
*/
util::Map<std::string, const JobCard*> Controller::getJobCardsByUser() util::Map<std::string, const JobCard*> Controller::getJobCardsByUser()
{ {
const User* currentUser = getAuthenticatedUser(); const User* currentUser = getAuthenticatedUser();
@@ -384,14 +277,6 @@ util::Map<std::string, const JobCard*> Controller::getJobCardsByUser()
return readOnlyJobCardMap; return readOnlyJobCardMap;
} }
/*
Function: completeJob
Description: Marks a job card as completed.
Parameters:
- jobID: std::string, ID of the job card
Returns:
- void
*/
void Controller::completeJob(const std::string& jobID) void Controller::completeJob(const std::string& jobID)
{ {
m_serviceManagementService.completeJob(jobID); m_serviceManagementService.completeJob(jobID);
@@ -409,8 +294,10 @@ void Controller::removeUser(const std::string& userID)
User* user = m_userManagementService.getUser(userID); User* user = m_userManagementService.getUser(userID);
if (!user) if (!user)
{ {
throw std::runtime_error("Error: User not Found.\n"); throw std::runtime_error("Error User not Found.\n");
} }
m_serviceManagementService.cancelCustomerServiceBookings(userID);
m_serviceManagementService.cancelTechnicianJobs(userID);
m_userManagementService.removeUser(userID); m_userManagementService.removeUser(userID);
} }
@@ -440,15 +327,6 @@ void Controller::removeComboPackage(const std::string& comboPackageID)
m_serviceManagementService.removeComboPackage(comboPackageID); m_serviceManagementService.removeComboPackage(comboPackageID);
} }
/*
Function: getInvoicesByUser
Description: Retrieves all invoices associated with the currently authenticated user.
Converts them into a read-only map before returning.
Parameters:
- None
Returns:
- util::Map<std::string, const Invoice*> containing the users invoices
*/
util::Map<std::string, const Invoice*> Controller::getInvoicesByUser() util::Map<std::string, const Invoice*> Controller::getInvoicesByUser()
{ {
User* currentUser = m_authenticationManagementService.getAuthenticatedUser(); User* currentUser = m_authenticationManagementService.getAuthenticatedUser();
@@ -462,15 +340,6 @@ util::Map<std::string, const Invoice*> Controller::getInvoicesByUser()
return userInvoicesReadOnly; return userInvoicesReadOnly;
} }
/*
Function: completePayment
Description: Completes payment for a specific invoice using the given payment mode.
Parameters:
- invoiceID: std::string, ID of the invoice to be paid
- paymentMode: util::PaymentMode, mode of payment (e.g., ONLINE, OFFLINE)
Returns:
- void
*/
void Controller::completePayment(const std::string& invoiceID, util::PaymentMode paymentMode) void Controller::completePayment(const std::string& invoiceID, util::PaymentMode paymentMode)
{ {
m_paymentManagementService.completePayment(invoiceID, paymentMode); m_paymentManagementService.completePayment(invoiceID, paymentMode);
@@ -554,16 +423,6 @@ void Controller::configureNotifications(bool paymentNotifications, bool serviceN
} }
} }
/*
Function: loadSystemData
Description: Loads all system data from persistent storage into memory.
Invokes the respective management services to load users, inventory items, services,
combo packages, service bookings, job cards, invoices, and observers.
Parameters:
- None
Returns:
- void
*/
void Controller::loadSystemData() void Controller::loadSystemData()
{ {
m_userManagementService.loadUsers(); m_userManagementService.loadUsers();
@@ -578,16 +437,6 @@ void Controller::loadSystemData()
m_inventoryManagementService.loadObservers(); m_inventoryManagementService.loadObservers();
} }
/*
Function: saveSystemData
Description: Saves all system data from memory back to persistent storage.
Invokes the respective management services to save users, inventory items, services,
combo packages, service bookings, job cards, invoices, and observers.
Parameters:
- None
Returns:
- void
*/
void Controller::saveSystemData() void Controller::saveSystemData()
{ {
m_userManagementService.saveUsers(); m_userManagementService.saveUsers();
@@ -604,8 +453,9 @@ void Controller::saveSystemData()
/* /*
Function: runSystemChecks Function: runSystemChecks
Description: Runs system checks to ensure critical configurations, such as verifying admin existence. Description: Executes system checks including sending low stock alerts
Parameter: None and payment reminders.
Parameters: None
Return type: void Return type: void
*/ */
void Controller::runSystemChecks() void Controller::runSystemChecks()
@@ -6,7 +6,6 @@ Description: Header file declaring the Controller class, which manages
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#pragma once #pragma once
#include <string> #include <string>
#include "AuthenticationManagementService.h" #include "AuthenticationManagementService.h"
@@ -29,9 +28,9 @@ class Notification;
class Controller class Controller
{ {
private: private:
AuthenticationManagementService m_authenticationManagementService; AuthenticationManagementService m_authenticationManagementService;
UserManagementService m_userManagementService; UserManagementService m_userManagementService;
ServiceManagementService m_serviceManagementService; ServiceManagementService m_serviceManagementService;
InventoryManagementService m_inventoryManagementService; InventoryManagementService m_inventoryManagementService;
PaymentManagementService m_paymentManagementService; PaymentManagementService m_paymentManagementService;
public: public:
@@ -40,7 +39,7 @@ public:
void changePassword(const std::string& newPassword); void changePassword(const std::string& newPassword);
void createCustomer(const std::string& username, const std::string& name, const std::string& password, const std::string& email, const std::string& phone); void createCustomer(const std::string& username, const std::string& name, const std::string& password, const std::string& email, const std::string& phone);
const User* getAuthenticatedUser(); const User* getAuthenticatedUser();
void createTechnician(const std::string& username, const std::string& name, const std::string& password, const std::string& email, const std::string& phone); void createTechnician(const std::string& username, const std::string& name, const std::string& password, const std::string& email, const std::string& phoneNumber);
void updateUserDetails(const std::string& email, const std::string& phone); void updateUserDetails(const std::string& email, const std::string& phone);
util::Map<std::string, const Service*> getServices(); util::Map<std::string, const Service*> getServices();
util::Map<std::string, const ComboPackage*> getComboPackages(); util::Map<std::string, const ComboPackage*> getComboPackages();
@@ -0,0 +1 @@
Place files here.
@@ -56,19 +56,6 @@ ComboPackage::ComboPackage(const std::string& packageName, double discountPercen
} }
} }
/*
Function: ComboPackage (parameterized constructor with ID)
Description: Initializes a combo package with an existing ID, name, discount percentage,
service IDs, and state. Updates UID tracking based on ID.
Parameters:
- id: const std::string&, unique ID of the package
- packageName: const std::string&, name of the package
- discountPercentage: double, discount percentage applied
- serviceIDs: const util::Vector<std::string>&, IDs of services included
- status: util::State, state of the package (ACTIVE/INACTIVE)
Returns:
- A new ComboPackage object
*/
ComboPackage::ComboPackage(const std::string& id, const std::string& packageName, double discountPercentage, const util::Vector<std::string>& serviceIDs, util::State status) ComboPackage::ComboPackage(const std::string& id, const std::string& packageName, double discountPercentage, const util::Vector<std::string>& serviceIDs, util::State status)
: m_id(id), : m_id(id),
m_packageName(packageName), m_packageName(packageName),
@@ -225,14 +212,6 @@ void ComboPackage::setState(util::State status)
m_status = status; m_status = status;
} }
/*
Function: getServiceIDsAsString (static helper)
Description: Converts a vector of service IDs into a single string separated by '|'.
Parameters:
- serviceIDs: const util::Vector<std::string>&, vector of service IDs
Returns:
- std::string: Concatenated service IDs string
*/
static std::string getServiceIDsAsString(const util::Vector<std::string>& serviceIDs) static std::string getServiceIDsAsString(const util::Vector<std::string>& serviceIDs)
{ {
int numberOfServices = serviceIDs.getSize(); int numberOfServices = serviceIDs.getSize();
@@ -248,14 +227,6 @@ static std::string getServiceIDsAsString(const util::Vector<std::string>& servic
return serviceIDsString; return serviceIDsString;
} }
/*
Function: getServiceIDsAsVector (static helper)
Description: Converts a string of service IDs separated by '|' into a vector.
Parameters:
- serviceIDsString: const std::string&, concatenated service IDs string
Returns:
- util::Vector<std::string>: Vector of service IDs
*/
static util::Vector<std::string> getServiceIDsAsVector(const std::string& serviceIDsString) static util::Vector<std::string> getServiceIDsAsVector(const std::string& serviceIDsString)
{ {
util::Vector<std::string> serviceIDs; util::Vector<std::string> serviceIDs;
@@ -268,14 +239,6 @@ static util::Vector<std::string> getServiceIDsAsVector(const std::string& servic
return serviceIDs; return serviceIDs;
} }
/*
Function: serialize
Description: Serializes the combo package into a CSV-formatted string.
Parameters:
- None
Returns:
- std::string: Serialized combo package record
*/
std::string ComboPackage::serialize() const std::string ComboPackage::serialize() const
{ {
std::ostringstream serializedComboPackage; std::ostringstream serializedComboPackage;
@@ -287,16 +250,6 @@ std::string ComboPackage::serialize() const
return serializedComboPackage.str(); return serializedComboPackage.str();
} }
/*
Function: deserialize
Description: Deserializes a CSV-formatted string into a ComboPackage object.
Parameters:
- record: const std::string&, serialized combo package record
Returns:
- ComboPackage*: Pointer to the deserialized ComboPackage object
Throws:
- std::runtime_error if data is invalid
*/
ComboPackage* ComboPackage::deserialize(const std::string& record) ComboPackage* ComboPackage::deserialize(const std::string& record)
{ {
std::string id, packageName; std::string id, packageName;
@@ -327,14 +280,6 @@ ComboPackage* ComboPackage::deserialize(const std::string& record)
); );
} }
/*
Function: getHeaders
Description: Retrieves the CSV headers for combo package serialization.
Parameters:
- None
Returns:
- std::string: Header string ("ID,PackageName,DiscountPercentage,ServiceIDs,Status")
*/
std::string ComboPackage::getHeaders() std::string ComboPackage::getHeaders()
{ {
return "ID,PackageName,DiscountPercentage,ServiceIDs,Status"; return "ID,PackageName,DiscountPercentage,ServiceIDs,Status";
@@ -8,9 +8,9 @@ Date: 19-May-2026
#include <sstream> #include <sstream>
#include <stdexcept> #include <stdexcept>
#include "InventoryItem.h"
#include "Factory.h" #include "Factory.h"
#include "StringHelper.h" #include "StringHelper.h"
#include "InventoryItem.h"
int InventoryItem::m_uid = 0; int InventoryItem::m_uid = 0;
@@ -47,19 +47,6 @@ InventoryItem::InventoryItem(const std::string& partName, int quantity, double p
m_status(util::State::ACTIVE), m_status(util::State::ACTIVE),
m_price(price) {} m_price(price) {}
/*
Function: InventoryItem (parameterized constructor with ID)
Description: Initializes an inventory item with an existing ID, part name, quantity,
price, and state. Updates UID tracking based on ID.
Parameters:
- id: const std::string&, unique ID of the item
- partName: const std::string&, name of the part
- quantity: int, quantity of the part
- price: double, price of the part
- status: util::State, state of the item (ACTIVE/INACTIVE)
Returns:
- A new InventoryItem object
*/
InventoryItem::InventoryItem(const std::string& id, const std::string& partName, int quantity, double price, util::State status) InventoryItem::InventoryItem(const std::string& id, const std::string& partName, int quantity, double price, util::State status)
: m_id(id), : m_id(id),
m_partName(partName), m_partName(partName),
@@ -204,14 +191,6 @@ void InventoryItem::setState(util::State status)
m_status = status; m_status = status;
} }
/*
Function: serialize
Description: Serializes the inventory item into a CSV-formatted string.
Parameters:
- None
Returns:
- std::string: Serialized inventory item record
*/
std::string InventoryItem::serialize() const std::string InventoryItem::serialize() const
{ {
std::ostringstream serializedInventoryItem; std::ostringstream serializedInventoryItem;
@@ -223,16 +202,6 @@ std::string InventoryItem::serialize() const
return serializedInventoryItem.str(); return serializedInventoryItem.str();
} }
/*
Function: deserialize
Description: Deserializes a CSV-formatted string into an InventoryItem object.
Parameters:
- record: const std::string&, serialized inventory item record
Returns:
- InventoryItem*: Pointer to the deserialized InventoryItem object
Throws:
- std::runtime_error if data is invalid
*/
InventoryItem* InventoryItem::deserialize(const std::string& record) InventoryItem* InventoryItem::deserialize(const std::string& record)
{ {
std::string id, partName; std::string id, partName;
@@ -264,15 +233,7 @@ InventoryItem* InventoryItem::deserialize(const std::string& record)
); );
} }
/*
Function: getHeaders
Description: Retrieves the CSV headers for inventory item serialization.
Parameters:
- None
Returns:
- std::string: Header string ("ID,PartName,Quantity,Price,Status")
*/
std::string InventoryItem::getHeaders() std::string InventoryItem::getHeaders()
{ {
return "ID,PartName,Quantity,Price,Status"; return "ID,PartName,Quantity,Price,Status";
} }
@@ -59,7 +59,8 @@ Invoice::Invoice(
ServiceBooking* booking, ServiceBooking* booking,
const util::Timestamp& invoiceDate, const util::Timestamp& invoiceDate,
double laborCost, double laborCost,
const util::Map<std::string, InventoryItem*>& parts, const util::Map<std::string,
InventoryItem*>& parts,
double partsCost, double partsCost,
double discountPercentage, double discountPercentage,
double totalAmount, double totalAmount,
@@ -87,6 +88,7 @@ Invoice::Invoice(
m_partIDs.push_back(partPointers[index]->getId()); m_partIDs.push_back(partPointers[index]->getId());
} }
} }
Invoice::Invoice( Invoice::Invoice(
const std::string& id, const std::string& id,
const std::string& bookingId, const std::string& bookingId,
@@ -120,12 +122,6 @@ Invoice::Invoice(
} }
} }
/*
Function: getId
Description: Retrieves the unique ID of the invoice.
Returns:
- const std::string& representing the invoice ID.
*/
const std::string& Invoice::getId() const const std::string& Invoice::getId() const
{ {
return m_id; return m_id;
@@ -175,14 +171,6 @@ double Invoice::getLaborCost() const
return m_laborCost; return m_laborCost;
} }
/*
Function: getPartIDs
Description: Retrieves the IDs of parts used in the invoice.
Parameters:
- None
Returns:
- const util::Vector<std::string>&: Part IDs
*/
const util::Vector<std::string>& Invoice::getPartIDs() const const util::Vector<std::string>& Invoice::getPartIDs() const
{ {
return m_partIDs; return m_partIDs;
@@ -192,7 +180,7 @@ const util::Vector<std::string>& Invoice::getPartIDs() const
Function: getParts Function: getParts
Description: Retrieves the map of inventory items used in the service. Description: Retrieves the map of inventory items used in the service.
Returns: Returns:
- const util::Map<int, InventoryItem*>& representing the parts. - const util::Map<std::string, InventoryItem*>& representing the parts.
*/ */
const util::Map<std::string, InventoryItem*>& Invoice::getParts() const const util::Map<std::string, InventoryItem*>& Invoice::getParts() const
{ {
@@ -428,14 +416,6 @@ void Invoice::setStatus(util::PaymentStatus status)
m_status = status; m_status = status;
} }
/*
Function: getPartIDsAsString (static helper)
Description: Converts a vector of part IDs into a single string separated by '|'.
Parameters:
- partIDs: const util::Vector<std::string>&, vector of part IDs
Returns:
- std::string: Concatenated part IDs string
*/
static std::string getPartIDsAsString(const util::Vector<std::string>& partIDs) static std::string getPartIDsAsString(const util::Vector<std::string>& partIDs)
{ {
int numberOfParts = partIDs.getSize(); int numberOfParts = partIDs.getSize();
@@ -451,14 +431,6 @@ static std::string getPartIDsAsString(const util::Vector<std::string>& partIDs)
return partIDsString; return partIDsString;
} }
/*
Function: getPartIDsAsVector (static helper)
Description: Converts a string of part IDs separated by '|' into a vector.
Parameters:
- partIDsString: const std::string&, concatenated part IDs string
Returns:
- util::Vector<std::string>: Vector of part IDs
*/
static util::Vector<std::string> getPartIDsAsVector(const std::string& partIDsString) static util::Vector<std::string> getPartIDsAsVector(const std::string& partIDsString)
{ {
util::Vector<std::string> partIDs; util::Vector<std::string> partIDs;
@@ -471,14 +443,6 @@ static util::Vector<std::string> getPartIDsAsVector(const std::string& partIDsSt
return partIDs; return partIDs;
} }
/*
Function: serialize
Description: Serializes the invoice into a CSV-formatted string.
Parameters:
- None
Returns:
- std::string: Serialized invoice record
*/
std::string Invoice::serialize() const std::string Invoice::serialize() const
{ {
std::ostringstream serializedInvoice; std::ostringstream serializedInvoice;
@@ -496,16 +460,6 @@ std::string Invoice::serialize() const
return serializedInvoice.str(); return serializedInvoice.str();
} }
/*
Function: deserialize
Description: Deserializes a CSV-formatted string into an Invoice object.
Parameters:
- record: const std::string&, serialized invoice record
Returns:
- Invoice*: Pointer to the deserialized Invoice object
Throws:
- std::runtime_error if data is invalid
*/
Invoice* Invoice::deserialize(const std::string& record) Invoice* Invoice::deserialize(const std::string& record)
{ {
std::string id, bookingId; std::string id, bookingId;
@@ -558,15 +512,7 @@ Invoice* Invoice::deserialize(const std::string& record)
); );
} }
/*
Function: getHeaders
Description: Retrieves the CSV headers for invoice serialization.
Parameters:
- None
Returns:
- std::string: Header string ("ID,BookingID,InvoiceDate,LaborCost,PartIDs,PartsCost,DiscountPercentage,TotalAmount,PaymentDate,PaymentMethod,Status")
*/
std::string Invoice::getHeaders() std::string Invoice::getHeaders()
{ {
return "ID,BookingID,InvoiceDate,LaborCost,PartIDs,PartsCost,DiscountPercentage,TotalAmount,PaymentDate,PaymentMethod,Status"; return "ID,BookingID,InvoiceDate,LaborCost,PartIDs,PartsCost,DiscountPercentage,TotalAmount,PaymentDate,PaymentMethod,Status";
} }
@@ -6,7 +6,6 @@ Description: Implementation file containing the method definitions of the
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#include <sstream> #include <sstream>
#include <stdexcept> #include <stdexcept>
#include "JobCard.h" #include "JobCard.h"
@@ -18,10 +17,12 @@ int JobCard::m_uid = 0;
/* /*
Function: JobCard Function: JobCard
Description: Default constructor that initializes a new job card with Description: Default constructor that initializes a new job card with a unique ID,
a unique ID and default values. null booking, null service, null technician, and default job status.
Parameter: None Parameters:
Return type: Constructor - None
Returns:
- A new JobCard object.
*/ */
JobCard::JobCard() JobCard::JobCard()
: m_id("JC" + std::to_string(++m_uid)), : m_id("JC" + std::to_string(++m_uid)),
@@ -32,19 +33,18 @@ JobCard::JobCard()
/* /*
Function: JobCard Function: JobCard
Description: Parameterized constructor that initializes a new job card with a unique ID and specified details. Description: Parameterized constructor that initializes a job card with
Parameters: booking, service, technician, and status details.
- bookingId: ID of the associated service booking. Parameter: const std::string& bookingId - ID of the booking
- booking: Pointer to the ServiceBooking object. ServiceBooking* booking - pointer to the booking object
- service: Pointer to the Service object. Service* service - pointer to the service object
- serviceId: ID of the associated service. const std::string& serviceId - ID of the service
- technicianId: ID of the assigned technician. const std::string& technicianId - ID of the technician
- technician: Pointer to the User object representing the technician. User* technician - pointer to the technician object
- assignedDate: Timestamp of when the job was assigned. const util::Timestamp& assignedDate - date when job was assigned
- status: Current status of the job (STARTED/COMPLETED). util::ServiceJobStatus status - current status of the job
- completionDate: Timestamp of when the job was completed. const util::Timestamp& completionDate - date when job was completed
Returns: Return type: Constructor
- A new JobCard object.
*/ */
JobCard::JobCard(const std::string& bookingId, JobCard::JobCard(const std::string& bookingId,
ServiceBooking* booking, ServiceBooking* booking,
@@ -67,22 +67,6 @@ JobCard::JobCard(const std::string& bookingId,
m_status(status), m_status(status),
m_completionDate(completionDate) {} m_completionDate(completionDate) {}
/*
Function: JobCard (parameterized constructor with ID)
Description: Initializes a job card with an existing ID, booking ID, service ID,
technician ID, assignment date, completion date, and status.
Updates UID tracking based on ID.
Parameters:
- id: const std::string&, unique job card ID
- bookingId: const std::string&, ID of the booking
- serviceId: const std::string&, ID of the service
- technicianId: const std::string&, ID of the technician
- assignedDate: const util::Timestamp&, date of assignment
- status: util::ServiceJobStatus, job status
- completionDate: const util::Timestamp&, date of completion
Returns:
- A new JobCard object
*/
JobCard::JobCard(const std::string& id, JobCard::JobCard(const std::string& id,
const std::string& bookingId, const std::string& bookingId,
const std::string& serviceId, const std::string& serviceId,
@@ -199,9 +183,9 @@ const util::Timestamp& JobCard::getAssignedDate() const
/* /*
Function: getStatus Function: getStatus
Description: Retrieves the current status of the job. Description: Retrieves the current status of the job card.
Returns: Parameter: None
- ServiceJobStatus representing the job status. Return type: util::ServiceJobStatus
*/ */
util::ServiceJobStatus JobCard::getStatus() const util::ServiceJobStatus JobCard::getStatus() const
{ {
@@ -325,11 +309,9 @@ void JobCard::setAssignedDate(const util::Timestamp& assignedDate)
/* /*
Function: setStatus Function: setStatus
Description: Sets the current status of the job. Description: Sets the status of the job card.
Parameters: Parameter: util::ServiceJobStatus status - new job status
- status: New job status value. Return type: void
Returns:
- void
*/ */
void JobCard::setStatus(util::ServiceJobStatus status) void JobCard::setStatus(util::ServiceJobStatus status)
{ {
@@ -349,14 +331,6 @@ void JobCard::setCompletionDate(const util::Timestamp& completionDate)
m_completionDate = completionDate; m_completionDate = completionDate;
} }
/*
Function: serialize
Description: Serializes the job card into a CSV-formatted string.
Parameters:
- None
Returns:
- std::string: Serialized job card record
*/
std::string JobCard::serialize() const std::string JobCard::serialize() const
{ {
std::ostringstream serializedJobCard; std::ostringstream serializedJobCard;
@@ -370,16 +344,6 @@ std::string JobCard::serialize() const
return serializedJobCard.str(); return serializedJobCard.str();
} }
/*
Function: deserialize
Description: Deserializes a CSV-formatted string into a JobCard object.
Parameters:
- record: const std::string&, serialized job card record
Returns:
- JobCard*: Pointer to the deserialized JobCard object
Throws:
- std::runtime_error if timestamp parsing fails
*/
JobCard* JobCard::deserialize(const std::string& record) JobCard* JobCard::deserialize(const std::string& record)
{ {
std::string id, bookingId, serviceId, technicianId; std::string id, bookingId, serviceId, technicianId;
@@ -415,14 +379,6 @@ JobCard* JobCard::deserialize(const std::string& record)
); );
} }
/*
Function: getHeaders
Description: Retrieves the CSV headers for job card serialization.
Parameters:
- None
Returns:
- std::string: Header string ("ID,BookingID,ServiceID,TechnicianID,AssignedDate,Status,CompletionDate")
*/
std::string JobCard::getHeaders() std::string JobCard::getHeaders()
{ {
return "ID,BookingID,ServiceID,TechnicianID,AssignedDate,Status,CompletionDate"; return "ID,BookingID,ServiceID,TechnicianID,AssignedDate,Status,CompletionDate";
@@ -6,11 +6,11 @@ Description: Header file declaring the JobCard class, which represents
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#pragma once #pragma once
#include <string> #include <string>
#include "Enums.h" #include "Enums.h"
#include "Timestamp.h" #include "Timestamp.h"
#include "Enums.h"
class ServiceBooking; class ServiceBooking;
class Service; class Service;
@@ -45,19 +45,6 @@ Notification::Notification(const std::string& recipientUserId, User* recipient,
m_message(message), m_message(message),
m_createdAt(createdAt) {} m_createdAt(createdAt) {}
/*
Function: Notification (parameterized constructor with ID)
Description: Initializes a notification with an existing ID, recipient details,
title, message, and creation timestamp. Updates UID tracking based on ID.
Parameters:
- id: const std::string&, unique notification ID
- recipientUserId: const std::string&, ID of the recipient user
- title: const std::string&, notification title
- message: const std::string&, notification message
- createdAt: const util::Timestamp&, timestamp of creation
Returns:
- A new Notification object
*/
Notification::Notification(const std::string& id, const std::string& recipientUserId, const std::string& title, const std::string& message, const util::Timestamp& createdAt) Notification::Notification(const std::string& id, const std::string& recipientUserId, const std::string& title, const std::string& message, const util::Timestamp& createdAt)
: m_id(id), : m_id(id),
m_recipientUserId(recipientUserId), m_recipientUserId(recipientUserId),
@@ -217,14 +204,6 @@ void Notification::setCreatedAt(const util::Timestamp& createdAt)
m_createdAt = createdAt; m_createdAt = createdAt;
} }
/*
Function: serialize
Description: Serializes the notification into a CSV-formatted string.
Parameters:
- None
Returns:
- std::string: Serialized notification record
*/
std::string Notification::serialize() const std::string Notification::serialize() const
{ {
std::ostringstream serializedNotification; std::ostringstream serializedNotification;
@@ -236,16 +215,6 @@ std::string Notification::serialize() const
return serializedNotification.str(); return serializedNotification.str();
} }
/*
Function: deserialize
Description: Deserializes a CSV-formatted string into a Notification object.
Parameters:
- record: const std::string&, serialized notification record
Returns:
- Notification*: Pointer to the deserialized Notification object
Throws:
- std::runtime_error if timestamp parsing fails
*/
Notification* Notification::deserialize(const std::string& record) Notification* Notification::deserialize(const std::string& record)
{ {
std::string id, recipientUserId, title, message, createdAtTimestampString; std::string id, recipientUserId, title, message, createdAtTimestampString;
@@ -273,14 +242,6 @@ Notification* Notification::deserialize(const std::string& record)
); );
} }
/*
Function: getHeaders
Description: Retrieves the CSV headers for notification serialization.
Parameters:
- None
Returns:
- std::string: Header string ("ID,RecipientID,Title,Message,Timestamp")
*/
std::string Notification::getHeaders() std::string Notification::getHeaders()
{ {
return "ID,RecipientID,Title,Message,Timestamp"; return "ID,RecipientID,Title,Message,Timestamp";
@@ -54,19 +54,6 @@ Service::Service(const std::string& name, const util::Map<std::string, Inventory
} }
} }
/*
Function: Service (parameterized constructor with ID)
Description: Initializes a service with an existing ID, name, inventory item IDs,
labor cost, and state. Updates UID tracking based on ID.
Parameters:
- id: const std::string&, unique service ID
- name: const std::string&, name of the service
- requiredInventoryItemIDs: const util::Vector<std::string>&, IDs of required inventory items
- laborCost: double, labor cost of the service
- status: util::State, state of the service (ACTIVE/INACTIVE)
Returns:
- A new Service object
*/
Service::Service(const std::string& id, const std::string& name, const util::Vector<std::string>& requiredInventoryItemIDs, double laborCost, util::State status) Service::Service(const std::string& id, const std::string& name, const util::Vector<std::string>& requiredInventoryItemIDs, double laborCost, util::State status)
: m_id(id), : m_id(id),
m_name(name), m_name(name),
@@ -103,14 +90,6 @@ const std::string& Service::getName() const
return m_name; return m_name;
} }
/*
Function: getRequiredInventoryItemIDs
Description: Retrieves the IDs of required inventory items for the service.
Parameters:
- None
Returns:
- const util::Vector<std::string>&: Inventory item IDs
*/
const util::Vector<std::string>& Service::getRequiredInventoryItemIDs() const const util::Vector<std::string>& Service::getRequiredInventoryItemIDs() const
{ {
return m_requiredInventoryItemIDs; return m_requiredInventoryItemIDs;
@@ -221,14 +200,6 @@ void Service::setState(util::State status)
m_status = status; m_status = status;
} }
/*
Function: getInventoryItemIDsAsString (static helper)
Description: Converts a vector of inventory item IDs into a single string separated by '|'.
Parameters:
- inventoryItemIds: const util::Vector<std::string>&, vector of inventory item IDs
Returns:
- std::string: Concatenated inventory item IDs string
*/
static std::string getInventoryItemIDsAsString(const util::Vector<std::string>& inventoryItemIds) static std::string getInventoryItemIDsAsString(const util::Vector<std::string>& inventoryItemIds)
{ {
int numberOfInventoryItems = inventoryItemIds.getSize(); int numberOfInventoryItems = inventoryItemIds.getSize();
@@ -244,14 +215,6 @@ static std::string getInventoryItemIDsAsString(const util::Vector<std::string>&
return inventoryItemIDs; return inventoryItemIDs;
} }
/*
Function: getInventoryItemIDsAsVector (static helper)
Description: Converts a string of inventory item IDs separated by '|' into a vector.
Parameters:
- inventoryItemIDsString: const std::string&, concatenated inventory item IDs string
Returns:
- util::Vector<std::string>: Vector of inventory item IDs
*/
static util::Vector<std::string> getInventoryItemIDsAsVector(const std::string& inventoryItemIDsString) static util::Vector<std::string> getInventoryItemIDsAsVector(const std::string& inventoryItemIDsString)
{ {
util::Vector<std::string> inventoryItemIDs; util::Vector<std::string> inventoryItemIDs;
@@ -264,14 +227,6 @@ static util::Vector<std::string> getInventoryItemIDsAsVector(const std::string&
return inventoryItemIDs; return inventoryItemIDs;
} }
/*
Function: serialize
Description: Serializes the service into a CSV-formatted string.
Parameters:
- None
Returns:
- std::string: Serialized service record
*/
std::string Service::serialize() const std::string Service::serialize() const
{ {
std::ostringstream serializedService; std::ostringstream serializedService;
@@ -283,16 +238,6 @@ std::string Service::serialize() const
return serializedService.str(); return serializedService.str();
} }
/*
Function: deserialize
Description: Deserializes a CSV-formatted string into a Service object.
Parameters:
- record: const std::string&, serialized service record
Returns:
- Service*: Pointer to the deserialized Service object
Throws:
- std::runtime_error if labor cost parsing fails
*/
Service* Service::deserialize(const std::string& record) Service* Service::deserialize(const std::string& record)
{ {
std::string id, name; std::string id, name;
@@ -323,14 +268,6 @@ Service* Service::deserialize(const std::string& record)
); );
} }
/*
Function: getHeaders
Description: Retrieves the CSV headers for service serialization.
Parameters:
- None
Returns:
- std::string: Header string ("ID,Name,InventoryIDs,LaborCost,Status")
*/
std::string Service::getHeaders() std::string Service::getHeaders()
{ {
return "ID,Name,InventoryIDs,LaborCost,Status"; return "ID,Name,InventoryIDs,LaborCost,Status";
@@ -20,31 +20,31 @@ int ServiceBooking::m_uid = 0;
Function: ServiceBooking Function: ServiceBooking
Description: Default constructor that initializes a new service booking with a unique ID, Description: Default constructor that initializes a new service booking with a unique ID,
null customer, and zero discount percentage. null customer, and zero discount percentage.
Parameters: None Parameters:
Returns: A new ServiceBooking object. - None
Returns:
- A new ServiceBooking object.
*/ */
ServiceBooking::ServiceBooking() ServiceBooking::ServiceBooking()
: m_id("SBK" + std::to_string(++m_uid)), : m_id("SRV" + std::to_string(++m_uid)),
m_customer(nullptr), m_customer(nullptr),
m_assignedTechnician(nullptr), m_assignedTechnician(nullptr),
m_status(util::ServiceJobStatus::PENDING),
m_discountPercentage(0.0) {} m_discountPercentage(0.0) {}
/* /*
Function: ServiceBooking Function: ServiceBooking
Description: Parameterized constructor that initializes a new service booking with a unique ID and specified details. Description: Parameterized constructor that initializes a service booking
Parameters: with customer, vehicle, technician, and discount details.
- id: Booking ID string. Parameter: const std::string& id - booking ID
- status: Current status of the booking (e.g., PENDING, COMPLETED). util::ServiceJobStatus status - current booking status
- services: Map of services included in the booking. const util::Map<std::string, Service*>& services - map of services
- customerId: ID of the customer. const std::string& customerId - ID of the customer
- customer: Pointer to the User object representing the customer. User* customer - pointer to the customer object
- vehicleNumber: Vehicle registration number. const std::string& vehicleNumber - vehicle registration number
- vehicleBrand: Brand of the vehicle. const std::string& vehicleBrand - brand of the vehicle
- vehicleModel: Model of the vehicle. const std::string& vehicleModel - model of the vehicle
- discountPercentage: Discount applied to the booking. double discountPercentage - discount applied to the booking
Returns: Return type: Constructor
- A new ServiceBooking object.
*/ */
ServiceBooking::ServiceBooking( ServiceBooking::ServiceBooking(
util::ServiceJobStatus status, util::ServiceJobStatus status,
@@ -57,7 +57,7 @@ ServiceBooking::ServiceBooking(
const std::string& vehicleModel, const std::string& vehicleModel,
double discountPercentage double discountPercentage
) )
: m_id("SBK" + std::to_string(++m_uid)), : m_id("SRV" + std::to_string(++m_uid)),
m_status(status), m_status(status),
m_services(services), m_services(services),
m_customerId(customerId), m_customerId(customerId),
@@ -77,24 +77,6 @@ ServiceBooking::ServiceBooking(
} }
} }
/*
Function: ServiceBooking (parameterized constructor with ID)
Description: Initializes a service booking with an existing ID, status, service IDs,
customer details, vehicle details, technician ID, and discount percentage.
Updates UID tracking based on ID.
Parameters:
- id: const std::string&, unique booking ID
- status: util::ServiceJobStatus, job status of the booking
- serviceIDs: const util::Vector<std::string>&, IDs of booked services
- customerId: const std::string&, ID of the customer
- vehicleNumber: const std::string&, vehicle number
- vehicleBrand: const std::string&, vehicle brand
- vehicleModel: const std::string&, vehicle model
- assignedTechnicianId: const std::string&, ID of the assigned technician
- discountPercentage: double, discount applied
Returns:
- A new ServiceBooking object
*/
ServiceBooking::ServiceBooking( ServiceBooking::ServiceBooking(
const std::string& id, const std::string& id,
util::ServiceJobStatus status, util::ServiceJobStatus status,
@@ -125,12 +107,6 @@ ServiceBooking::ServiceBooking(
} }
} }
/*
Function: getId
Description: Retrieves the unique identifier of the service booking.
Parameter: None
Return type: const std::string&
*/
const std::string& ServiceBooking::getId() const const std::string& ServiceBooking::getId() const
{ {
return m_id; return m_id;
@@ -139,22 +115,14 @@ const std::string& ServiceBooking::getId() const
/* /*
Function: getStatus Function: getStatus
Description: Retrieves the current status of the service booking. Description: Retrieves the current status of the service booking.
Parameter: None Returns:
Return type: util::ServiceJobStatus - util::ServiceJobStatus representing the booking status.
*/ */
util::ServiceJobStatus ServiceBooking::getStatus() const util::ServiceJobStatus ServiceBooking::getStatus() const
{ {
return m_status; return m_status;
} }
/*
Function: getServiceIDs
Description: Retrieves the IDs of services booked.
Parameters:
- None
Returns:
- const util::Vector<std::string>&: Service IDs
*/
const util::Vector<std::string>& ServiceBooking::getServiceIDs() const const util::Vector<std::string>& ServiceBooking::getServiceIDs() const
{ {
return m_serviceIDs; return m_serviceIDs;
@@ -162,15 +130,9 @@ const util::Vector<std::string>& ServiceBooking::getServiceIDs() const
/* /*
Function: getServices Function: getServices
Description: Retrieves the services associated with the booking. Description: Retrieves the map of services included in the booking.
Parameter: None Returns:
Return type: const util::Map<std::string, Service*>& - const util::Map<std::string, Service*>& representing the services.
*/
/*
Function: getServices
Description: Retrieves the services associated with the booking.
Parameter: None
Return type: const util::Map<std::string, Service*>&
*/ */
const util::Map<std::string, Service*>& ServiceBooking::getServices() const const util::Map<std::string, Service*>& ServiceBooking::getServices() const
{ {
@@ -180,8 +142,8 @@ const util::Map<std::string, Service*>& ServiceBooking::getServices() const
/* /*
Function: getCustomerId Function: getCustomerId
Description: Retrieves the customer ID associated with the booking. Description: Retrieves the customer ID associated with the booking.
Parameter: None Returns:
Return type: const std::string& - const std::string& representing the customer ID.
*/ */
const std::string& ServiceBooking::getCustomerId() const const std::string& ServiceBooking::getCustomerId() const
{ {
@@ -190,9 +152,9 @@ const std::string& ServiceBooking::getCustomerId() const
/* /*
Function: getCustomer Function: getCustomer
Description: Retrieves the customer object associated with the booking. Description: Retrieves the pointer to the associated customer.
Parameter: None Returns:
Return type: User* - User* representing the customer.
*/ */
User* ServiceBooking::getCustomer() const User* ServiceBooking::getCustomer() const
{ {
@@ -201,9 +163,9 @@ User* ServiceBooking::getCustomer() const
/* /*
Function: getVehicleNumber Function: getVehicleNumber
Description: Retrieves the vehicle registration number for the booking. Description: Retrieves the vehicle registration number.
Parameter: None Returns:
Return type: const std::string& - const std::string& representing the vehicle number.
*/ */
const std::string& ServiceBooking::getVehicleNumber() const const std::string& ServiceBooking::getVehicleNumber() const
{ {
@@ -212,9 +174,9 @@ const std::string& ServiceBooking::getVehicleNumber() const
/* /*
Function: getVehicleBrand Function: getVehicleBrand
Description: Retrieves the brand of the vehicle for the booking. Description: Retrieves the brand of the vehicle.
Parameter: None Returns:
Return type: const std::string& - const std::string& representing the vehicle brand.
*/ */
const std::string& ServiceBooking::getVehicleBrand() const const std::string& ServiceBooking::getVehicleBrand() const
{ {
@@ -223,9 +185,9 @@ const std::string& ServiceBooking::getVehicleBrand() const
/* /*
Function: getVehicleModel Function: getVehicleModel
Description: Retrieves the model of the vehicle for the booking. Description: Retrieves the model of the vehicle.
Parameter: None Returns:
Return type: const std::string& - const std::string& representing the vehicle model.
*/ */
const std::string& ServiceBooking::getVehicleModel() const const std::string& ServiceBooking::getVehicleModel() const
{ {
@@ -234,9 +196,9 @@ const std::string& ServiceBooking::getVehicleModel() const
/* /*
Function: getAssignedTechnicianId Function: getAssignedTechnicianId
Description: Retrieves the ID of the technician assigned to the booking. Description: Retrieves the ID of the assigned technician.
Parameter: None Returns:
Return type: const std::string& - const std::string& representing the technician ID.
*/ */
const std::string& ServiceBooking::getAssignedTechnicianId() const const std::string& ServiceBooking::getAssignedTechnicianId() const
{ {
@@ -253,11 +215,12 @@ User* ServiceBooking::getAssignedTechnician() const
{ {
return m_assignedTechnician; return m_assignedTechnician;
} }
/* /*
Function: getDiscountPercentage Function: getDiscountPercentage
Description: Retrieves the discount percentage applied to the booking. Description: Retrieves the discount percentage applied to the booking.
Parameter: None Returns:
Return type: double - double representing the discount percentage.
*/ */
double ServiceBooking::getDiscountPercentage() const double ServiceBooking::getDiscountPercentage() const
{ {
@@ -266,9 +229,11 @@ double ServiceBooking::getDiscountPercentage() const
/* /*
Function: setId Function: setId
Description: Sets the unique identifier of the service booking. Description: Sets the unique ID of the service booking.
Parameter: const std::string& id - new booking ID Parameters:
Return type: void - id: New booking ID string.
Returns:
- void
*/ */
void ServiceBooking::setId(const std::string& id) void ServiceBooking::setId(const std::string& id)
{ {
@@ -278,8 +243,10 @@ void ServiceBooking::setId(const std::string& id)
/* /*
Function: setStatus Function: setStatus
Description: Sets the current status of the service booking. Description: Sets the current status of the service booking.
Parameter: const util::ServiceJobStatus& status - new booking status Parameters:
Return type: void - status: New booking status value.
Returns:
- void
*/ */
void ServiceBooking::setStatus(const util::ServiceJobStatus& status) void ServiceBooking::setStatus(const util::ServiceJobStatus& status)
{ {
@@ -288,9 +255,11 @@ void ServiceBooking::setStatus(const util::ServiceJobStatus& status)
/* /*
Function: setServices Function: setServices
Description: Sets the services associated with the booking. Description: Sets the services included in the booking.
Parameter: const util::Map<std::string, Service*>& services - new services map Parameters:
Return type: void - services: Map of services.
Returns:
- void
*/ */
void ServiceBooking::setServices(const util::Map<std::string, Service*>& services) void ServiceBooking::setServices(const util::Map<std::string, Service*>& services)
{ {
@@ -306,9 +275,11 @@ void ServiceBooking::setServices(const util::Map<std::string, Service*>& service
/* /*
Function: setCustomerId Function: setCustomerId
Description: Sets the customer ID for the booking. Description: Sets the customer ID associated with the booking.
Parameter: const std::string& customerId - new customer ID Parameters:
Return type: void - customerId: New customer ID string.
Returns:
- void
*/ */
void ServiceBooking::setCustomerId(const std::string& customerId) void ServiceBooking::setCustomerId(const std::string& customerId)
{ {
@@ -317,9 +288,11 @@ void ServiceBooking::setCustomerId(const std::string& customerId)
/* /*
Function: setCustomer Function: setCustomer
Description: Sets the customer object for the booking. Description: Sets the pointer to the associated customer.
Parameter: User* customer - pointer to the customer object Parameters:
Return type: void - customer: Pointer to the User object.
Returns:
- void
*/ */
void ServiceBooking::setCustomer(User* customer) void ServiceBooking::setCustomer(User* customer)
{ {
@@ -328,9 +301,11 @@ void ServiceBooking::setCustomer(User* customer)
/* /*
Function: setVehicleNumber Function: setVehicleNumber
Description: Sets the vehicle registration number for the booking. Description: Sets the vehicle registration number.
Parameter: const std::string& vehicleNumber - new vehicle number Parameters:
Return type: void - vehicleNumber: New vehicle number string.
Returns:
- void
*/ */
void ServiceBooking::setVehicleNumber(const std::string& vehicleNumber) void ServiceBooking::setVehicleNumber(const std::string& vehicleNumber)
{ {
@@ -339,9 +314,11 @@ void ServiceBooking::setVehicleNumber(const std::string& vehicleNumber)
/* /*
Function: setVehicleBrand Function: setVehicleBrand
Description: Sets the brand of the vehicle for the booking. Description: Sets the brand of the vehicle.
Parameter: const std::string& vehicleBrand - new vehicle brand Parameters:
Return type: void - vehicleBrand: New vehicle brand string.
Returns:
- void
*/ */
void ServiceBooking::setVehicleBrand(const std::string& vehicleBrand) void ServiceBooking::setVehicleBrand(const std::string& vehicleBrand)
{ {
@@ -350,9 +327,11 @@ void ServiceBooking::setVehicleBrand(const std::string& vehicleBrand)
/* /*
Function: setVehicleModel Function: setVehicleModel
Description: Sets the model of the vehicle for the booking. Description: Sets the model of the vehicle.
Parameter: const std::string& vehicleModel - new vehicle model Parameters:
Return type: void - vehicleModel: New vehicle model string.
Returns:
- void
*/ */
void ServiceBooking::setVehicleModel(const std::string& vehicleModel) void ServiceBooking::setVehicleModel(const std::string& vehicleModel)
{ {
@@ -361,9 +340,11 @@ void ServiceBooking::setVehicleModel(const std::string& vehicleModel)
/* /*
Function: setAssignedTechnicianId Function: setAssignedTechnicianId
Description: Sets the ID of the technician assigned to the booking. Description: Sets the ID of the assigned technician.
Parameter: const std::string& assignedTechnicianId - new technician ID Parameters:
Return type: void - assignedTechnicianId: New technician ID string.
Returns:
- void
*/ */
void ServiceBooking::setAssignedTechnicianId(const std::string& assignedTechnicianId) void ServiceBooking::setAssignedTechnicianId(const std::string& assignedTechnicianId)
{ {
@@ -383,23 +364,17 @@ void ServiceBooking::setAssignedTechnician(User* assignedTechnician)
/* /*
Function: setDiscountPercentage Function: setDiscountPercentage
Description: Sets the discount percentage for the booking. Description: Sets the discount percentage applied to the booking.
Parameter: double discountPercentage - new discount percentage Parameters:
Return type: void - discountPercentage: New discount percentage value.
Returns:
- void
*/ */
void ServiceBooking::setDiscountPercentage(double discountPercentage) void ServiceBooking::setDiscountPercentage(double discountPercentage)
{ {
m_discountPercentage = discountPercentage; m_discountPercentage = discountPercentage;
} }
/*
Function: getServiceIDsAsString (static helper)
Description: Converts a vector of service IDs into a single string separated by '|'.
Parameters:
- serviceIDs: const util::Vector<std::string>&, vector of service IDs
Returns:
- std::string: Concatenated service IDs string
*/
static std::string getServiceIDsAsString(const util::Vector<std::string>& serviceIDs) static std::string getServiceIDsAsString(const util::Vector<std::string>& serviceIDs)
{ {
int numberOfServices = serviceIDs.getSize(); int numberOfServices = serviceIDs.getSize();
@@ -415,14 +390,6 @@ static std::string getServiceIDsAsString(const util::Vector<std::string>& servic
return serviceIDsString; return serviceIDsString;
} }
/*
Function: getServiceIDsAsVector (static helper)
Description: Converts a string of service IDs separated by '|' into a vector.
Parameters:
- serviceIDsString: const std::string&, concatenated service IDs string
Returns:
- util::Vector<std::string>: Vector of service IDs
*/
static util::Vector<std::string> getServiceIDsAsVector(const std::string& serviceIDsString) static util::Vector<std::string> getServiceIDsAsVector(const std::string& serviceIDsString)
{ {
util::Vector<std::string> serviceIDs; util::Vector<std::string> serviceIDs;
@@ -435,14 +402,6 @@ static util::Vector<std::string> getServiceIDsAsVector(const std::string& servic
return serviceIDs; return serviceIDs;
} }
/*
Function: serialize
Description: Serializes the service booking into a CSV-formatted string.
Parameters:
- None
Returns:
- std::string: Serialized booking record
*/
std::string ServiceBooking::serialize() const std::string ServiceBooking::serialize() const
{ {
std::ostringstream serializedBooking; std::ostringstream serializedBooking;
@@ -458,16 +417,6 @@ std::string ServiceBooking::serialize() const
return serializedBooking.str(); return serializedBooking.str();
} }
/*
Function: deserialize
Description: Deserializes a CSV-formatted string into a ServiceBooking object.
Parameters:
- record: const std::string&, serialized booking record
Returns:
- ServiceBooking*: Pointer to the deserialized ServiceBooking object
Throws:
- std::runtime_error if discount percentage parsing fails
*/
ServiceBooking* ServiceBooking::deserialize(const std::string& record) ServiceBooking* ServiceBooking::deserialize(const std::string& record)
{ {
std::string id, customerId, vehicleNumber, vehicleBrand, vehicleModel, assignedTechnicianId; std::string id, customerId, vehicleNumber, vehicleBrand, vehicleModel, assignedTechnicianId;
@@ -506,15 +455,7 @@ ServiceBooking* ServiceBooking::deserialize(const std::string& record)
); );
} }
/*
Function: getHeaders
Description: Retrieves the CSV headers for service booking serialization.
Parameters:
- None
Returns:
- std::string: Header string ("ID,Status,ServiceIDs,CustomerID,VehicleNumber,VehicleBrand,VehicleModel,AssignedTechnicianID,DiscountPercentage")
*/
std::string ServiceBooking::getHeaders() std::string ServiceBooking::getHeaders()
{ {
return "ID,Status,ServiceIDs,CustomerID,VehicleNumber,VehicleBrand,VehicleModel,AssignedTechnicianID,DiscountPercentage"; return "ID,Status,ServiceIDs,CustomerID,VehicleNumber,VehicleBrand,VehicleModel,AssignedTechnicianID,DiscountPercentage";
} }
@@ -53,22 +53,6 @@ User::User(const std::string& userName, const std::string& password, const std::
m_type(role), m_type(role),
m_status(util::State::ACTIVE) {} m_status(util::State::ACTIVE) {}
/*
Function: User (parameterized constructor with ID)
Description: Initializes a user with an existing ID, credentials, personal details,
role, and state. Updates UID tracking based on ID.
Parameters:
- userId: const std::string&, unique user ID
- userName: const std::string&, username
- password: const std::string&, password
- name: const std::string&, full name
- phone: const std::string&, phone number
- email: const std::string&, email address
- role: util::UserType, role of the user
- status: util::State, state of the user (ACTIVE/INACTIVE)
Returns:
- A new User object
*/
User::User(const std::string& userId, const std::string& userName, const std::string& password, const std::string& name, const std::string& phone, const std::string& email, util::UserType role, util::State status) User::User(const std::string& userId, const std::string& userName, const std::string& password, const std::string& name, const std::string& phone, const std::string& email, util::UserType role, util::State status)
: m_id(userId), : m_id(userId),
m_userName(userName), m_userName(userName),
@@ -322,14 +306,6 @@ void User::setState(util::State status)
m_status = status; m_status = status;
} }
/*
Function: serialize
Description: Serializes the user into a CSV-formatted string.
Parameters:
- None
Returns:
- std::string: Serialized user record
*/
std::string User::serialize() const std::string User::serialize() const
{ {
std::ostringstream serializedUser; std::ostringstream serializedUser;
@@ -344,14 +320,6 @@ std::string User::serialize() const
return serializedUser.str(); return serializedUser.str();
} }
/*
Function: deserialize
Description: Deserializes a CSV-formatted string into a User object.
Parameters:
- record: const std::string&, serialized user record
Returns:
- User*: Pointer to the deserialized User object
*/
User* User::deserialize(const std::string& record) User* User::deserialize(const std::string& record)
{ {
std::string id, name, username, phone, password, email; std::string id, name, username, phone, password, email;
@@ -377,15 +345,8 @@ User* User::deserialize(const std::string& record)
status); status);
} }
/*
Function: getHeaders
Description: Retrieves the CSV headers for user serialization.
Parameters:
- None
Returns:
- std::string: Header string ("ID,Username,Password,Name,Phone,Email,UserType,UserStatus")
*/
std::string User::getHeaders() std::string User::getHeaders()
{ {
return "ID,Username,Password,Name,Phone,Email,UserType,UserStatus"; return "ID,Username,Password,Name,Phone,Email,UserType,UserStatus";
} }
@@ -6,22 +6,12 @@ Description: Implementation file containing the method definitions of the
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#include <stdexcept> #include <stdexcept>
#include "AuthenticationManagementService.h" #include "AuthenticationManagementService.h"
#include "User.h" #include "User.h"
User* AuthenticationManagementService::m_authenticatedUser = nullptr; User* AuthenticationManagementService::m_authenticatedUser = nullptr;
/*
Function: login
Description: Authenticates a user by checking the provided username and password
against the stored users in the DataStore. If successful, sets the
authenticated user.
Parameter: const std::string& username - users username
const std::string& password - users password
Return type: bool - true if login successful, false otherwise
*/
bool AuthenticationManagementService::login(const std::string& username, const std::string& password) bool AuthenticationManagementService::login(const std::string& username, const std::string& password)
{ {
util::Map<std::string, User*> users = m_dataStore.getUsers(); util::Map<std::string, User*> users = m_dataStore.getUsers();
@@ -42,12 +32,6 @@ bool AuthenticationManagementService::login(const std::string& username, const s
return false; return false;
} }
/*
Function: getAuthenticatedUser
Description: Retrieves the currently authenticated user.
Parameter: None
Return type: User* - pointer to the authenticated user
*/
User* AuthenticationManagementService::getAuthenticatedUser() User* AuthenticationManagementService::getAuthenticatedUser()
{ {
return m_authenticatedUser; return m_authenticatedUser;
@@ -6,7 +6,6 @@ Description: Header file declaring the AuthenticationManagementService class, wh
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#pragma once #pragma once
#include <string> #include <string>
#include "DataStore.h" #include "DataStore.h"
@@ -1,61 +1,171 @@
/* /*
File: InventoryManagementService.cpp File: InventoryManagementService.cpp
Description: Implements the InventoryManagementService class, which manages inventory Description: Implementation file containing the method definitions of the
items and observer relationships within the system. Provides methods InventoryManagementService class, including inventory operations
for loading and saving inventory items from persistent storage, as well and notification handling.
as attaching and persisting observers for notification handling.
Author: Trenser Author: Trenser
Date: 22-May-2026 Date:19-May-2026
*/ */
#include <stdexcept>
#include "Config.h"
#include "Enums.h"
#include "Factory.h"
#include "FileManager.h"
#include "InventoryItem.h"
#include "InventoryManagementService.h" #include "InventoryManagementService.h"
#include "Timestamp.h" #include "Config.h"
#include "User.h"
#include "Utility.h"
#include "Vector.h" #include "Vector.h"
#include "Enums.h"
#include "InventoryItem.h"
#include "Config.h"
#include "User.h"
#include "Factory.h"
#include "Timestamp.h"
#include "FileManager.h"
#include "Utility.h"
util::Map<std::string, User*> InventoryManagementService::m_observers{}; util::Map<std::string, User*> InventoryManagementService::m_observers{};
/* /*
Function: sendLowStockAlertsToAdmins (static helper) Function: addInventoryItem
Description: Sends low stock alert notifications to all admin users for a given inventory item. Description: Creates a new inventory item using the Factory and inserts it
Parameters: into the DataStore.
- inventoryManagementService: InventoryManagementService&, service used to send notifications Parameter: const std::string& partName - name of the part
- inventoryItem: const InventoryItem*, pointer to the low-stock inventory item int quantity - initial quantity of the part
- adminUsers: const util::Vector<User*>&, list of admin users to notify double price - price of the part
Returns: Return type: void
- None
*/ */
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;
}
void InventoryManagementService::attach(User* user)
{
if (user)
{
const std::string& userID = user->getId();
if (m_observers.find(userID) == -1)
{
m_observers[userID] = user;
}
}
}
void InventoryManagementService::detach(User* user)
{
if (user)
{
const std::string& userID = user->getId();
if (m_observers.find(userID) != -1)
{
m_observers.remove(userID);
}
}
}
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");
}
}
}
}
static void sendLowStockAlertsToAdmins(InventoryManagementService& inventoryManagementService, const InventoryItem* inventoryItem, const util::Vector<User*>& adminUsers) static void sendLowStockAlertsToAdmins(InventoryManagementService& inventoryManagementService, const InventoryItem* inventoryItem, const util::Vector<User*>& adminUsers)
{ {
int adminUsersSize = adminUsers.getSize(); int adminUsersSize = adminUsers.getSize();
for (int index = 0; index < adminUsersSize; index++) 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( inventoryManagementService.sendNotification(
adminUsers[index], adminUsers[index],
title, "Low Stock Alert",
message "The inventory item with ID " + inventoryItem->getId() +
); " has very low quantity in the inventory"
);
} }
} }
/*
Function: sendLowStockAlerts
Description: Sends alerts to user for inventory items with low stock
Parameters:
- None
Returns:
- None
*/
void InventoryManagementService::sendLowStockAlerts() void InventoryManagementService::sendLowStockAlerts()
{ {
auto& inventoryItems = m_dataStore.getInventoryItems(); auto& inventoryItems = m_dataStore.getInventoryItems();
@@ -80,7 +190,7 @@ void InventoryManagementService::sendLowStockAlerts()
{ {
throw std::runtime_error("The system has no admins present!"); throw std::runtime_error("The system has no admins present!");
} }
for (int index = 0; index < inventoryItemsSize; index++) for (int index = 0; index <= inventoryItemsSize; index++)
{ {
InventoryItem* inventoryItem = inventoryItems.getValueAt(index); InventoryItem* inventoryItem = inventoryItems.getValueAt(index);
if (inventoryItem && inventoryItem->getQuantity() < config::threshold::INVENTORY_LOW_STOCK_THRESHOLD) if (inventoryItem && inventoryItem->getQuantity() < config::threshold::INVENTORY_LOW_STOCK_THRESHOLD)
@@ -90,15 +200,6 @@ void InventoryManagementService::sendLowStockAlerts()
} }
} }
/*
Function: getObserverIDs
Description: Retrieves the IDs of all observers currently attached to the
InventoryManagementService.
Parameters:
- None
Returns:
- util::Vector<std::string>: Vector of observer user IDs
*/
util::Vector<std::string> InventoryManagementService::getObserverIDs() util::Vector<std::string> InventoryManagementService::getObserverIDs()
{ {
util::Vector<std::string> observerIDs; util::Vector<std::string> observerIDs;
@@ -114,15 +215,6 @@ util::Vector<std::string> InventoryManagementService::getObserverIDs()
return observerIDs; return observerIDs;
} }
/*
Function: loadInventoryItems
Description: Loads inventory items from persistent storage into the datastore.
Uses FileManager to deserialize inventory items from the configured file.
Parameters:
- None
Returns:
- void
*/
void InventoryManagementService::loadInventoryItems() void InventoryManagementService::loadInventoryItems()
{ {
util::FileManager<InventoryItem> inventoryItemFileManager(config::file::INVENTORYITEM_FILE); util::FileManager<InventoryItem> inventoryItemFileManager(config::file::INVENTORYITEM_FILE);
@@ -135,15 +227,6 @@ void InventoryManagementService::loadInventoryItems()
} }
} }
/*
Function: saveInventoryItems
Description: Saves inventory items from the datastore to persistent storage.
Uses FileManager to serialize inventory items into the configured file.
Parameters:
- None
Returns:
- void
*/
void InventoryManagementService::saveInventoryItems() void InventoryManagementService::saveInventoryItems()
{ {
util::FileManager<InventoryItem> inventoryItemFileManager(config::file::INVENTORYITEM_FILE); util::FileManager<InventoryItem> inventoryItemFileManager(config::file::INVENTORYITEM_FILE);
@@ -151,191 +234,12 @@ void InventoryManagementService::saveInventoryItems()
inventoryItemFileManager.save(inventoryItems); inventoryItemFileManager.save(inventoryItems);
} }
/*
Function: loadObservers
Description: Loads observer IDs from persistent storage and attaches corresponding
users as observers to the InventoryManagementService.
Parameters:
- None
Returns:
- void
*/
void InventoryManagementService::loadObservers() void InventoryManagementService::loadObservers()
{ {
util::loadObservers(config::file::INVENTORYMANAGEMENTOBSERVERS, this, m_dataStore); util::loadObservers(config::file::INVENTORYMANAGEMENTOBSERVERS, this, m_dataStore);
} }
/*
Function: saveObservers
Description: Saves the current observer IDs of the InventoryManagementService
to persistent storage for future retrieval.
Parameters:
- None
Returns:
- void
*/
void InventoryManagementService::saveObservers() void InventoryManagementService::saveObservers()
{ {
util::saveObservers(config::file::INVENTORYMANAGEMENTOBSERVERS, this); 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,
title,
message,
util::Timestamp()
);
if (notification)
{
user->addNotification(notification);
}
else
{
throw std::runtime_error("Failed to create notification");
}
}
}
}
@@ -6,7 +6,6 @@ Description: Header file declaring the InventoryManagementService class,
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#pragma once #pragma once
#include <string> #include <string>
#include "Map.h" #include "Map.h"
@@ -8,6 +8,7 @@ Date: 20-May-2026
*/ */
#include <stdexcept> #include <stdexcept>
#include "PaymentManagementService.h"
#include "Config.h" #include "Config.h"
#include "Enums.h" #include "Enums.h"
#include "Factory.h" #include "Factory.h"
@@ -15,7 +16,6 @@ Date: 20-May-2026
#include "InventoryItem.h" #include "InventoryItem.h"
#include "Invoice.h" #include "Invoice.h"
#include "JobCard.h" #include "JobCard.h"
#include "PaymentManagementService.h"
#include "Service.h" #include "Service.h"
#include "ServiceBooking.h" #include "ServiceBooking.h"
#include "Timestamp.h" #include "Timestamp.h"
@@ -24,6 +24,90 @@ Date: 20-May-2026
util::Map<std::string, User*> PaymentManagementService::m_observers{}; util::Map<std::string, User*> PaymentManagementService::m_observers{};
static void createInventoryItemsMap(util::Map<std::string, InventoryItem*>& completeInventoryItemMapOfBooking, const Service* currentService)
{
auto& currentRequiredInventoryItems = currentService->getRequiredInventoryItems();
for (int iterator = 0; iterator < currentRequiredInventoryItems.getSize(); iterator++)
{
auto& currentRequiredInventoryItem = currentRequiredInventoryItems.getValueAt(iterator);
completeInventoryItemMapOfBooking.insert(currentRequiredInventoryItem->getId(), currentRequiredInventoryItem);
}
}
void PaymentManagementService::generateInvoice(ServiceBooking* booking)
{
if (!booking)
{
throw std::runtime_error("Invoice generation failed: booking is null.");
}
double totalLabourCost = 0, totalPartsCost = 0, totalServiceCost = 0;
double discountPercentage = booking->getDiscountPercentage();
std::string bookingID = booking->getId();
util::Map<std::string, Service*> servicesInTheBookedService = booking->getServices();
util::Map<std::string, InventoryItem*> completeInventoryItemMapOfBooking;
util::Map<std::string, JobCard*> currentJobCards = m_dataStore.getJobCards();
for (int iterator = 0; iterator < currentJobCards.getSize(); iterator++)
{
JobCard* currentJobCard = currentJobCards.getValueAt(iterator);
if (currentJobCard->getBookingId() == bookingID && currentJobCard->getStatus() != util::ServiceJobStatus::COMPLETED)
{
throw std::runtime_error("Invoice generation failed: not all job cards are completed for booking '" + bookingID + "'.");
}
}
for (int iterator = 0; iterator < servicesInTheBookedService.getSize(); iterator++)
{
Service* currentService = servicesInTheBookedService.getValueAt(iterator);
if (currentService)
{
createInventoryItemsMap(completeInventoryItemMapOfBooking, currentService);
totalLabourCost += currentService->getLaborCost();
totalPartsCost += util::calculatePartsCost(currentService);
}
}
totalServiceCost = totalLabourCost + totalPartsCost;
totalServiceCost -= (totalServiceCost * (discountPercentage / 100));
Invoice* invoice = Factory::getObject<Invoice>(bookingID, booking, util::Timestamp(), totalLabourCost, completeInventoryItemMapOfBooking, totalPartsCost, discountPercentage, totalServiceCost, util::Timestamp(), util::PaymentMode::NOTSET, util::PaymentStatus::PENDING);
util::Map<std::string, Invoice*>& currentInvoices = m_dataStore.getInvoices();
currentInvoices.insert(invoice->getId(), invoice);
}
util::Map<std::string, Invoice*> PaymentManagementService::getInvoices(const std::string& customerID)
{
util::Map<std::string, Invoice*>& currentInvoices = m_dataStore.getInvoices();
util::Map<std::string, Invoice*> currentUserInvoices;
for (int iterator = 0; iterator < currentInvoices.getSize(); iterator++)
{
Invoice* currentInvoice = currentInvoices.getValueAt(iterator);
if (currentInvoice->getBooking()->getCustomerId() == customerID)
{
currentUserInvoices.insert(currentInvoice->getId(), currentInvoice);
}
}
return currentUserInvoices;
}
void PaymentManagementService::completePayment(const std::string& invoiceID, util::PaymentMode paymentMode)
{
auto& currentInvoices = m_dataStore.getInvoices();
int invoiceIndex = currentInvoices.find(invoiceID);
if (invoiceIndex != -1)
{
Invoice* invoice = currentInvoices.getValueAt(invoiceIndex);
User* currentUser = invoice->getBooking()->getCustomer();
invoice->setPaymentMethod(paymentMode);
invoice->setPaymentDate(util::Timestamp());
invoice->setStatus(util::PaymentStatus::COMPLETED);
std::string title, message;
title = "Payment successful";
message = "Payment successful for invoice ID " + invoiceID;
sendNotification(currentUser, title, message);
}
else
{
throw std::runtime_error("Payment failed: invalid invoice ID.");
}
}
/* /*
Function: attach Function: attach
Description: Attaches a user as an observer to the PaymentManagementService for receiving notifications. Description: Attaches a user as an observer to the PaymentManagementService for receiving notifications.
@@ -86,7 +170,7 @@ void PaymentManagementService::sendNotification(User* user, const std::string& t
Factory::getObject<Notification>( Factory::getObject<Notification>(
user->getId(), user->getId(),
user, user,
title, "PaymentManagementService: " + title,
message, message,
util::Timestamp() util::Timestamp()
); );
@@ -130,9 +214,9 @@ void PaymentManagementService::sendPaymentReminders()
User* customer = serviceBooking->getCustomer(); User* customer = serviceBooking->getCustomer();
if (customer) if (customer)
{ {
std::string title = "Payment Reminder"; sendNotification(customer,
std::string message = "Your payment for Invoice ID " + invoice->getId() + " is still pending. Please complete the payment."; "Payment Reminder",
sendNotification(customer, title, message); "Your payment for Invoice ID " + invoice->getId() + " is still pending.Please complete the payment." + invoice->getId());
} }
} }
} }
@@ -140,15 +224,6 @@ void PaymentManagementService::sendPaymentReminders()
} }
} }
/*
Function: getObserverIDs
Description: Retrieves the IDs of all observers currently attached to the
PaymentManagementService.
Parameters:
- None
Returns:
- util::Vector<std::string>: Vector of observer user IDs
*/
util::Vector<std::string> PaymentManagementService::getObserverIDs() util::Vector<std::string> PaymentManagementService::getObserverIDs()
{ {
util::Vector<std::string> observerIDs; util::Vector<std::string> observerIDs;
@@ -164,19 +239,6 @@ util::Vector<std::string> PaymentManagementService::getObserverIDs()
return observerIDs; return observerIDs;
} }
/*
Function: loadInvoices
Description: Loads invoices from persistent storage into the datastore.
Validates associated service bookings and inventory parts before
attaching them to each invoice. Throws exceptions if invalid IDs
are encountered.
Parameters:
- None
Returns:
- void
Throws:
- std::runtime_error if a booking ID or part ID is invalid
*/
void PaymentManagementService::loadInvoices() void PaymentManagementService::loadInvoices()
{ {
util::FileManager<Invoice> invoiceFileManager(config::file::INVOICE_FILE); util::FileManager<Invoice> invoiceFileManager(config::file::INVOICE_FILE);
@@ -210,16 +272,6 @@ void PaymentManagementService::loadInvoices()
invoices[invoice->getId()] = invoice; invoices[invoice->getId()] = invoice;
} }
} }
/*
Function: saveInvoices
Description: Saves invoices from the datastore to persistent storage.
Uses FileManager to serialize invoices into the configured file.
Parameters:
- None
Returns:
- void
*/
void PaymentManagementService::saveInvoices() void PaymentManagementService::saveInvoices()
{ {
util::FileManager<Invoice> invoiceFileManager(config::file::INVOICE_FILE); util::FileManager<Invoice> invoiceFileManager(config::file::INVOICE_FILE);
@@ -227,161 +279,12 @@ void PaymentManagementService::saveInvoices()
invoiceFileManager.save(invoices); invoiceFileManager.save(invoices);
} }
/*
Function: loadObservers
Description: Loads observer IDs from persistent storage and attaches corresponding
users as observers to the PaymentManagementService.
Parameters:
- None
Returns:
- void
Throws:
- std::runtime_error if an observer ID is invalid (not found in datastore)
*/
void PaymentManagementService::loadObservers() void PaymentManagementService::loadObservers()
{ {
util::loadObservers(config::file::PAYMENTMANAGEMENTOBSERVERS, this, m_dataStore); util::loadObservers(config::file::PAYMENTMANAGEMENTOBSERVERS, this, m_dataStore);
} }
/*
Function: saveObservers
Description: Saves the current observer IDs of the PaymentManagementService
to persistent storage for future retrieval.
Parameters:
- None
Returns:
- void
*/
void PaymentManagementService::saveObservers() void PaymentManagementService::saveObservers()
{ {
util::saveObservers(config::file::PAYMENTMANAGEMENTOBSERVERS, this); util::saveObservers(config::file::PAYMENTMANAGEMENTOBSERVERS, this);
} }
/*
Function: createInventoryItemsMap (static helper)
Description: Builds a map of inventory items required for a given service and adds them to the bookings inventory map.
Parameters:
- completeInventoryItemMapOfBooking: util::Map<std::string, InventoryItem*>&, map to store inventory items for the booking
- currentService: const Service*, pointer to the current service
Returns:
- void
*/
static void createInventoryItemsMap(util::Map<std::string, InventoryItem*>& completeInventoryItemMapOfBooking, const Service* currentService)
{
auto& currentRequiredInventoryItems = currentService->getRequiredInventoryItems();
for (int iterator = 0; iterator < currentRequiredInventoryItems.getSize(); iterator++)
{
auto& currentRequiredInventoryItem = currentRequiredInventoryItems.getValueAt(iterator);
completeInventoryItemMapOfBooking.insert(currentRequiredInventoryItem->getId(), currentRequiredInventoryItem);
}
}
/*
Function: generateInvoice
Description: Generates an invoice for a completed service booking.
Validates that all job cards are completed, calculates labor and parts cost, applies discount,
and stores the invoice in the datastore.
Parameters:
- booking: ServiceBooking*, pointer to the service booking
Returns:
- void
Throws:
- std::runtime_error if booking is null or job cards are incomplete
*/
void PaymentManagementService::generateInvoice(ServiceBooking* booking)
{
if (!booking)
{
throw std::runtime_error("Invoice generation failed: booking is null.");
}
double totalLaborCost = 0, totalPartsCost = 0, totalServiceCost = 0;
double discountPercentage = booking->getDiscountPercentage();
std::string bookingID = booking->getId();
util::Map<std::string, Service*> servicesInTheBookedService = booking->getServices();
util::Map<std::string, InventoryItem*> completeInventoryItemMapOfBooking;
util::Map<std::string, JobCard*> currentJobCards = m_dataStore.getJobCards();
for (int iterator = 0; iterator < currentJobCards.getSize(); iterator++)
{
JobCard* currentJobCard = currentJobCards.getValueAt(iterator);
util::ServiceJobStatus currentJobCardStatus = currentJobCard->getStatus();
if (currentJobCard->getBookingId() == bookingID && currentJobCardStatus != util::ServiceJobStatus::CANCELLED && currentJobCardStatus != util::ServiceJobStatus::COMPLETED)
{
throw std::runtime_error("Invoice generation failed: Not all job cards are completed for booking '" + bookingID + "'.");
}
}
for (int iterator = 0; iterator < servicesInTheBookedService.getSize(); iterator++)
{
Service* currentService = servicesInTheBookedService.getValueAt(iterator);
if (currentService)
{
createInventoryItemsMap(completeInventoryItemMapOfBooking, currentService);
totalLaborCost += currentService->getLaborCost();
totalPartsCost += util::calculatePartsCost(currentService);
}
}
totalServiceCost = totalLaborCost + totalPartsCost;
totalServiceCost -= (totalServiceCost * (discountPercentage / 100));
Invoice* invoice = Factory::getObject<Invoice>(bookingID, booking, util::Timestamp(), totalLaborCost, completeInventoryItemMapOfBooking, totalPartsCost, discountPercentage, totalServiceCost, util::Timestamp(), util::PaymentMode::NOTSET, util::PaymentStatus::PENDING);
util::Map<std::string, Invoice*>& currentInvoices = m_dataStore.getInvoices();
currentInvoices.insert(invoice->getId(), invoice);
}
/*
Function: getInvoices
Description: Retrieves all invoices associated with a specific customer.
Parameters:
- customerID: std::string, ID of the customer
Returns:
- util::Map<std::string, Invoice*> containing the customers invoices
*/
util::Map<std::string, Invoice*> PaymentManagementService::getInvoices(const std::string& customerID)
{
util::Map<std::string, Invoice*>& currentInvoices = m_dataStore.getInvoices();
util::Map<std::string, Invoice*> currentUserInvoices;
for (int iterator = 0; iterator < currentInvoices.getSize(); iterator++)
{
Invoice* currentInvoice = currentInvoices.getValueAt(iterator);
if (currentInvoice->getBooking()->getCustomerId() == customerID)
{
currentUserInvoices.insert(currentInvoice->getId(), currentInvoice);
}
}
return currentUserInvoices;
}
/*
Function: completePayment
Description: Completes payment for a specific invoice. Updates payment method, date, and status,
then sends a notification to the customer.
Parameters:
- invoiceID: std::string, ID of the invoice
- paymentMode: util::PaymentMode, mode of payment (e.g., ONLINE, OFFLINE)
Returns:
- void
Throws:
- std::runtime_error if the invoice ID is invalid
*/
void PaymentManagementService::completePayment(const std::string& invoiceID, util::PaymentMode paymentMode)
{
auto& currentInvoices = m_dataStore.getInvoices();
int invoiceIndex = currentInvoices.find(invoiceID);
if (invoiceIndex != -1)
{
Invoice* invoice = currentInvoices.getValueAt(invoiceIndex);
if (invoice && invoice->getStatus() != util::PaymentStatus::COMPLETED)
{
User* currentUser = invoice->getBooking()->getCustomer();
invoice->setPaymentMethod(paymentMode);
invoice->setPaymentDate(util::Timestamp());
invoice->setStatus(util::PaymentStatus::COMPLETED);
std::string title, message;
title = "Payment successful";
message = "Payment successful for Invoice ID " + invoiceID;
sendNotification(currentUser, title, message);
}
}
else
{
throw std::runtime_error("Payment failed: invalid invoice ID.");
}
}
@@ -6,7 +6,6 @@ Description: Header file declaring the ServiceManagementService class, which man
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#pragma once #pragma once
#include <string> #include <string>
#include "Map.h" #include "Map.h"
@@ -1,8 +1,7 @@
/* /*
File: UserManagementService.cpp File: UserManagementService.cpp
Description: Implementation file containing the method definitions of the Description: Implementation file containing the method definitions of the
UserManagementService class, including user creation, updates, UserManagementService class, including user retrieval and removal logic.
and ensuring an admin account exists.
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
@@ -13,22 +12,14 @@ Date:19-May-2026
#include "Factory.h" #include "Factory.h"
#include "FileManager.h" #include "FileManager.h"
#include "InventoryManagementService.h" #include "InventoryManagementService.h"
#include "Notification.h" #include "Invoice.h"
#include "PaymentManagementService.h" #include "PaymentManagementService.h"
#include "ServiceManagementService.h" #include "ServiceManagementService.h"
#include "User.h" #include "User.h"
#include "UserManagementService.h" #include "UserManagementService.h"
#include "Utility.h"
#include "Vector.h" #include "Vector.h"
#include "Validator.h"
/*
Function: ensureAdminExists
Description: Ensures that at least one admin user exists in the system.
If no admin is found, creates a default admin user using
configuration constants.
Parameter: None
Return type: void
*/
void UserManagementService::ensureAdminExists() void UserManagementService::ensureAdminExists()
{ {
auto& usersMap = m_dataStore.getUsers(); auto& usersMap = m_dataStore.getUsers();
@@ -55,37 +46,22 @@ void UserManagementService::ensureAdminExists()
} }
} }
/*
Function: createUser
Description: Creates a new user with the provided details. Validates that
the username is unique, then attaches the user to relevant
management services (payment, service, inventory).
Parameter: const std::string& username - users username
const std::string& name - users name
const std::string& password - users password
const std::string& email - users email address
const std::string& phone - users phone number
util::UserType type - type of user (ADMIN, CUSTOMER, TECHNICIAN)
Return type: void
*/
void UserManagementService::createUser(const std::string& username, const std::string& name, const std::string& password, const std::string& email, const std::string& phone, util::UserType type) void UserManagementService::createUser(const std::string& username, const std::string& name, const std::string& password, const std::string& email, const std::string& phone, util::UserType type)
{ {
InventoryManagementService inventoryManagementService; InventoryManagementService inventoryManagementService;
PaymentManagementService paymentManagementService; PaymentManagementService paymentManagementService;
ServiceManagementService serviceManagementService; ServiceManagementService serviceManagementService;
auto& usersMap = m_dataStore.getUsers(); auto& usersMap = m_dataStore.getUsers();
if (util::isUsernameDuplicate(username, usersMap)) int index = usersMap.findIf(
[&](const std::string&, User* user)
{
return user->getUserName() == username;
}
);
if (index != -1)
{ {
throw std::runtime_error("Username already exists"); throw std::runtime_error("Username already exists");
} }
if (util::isEmailDuplicate(email, usersMap))
{
throw std::runtime_error("Email already exists");
}
if (util::isPhoneDuplicate(phone, usersMap))
{
throw std::runtime_error("Phone already exists");
}
User* newUser = Factory::getObject<User>(username, password, name, phone, email, type); User* newUser = Factory::getObject<User>(username, password, name, phone, email, type);
usersMap.insert(newUser->getId(), newUser); usersMap.insert(newUser->getId(), newUser);
paymentManagementService.attach(newUser); paymentManagementService.attach(newUser);
@@ -96,42 +72,80 @@ void UserManagementService::createUser(const std::string& username, const std::s
} }
} }
/*
Function: updateUserDetails
Description: Updates the email and phone details of an existing user.
Throws an exception if the user does not exist.
Parameter: const std::string& userID - ID of the user to update
const std::string& email - new email address
const std::string& phone - new phone number
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)
{ {
auto& usersMap = m_dataStore.getUsers(); auto& usersMap = m_dataStore.getUsers();
int index = usersMap.find(userID); int index = usersMap.find(userID);
if (index == -1) if (index == -1)
{ {
throw std::runtime_error("User does not exist!\n"); throw std::runtime_error("User does not exist!");
} }
User* user = usersMap.getValueAt(index); User* user = usersMap.getValueAt(index);
if (email != user->getEmail())
{
if (util::isEmailDuplicate(email, usersMap))
{
throw std::runtime_error("Email already exists!\n");
}
}
if (phone != user->getPhone())
{
if (util::isPhoneDuplicate(phone, usersMap))
{
throw std::runtime_error("Phone number already exists!\n");
}
}
user->setEmail(email); user->setEmail(email);
user->setPhone(phone); user->setPhone(phone);
} }
/*
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();
}
util::Map<std::string, User*> UserManagementService::getUsers(util::UserType type)
{
util::Map<std::string, User*>& currentUsers = m_dataStore.getUsers();
util::Map<std::string, User*> filteredUsersMap;
for (int iterator = 0; iterator < currentUsers.getSize(); iterator++)
{
User* currentUser = currentUsers.getValueAt(iterator);
if (currentUser->getUserType() == type)
{
filteredUsersMap.insert(currentUser->getId(), currentUser);
}
}
return filteredUsersMap;
}
/*
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);
}
}
}
/* /*
Function: getUserNotifications Function: getUserNotifications
Description: Retrieves all notifications associated with a given user ID. Description: Retrieves all notifications associated with a given user ID.
@@ -157,7 +171,7 @@ util::Vector<Notification*> UserManagementService::getUserNotifications(const st
util::Vector<Notification*> notificationsVector; util::Vector<Notification*> notificationsVector;
for (int index = 0; index < numberOfNotifications; index++) for (int index = 0; index < numberOfNotifications; index++)
{ {
notificationsVector.push_back(notifications.getValueAt(index)); notificationsVector.push_back(notifications.getValueAt(index));
} }
return notificationsVector; return notificationsVector;
} }
@@ -194,18 +208,6 @@ void UserManagementService::deleteNotification(const std::string& notificationID
notifications.remove(notificationID); notifications.remove(notificationID);
} }
/*
Function: loadUsers
Description: Loads users and notifications from persistent storage into the datastore.
Validates that each notifications recipient exists and attaches the
notification to the corresponding user.
Parameters:
- None
Returns:
- void
Throws:
- std::runtime_error if a notification recipient user ID is invalid
*/
void UserManagementService::loadUsers() void UserManagementService::loadUsers()
{ {
util::FileManager<User> userFileManager(config::file::USER_FILE); util::FileManager<User> userFileManager(config::file::USER_FILE);
@@ -233,15 +235,6 @@ void UserManagementService::loadUsers()
} }
} }
/*
Function: saveUsers
Description: Saves users and their notifications from the datastore to persistent storage.
Collects notifications from all users into a single map before saving.
Parameters:
- None
Returns:
- void
*/
void UserManagementService::saveUsers() void UserManagementService::saveUsers()
{ {
util::FileManager<User> userFileManager(config::file::USER_FILE); util::FileManager<User> userFileManager(config::file::USER_FILE);
@@ -261,78 +254,3 @@ void UserManagementService::saveUsers()
userFileManager.save(users); userFileManager.save(users);
notificationFileManager.save(notifications); 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)
{
InventoryManagementService inventoryManagementService;
PaymentManagementService paymentManagementService;
ServiceManagementService serviceManagementService;
int index = m_dataStore.getUsers().find(userID);
if (index != -1)
{
User* user = m_dataStore.getUsers().getValueAt(index);
if (user != nullptr)
{
if (user->getUserType() == util::UserType::CUSTOMER)
{
serviceManagementService.cancelCustomerServiceBookings(userID);
}
if (user->getUserType() == util::UserType::TECHNICIAN)
{
serviceManagementService.cancelTechnicianJobs(userID);
}
user->setState(util::State::INACTIVE);
inventoryManagementService.detach(user);
paymentManagementService.detach(user);
serviceManagementService.detach(user);
}
}
}
util::Map<std::string, User*> UserManagementService::getUsers(util::UserType type)
{
util::Map<std::string, User*>& currentUsers = m_dataStore.getUsers();
util::Map<std::string, User*> filteredUsersMap;
for (int iterator = 0; iterator < currentUsers.getSize(); iterator++)
{
User* currentUser = currentUsers.getValueAt(iterator);
if (currentUser && currentUser->getState() == util::State::ACTIVE && currentUser->getUserType() == type)
{
filteredUsersMap.insert(currentUser->getId(), currentUser);
}
}
return filteredUsersMap;
}
@@ -1,8 +1,7 @@
/* /*
File: UserManagementService.h File: UserManagementService.h
Description: Header file declaring the UserManagementService class, which manages Description: Header file declaring the UserManagementService class, which manages
user creation, updates, retrieval, removal, notifications, and ensures user creation, updates, retrieval, removal, and notification handling.
the existence of an admin account.
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
@@ -1,8 +1,7 @@
/* /*
File: Config.h File: Config.h
Description: Header file declaring configuration constants for the Vehicle Service System. Description: Defines configuration constants for system thresholds in the Vehicle Service Management System.
Includes default admin account details such as username, name, password, Includes limits for inventory stock alerts and payment reminder intervals.
email, and phone number.
Author: Trenser Author: Trenser
Date: 21-May-2026 Date: 21-May-2026
*/ */
@@ -137,10 +137,6 @@ namespace util
{ {
return PaymentMode::OFFLINE; return PaymentMode::OFFLINE;
} }
if (value == "NOTSET")
{
return PaymentMode::NOTSET;
}
throw std::invalid_argument("Invalid PaymentMode string"); throw std::invalid_argument("Invalid PaymentMode string");
} }
@@ -286,4 +282,4 @@ namespace util
} }
throw std::invalid_argument("Invalid State string"); throw std::invalid_argument("Invalid State string");
} }
} }
@@ -1,67 +1,17 @@
/*
File: FileHelper.h
Description: Provides utility functions for loading and saving records
from and to CSV-like text files. Ensures files are created
if missing and supports simple record persistence.
Author: Trenser
Date: 22-May-2026
*/
#pragma once #pragma once
#include <fstream> #include <fstream>
#include <string> #include <string>
#include <stdexcept> #include <stdexcept>
#include <direct.h>
#include "Vector.h" #include "Vector.h"
namespace util namespace util
{ {
/*
Function: ensureDirectoryExists
Description: Creates all missing directories present in the given file path.
Iteratively parses the path and creates each directory level
using _mkdir() before file operations are performed.
Parameters:
- filePath: const std::string&, relative or absolute file path
Returns:
- void
Throws:
- None (_mkdir failures are intentionally ignored if directory already exists)
*/
inline void ensureDirectoryExists(const std::string& filePath)
{
size_t position = 0;
while ((position = filePath.find('/', position)) != std::string::npos)
{
std::string directory = filePath.substr(0, position);
if (!directory.empty())
{
(void)_mkdir(directory.c_str());
}
position++;
}
}
/*
Function: loadRecords
Description: Loads records from a given file path into a vector of strings.
Skips the header line if present. Creates the file if it does not exist.
Parameters:
- filePath: const std::string&, path to the file
Returns:
- util::Vector<std::string>: Vector containing all records (excluding header)
Throws:
- None (creates file if missing)
*/
inline util::Vector<std::string> loadRecords(const std::string& filePath) inline util::Vector<std::string> loadRecords(const std::string& filePath)
{ {
util::Vector<std::string> records; util::Vector<std::string> records;
std::ifstream file(filePath); std::ifstream file(filePath);
if (!file.is_open()) if (!file.is_open())
{ {
ensureDirectoryExists(filePath);
std::ofstream newFile(filePath); std::ofstream newFile(filePath);
newFile.close(); newFile.close();
file.open(filePath); file.open(filePath);
@@ -80,18 +30,6 @@ namespace util
return records; return records;
} }
/*
Function: saveRecords
Description: Saves records to a given file path. Overwrites existing content
and writes a header line followed by all records.
Parameters:
- filePath: const std::string&, path to the file
- records: const util::Vector<std::string>&, vector of records to save
Returns:
- void
Throws:
- std::runtime_error if the file cannot be opened for writing
*/
inline void saveRecords(const std::string& filePath, const util::Vector<std::string>& records) inline void saveRecords(const std::string& filePath, const util::Vector<std::string>& records)
{ {
std::ofstream file(filePath, std::ios::trunc); std::ofstream file(filePath, std::ios::trunc);
@@ -1,21 +1,9 @@
/*
File: FileManager.h
Description: Declares and implements a generic FileManager template class for
loading and saving objects to and from files. Uses serialization
and deserialization methods defined in the object type T.
Provides persistence support for system entities such as Users,
Services, InventoryItems, etc.
Author: Trenser
Date: 22-May-2026
*/
#pragma once #pragma once
#include <stdexcept>
#include <string> #include <string>
#include <stdexcept>
#include <fstream> #include <fstream>
#include "Vector.h" #include "Vector.h"
#include "Map.h" #include "Map.h"
#include "FileHelper.h"
namespace util namespace util
{ {
@@ -33,18 +21,6 @@ namespace util
void save(const objects<T>&); void save(const objects<T>&);
}; };
/*
Function: load
Description: Loads records from the file into a map of objects.
Skips the header line, deserializes each record into an object of type T,
and stores them in a map keyed by object ID.
Parameters:
- None
Returns:
- util::Map<std::string, T*> containing deserialized objects
Throws:
- std::runtime_error if deserialization fails for any record
*/
template <typename T> template <typename T>
objects<T> FileManager<T>::load() objects<T> FileManager<T>::load()
{ {
@@ -52,7 +28,6 @@ namespace util
std::ifstream file(m_filePath); std::ifstream file(m_filePath);
if (!file.is_open()) if (!file.is_open())
{ {
ensureDirectoryExists(m_filePath);
std::ofstream newFile(m_filePath); std::ofstream newFile(m_filePath);
newFile.close(); newFile.close();
file.open(m_filePath); file.open(m_filePath);
@@ -83,17 +58,6 @@ namespace util
return records; return records;
} }
/*
Function: save
Description: Saves records to the file. Serializes each object of type T into a string,
writes a header line, and then writes all serialized records to the file.
Parameters:
- records: const util::Map<std::string, T*>&, map of objects to save
Returns:
- void
Throws:
- std::runtime_error if the file cannot be opened for writing
*/
template <typename T> template <typename T>
void FileManager<T>::save(const objects<T>& records) void FileManager<T>::save(const objects<T>& records)
{ {
@@ -62,7 +62,6 @@ namespace util
*/ */
inline void pressEnter() inline void pressEnter()
{ {
std::cout << std::endl;
system("pause"); system("pause");
} }
} }
@@ -21,28 +21,4 @@ namespace util
{ {
std::cout << "\x1B[2J\x1B[H" << std::flush; std::cout << "\x1B[2J\x1B[H" << std::flush;
} }
/*
Function: truncateString
Description:
Truncates a string if its length exceeds the given maximum length.
The truncated string ends with "..." to indicate omitted characters.
Parameters:
- text: const std::string&, input string to truncate
- maxLength: size_t, maximum allowed length of the returned string
Returns:
- std::string: Original string if within limit, otherwise truncated string with "..."
*/
inline std::string truncateString(const std::string& text, size_t maxLength)
{
if (text.length() <= maxLength)
{
return text;
}
if (maxLength <= 3)
{
return std::string(maxLength, '.');
}
return text.substr(0, maxLength - 3) + "...";
}
} }
@@ -1,26 +1,8 @@
/*
File: StringHelper.h
Description: Provides utility functions for extracting numeric values from strings.
Useful for parsing IDs, codes, or mixed alphanumeric inputs where
digits need to be isolated and converted into integers.
Author: Trenser
Date: 22-May-2026
*/
#include <cctype> #include <cctype>
#include <string> #include <string>
namespace util namespace util
{ {
/*
Function: extractNumber
Description: Extracts all digits from the given string and converts them into an integer.
Ignores non-digit characters. For example, "abc123xyz" returns 123.
Parameters:
- input: const std::string&, the input string containing digits and/or other characters
Returns:
- int: The integer value formed by concatenating all digits in the string
*/
inline int extractNumber(const std::string& input) inline int extractNumber(const std::string& input)
{ {
int result = 0; int result = 0;
@@ -1,17 +1,17 @@
/* /*
File: Utility.h File: Utility.h
Description: Header file declaring utility functions used across the system Description: Header file declaring utility functions used across the system,
including cost calculation for services based on required inventory items.
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#pragma once #pragma once
#include "Service.h"
#include "ComboPackage.h" #include "ComboPackage.h"
#include "DataStore.h"
#include "FileHelper.h"
#include "InventoryItem.h" #include "InventoryItem.h"
#include "NotificationManagementService.h" #include "NotificationManagementService.h"
#include "Service.h" #include "FileHelper.h"
#include "DataStore.h"
namespace util namespace util
{ {
@@ -37,9 +37,11 @@ namespace util
/* /*
Function: calculateComboServiceEstimatedCost Function: calculateComboServiceEstimatedCost
Description: Calculates the estimated total cost of a combo package by summing Description: Calculates the estimated total cost of a combo package by summing
the labor and parts costs of all services included in the package. the labor cost and parts cost of all services included in the package.
Parameter: const ComboPackage* comboPackage - pointer to the combo package object Parameters:
Return type: double - estimated total cost of the combo package - comboPackage: const ComboPackage*, pointer to the combo package whose cost is to be estimated
Returns:
- double: The estimated total cost of the combo package
*/ */
inline double calculateComboServiceEstimatedCost(const ComboPackage* comboPackage) inline double calculateComboServiceEstimatedCost(const ComboPackage* comboPackage)
{ {
@@ -54,20 +56,6 @@ namespace util
return cost; return cost;
} }
/*
Function: loadObservers
Description: Loads observer IDs from a file and attaches the corresponding users
to the notification management service. Validates that each observer ID
exists in the datastore before attaching.
Parameters:
- filePath: const std::string&, path to the file containing observer IDs
- service: NotificationManagementService*, pointer to the notification service
- dataStore: DataStore&, reference to the datastore containing users
Returns:
- void
Throws:
- std::runtime_error if an observer ID is invalid (not found in datastore)
*/
inline void loadObservers(const std::string& filePath, NotificationManagementService* service, DataStore& dataStore) inline void loadObservers(const std::string& filePath, NotificationManagementService* service, DataStore& dataStore)
{ {
auto observerIDs = util::loadRecords(filePath); auto observerIDs = util::loadRecords(filePath);
@@ -84,19 +72,9 @@ namespace util
} }
} }
/*
Function: saveObservers
Description: Saves the current observer IDs from the notification management service
to a file for persistence.
Parameters:
- filePath: const std::string&, path to the file where observer IDs will be saved
- service: NotificationManagementService*, pointer to the notification service
Returns:
- void
*/
inline void saveObservers(const std::string& filePath, NotificationManagementService* service) inline void saveObservers(const std::string& filePath, NotificationManagementService* service)
{ {
auto observerIDs = service->getObserverIDs(); auto observerIDs = service->getObserverIDs();
util::saveRecords(filePath, observerIDs); util::saveRecords(filePath, observerIDs);
} }
} }
@@ -106,70 +106,4 @@ bool util::isPasswordValid(const std::string& password)
} }
return hasUpper && hasLower && hasDigit && hasSpecial; return hasUpper && hasLower && hasDigit && hasSpecial;
}
/*
* Function: isUsernameDuplicate
* Description: Checks if the given username already exists among active users.
* Parameters:
* username - string containing the username to validate
* usersMap - map of user objects keyed by identifier
* Returns:
* bool - true if the username is already in use by an active user, false otherwise
* Notes:
* - Only considers users with state util::State::ACTIVE
*/
bool util::isUsernameDuplicate(const std::string& username, const util::Map<std::string, User*>& usersMap)
{
int index = usersMap.findIf(
[&](const std::string&, User* user)
{
return (user->getUserName() == username && user->getState() == util::State::ACTIVE);
}
);
return index != -1;
}
/*
* Function: isPhoneDuplicate
* Description: Checks if the given phone number already exists among active users.
* Parameters:
* phone - string containing the phone number to validate
* usersMap - map of user objects keyed by identifier
* Returns:
* bool - true if the phone number is already in use by an active user, false otherwise
* Notes:
* - Only considers users with state util::State::ACTIVE
*/
bool util::isPhoneDuplicate(const std::string& phone, const util::Map<std::string, User*>& usersMap)
{
int index = usersMap.findIf(
[&](const std::string&, User* user)
{
return (user->getPhone() == phone && user->getState() == util::State::ACTIVE);
}
);
return index != -1;
}
/*
* Function: isEmailDuplicate
* Description: Checks if the given email address already exists among active users.
* Parameters:
* email - string containing the email address to validate
* usersMap - map of user objects keyed by identifier
* Returns:
* bool - true if the email address is already in use by an active user, false otherwise
* Notes:
* - Only considers users with state util::State::ACTIVE
*/
bool util::isEmailDuplicate(const std::string& email, const util::Map<std::string, User*>& usersMap)
{
int index = usersMap.findIf(
[&](const std::string&, User* user)
{
return (user->getEmail() == email && user->getState() == util::State::ACTIVE);
}
);
return index != -1;
} }
@@ -9,15 +9,10 @@
#include<string> #include<string>
#include<algorithm> #include<algorithm>
#include<cctype> #include<cctype>
#include "Map.h"
#include "User.h"
namespace util namespace util
{ {
bool isPhoneNumberValid(const std::string&); bool isPhoneNumberValid(const std::string&);
bool isEmailValid(const std::string&); bool isEmailValid(const std::string&);
bool isPasswordValid(const std::string&); bool isPasswordValid(const std::string&);
bool isUsernameDuplicate(const std::string&, const util::Map<std::string, User*>&);
bool isPhoneDuplicate(const std::string&, const util::Map<std::string, User*>&);
bool isEmailDuplicate(const std::string&, const util::Map<std::string, User*>&);
} }
@@ -1,16 +1,15 @@
/* /*
File: AdminMenu.cpp File: AdminMenu.cpp
Description: Implements the AdminMenu class which provides the administrators console interface Description: Implementation file containing the method definitions of the
in the Vehicle Service Management System. Handles menu display, user input, and AdminMenu class, including menu handling, inventory operations,
admin-specific operations such as inventory management, technician management, user management, and combo package management functions.
service creation, combo package management, job assignment, and notifications.
Author: Trenser Author: Trenser
Date: 19-May-2026 Date:19-May-2026
*/ */
#include <iomanip> #include <iomanip>
#include <iostream> #include <iostream>
#include "AdminMenu.h" #include "AdminMenu.h"
#include "ComboPackage.h"
#include "Enums.h" #include "Enums.h"
#include "InputHelper.h" #include "InputHelper.h"
#include "InventoryItem.h" #include "InventoryItem.h"
@@ -22,6 +21,7 @@ Date: 19-May-2026
#include "Utility.h" #include "Utility.h"
#include "Validator.h" #include "Validator.h"
/* /*
Function: showMenu Function: showMenu
Description: Displays the admin menu and handles user input until logout is selected. Description: Displays the admin menu and handles user input until logout is selected.
@@ -135,7 +135,6 @@ void AdminMenu::logout()
{ {
m_controller.logout(); m_controller.logout();
} }
/* /*
Function: changePassword Function: changePassword
Description: Allows the admin to change their password after validation. Description: Allows the admin to change their password after validation.
@@ -144,7 +143,23 @@ Return type: void
*/ */
void AdminMenu::changePassword() void AdminMenu::changePassword()
{ {
changePasswordHelper(m_controller); std::string newPassword;
while (true)
{
util::clear();
std::cout << "Enter new password: ";
util::read(newPassword);
if (!util::isPasswordValid(newPassword))
{
std::cout << "Error: Password is not strong enough!\n";
util::pressEnter();
continue;
}
m_controller.changePassword(newPassword);
std::cout << "Password changed successfully\n";
util::pressEnter();
break;
}
} }
/* /*
@@ -156,35 +171,11 @@ Return type: void
*/ */
void AdminMenu::viewStockLevels() void AdminMenu::viewStockLevels()
{ {
util::clear();
auto inventoryItems = m_controller.getInventoryItems(); auto inventoryItems = m_controller.getInventoryItems();
bool hasActiveItems = false;
std::cout << "View Stock Levels" << std::endl;
if (inventoryItems.isEmpty())
{
std::cout << "No items found in Inventory.\n";
util::pressEnter();
return;
}
for (int index = 0; index < inventoryItems.getSize(); index++)
{
const InventoryItem* item = inventoryItems.getValueAt(index);
if (item->getState() == util::State::ACTIVE)
{
hasActiveItems = true;
break;
}
}
if (!hasActiveItems)
{
std::cout << "No active Inventory Item found.\n";
util::pressEnter();
return;
}
std::cout << std::left << std::setw(15) << "Item ID" std::cout << std::left << std::setw(15) << "Item ID"
<< std::setw(25) << "Part Name" << std::setw(25) << "Part Name"
<< std::setw(15) << "Quantity" << std::setw(10) << "Quantity"
<< std::setw(15) << "Price" << std::setw(10) << "Price"
<< std::endl; << std::endl;
for (int iterator = 0; iterator < inventoryItems.getSize(); ++iterator) for (int iterator = 0; iterator < inventoryItems.getSize(); ++iterator)
{ {
@@ -195,14 +186,118 @@ void AdminMenu::viewStockLevels()
{ {
std::cout << std::left << std::setw(15) << item->getId() std::cout << std::left << std::setw(15) << item->getId()
<< std::setw(25) << item->getPartName() << std::setw(25) << item->getPartName()
<< std::setw(15) << item->getQuantity() << std::setw(10) << item->getQuantity()
<< std::setw(15) << item->getPrice() << std::setw(10) << item->getPrice()
<< std::endl; << std::endl;
} }
} }
} }
std::cout << "\n"; }
util::pressEnter();
/*
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*>
*/
static 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
*/
static 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
*/
static 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;
}
} }
/* /*
@@ -218,15 +313,13 @@ void AdminMenu::addInventoryItem()
int choice, quantity; int choice, quantity;
double price; double price;
std::string partName; std::string partName;
std::cout << "Add Inventory Item\n"; std::cout << "1. Add new item \n2. Add Quantity\nEnter your choice : ";
std::cout << "1. Add new item \n2. Restock Item\n\nEnter your choice : ";
util::read(choice); util::read(choice);
switch (choice) switch (choice)
{ {
case 1: case 1:
{ {
util::clear(); std::cout << "--------Enter Item Details----------\n";
std::cout << "Enter Item Details\n";
std::cout << "Part Name : "; std::cout << "Part Name : ";
util::read(partName); util::read(partName);
std::cout << "Quantity : "; std::cout << "Quantity : ";
@@ -234,21 +327,15 @@ void AdminMenu::addInventoryItem()
std::cout << "Price : "; std::cout << "Price : ";
util::read(price); util::read(price);
m_controller.addInventoryItem(partName, quantity, price); m_controller.addInventoryItem(partName, quantity, price);
std::cout << "\nNew Item " << partName << " added to the Inventory.\n\n"; std::cout << "New Item " << partName << " added to the Inventory.\n";
break; break;
} }
case 2: case 2:
{ {
util::clear();
std::cout << "Select Item to Restock\n";
auto inventoryItems = m_controller.getInventoryItems(); auto inventoryItems = m_controller.getInventoryItems();
addQuantityToItem(inventoryItems, m_controller); addQuantityToItem(inventoryItems, m_controller);
break; break;
} }
default:
{
std::cout << "\nEnter a valid choice.\n\n";
}
} }
util::pressEnter(); util::pressEnter();
} }
@@ -263,7 +350,6 @@ Return type: void
void AdminMenu::removeInventoryItem() void AdminMenu::removeInventoryItem()
{ {
util::clear(); util::clear();
std::cout << "Remove Inventory Item\n";
auto inventoryItems = m_controller.getInventoryItems(); auto inventoryItems = m_controller.getInventoryItems();
auto activeItems = filterActiveItems(inventoryItems); auto activeItems = filterActiveItems(inventoryItems);
int activeItemsSize = activeItems.getSize(); int activeItemsSize = activeItems.getSize();
@@ -283,7 +369,7 @@ void AdminMenu::removeInventoryItem()
util::pressEnter(); util::pressEnter();
return; return;
} }
const InventoryItem* selectedItem = activeItems.getValueAt(itemIndex - 1); const InventoryItem* selectedItem = inventoryItems.getValueAt(itemIndex - 1);
if (selectedItem != nullptr) if (selectedItem != nullptr)
{ {
if(selectedItem->getState() != util::State::INACTIVE) if(selectedItem->getState() != util::State::INACTIVE)
@@ -307,10 +393,8 @@ void AdminMenu::checkStockAvailability()
{ {
util::clear(); util::clear();
std::string itemId; std::string itemId;
std::cout << "Check Stock Availability \n"; std::cout << "Enter the Item Id : ";
std::cout << "Enter the Item ID : ";
util::read(itemId); util::read(itemId);
util::clear();
const InventoryItem* selectedItem = m_controller.getInventoryItem(itemId); const InventoryItem* selectedItem = m_controller.getInventoryItem(itemId);
if (selectedItem != nullptr) if (selectedItem != nullptr)
{ {
@@ -323,35 +407,126 @@ void AdminMenu::checkStockAvailability()
std::cout << "Quantity : " << selectedItem->getQuantity() << "\n"; std::cout << "Quantity : " << selectedItem->getQuantity() << "\n";
} }
} }
else
{
std::cout << "Item not Found" << std::endl;
}
util::pressEnter(); util::pressEnter();
} }
/* static bool listServiceBookings(util::Map<std::string, const ServiceBooking*>& currentBookings, int& bookingsSize, util::Map<int, const ServiceBooking*>& serviceBookingsMap)
Function: assignJob {
Description: Allows the admin to assign pending service bookings to available technicians. int currentIndex = 1;
Creates job cards for selected services. bool hasPendingService = false;
Parameters: std::cout << std::left
- None << std::setw(10) << "Index"
Returns: << std::setw(10) << "ID"
- void << std::setw(12) << "Status"
*/ << std::setw(12) << "CustID"
<< std::setw(20) << "Customer"
<< std::setw(15) << "VehicleNo"
<< std::setw(15) << "Brand"
<< std::setw(15) << "Model"
<< std::setw(20) << "Technician"
<< std::setw(15) << "TechID"
<< std::endl;
for (int iterator = 0; iterator < bookingsSize; iterator++)
{
const ServiceBooking* currentBooking = currentBookings.getValueAt(iterator);
if (currentBooking && currentBooking->getStatus() == util::ServiceJobStatus::PENDING)
{
hasPendingService = true;
std::cout << std::left
<< std::setw(10) << currentIndex
<< std::setw(10) << currentBooking->getId()
<< std::setw(12) << util::getServiceJobStatusString(currentBooking->getStatus())
<< std::setw(12) << currentBooking->getCustomerId()
<< std::setw(20) << currentBooking->getCustomer()->getName()
<< std::setw(15) << currentBooking->getVehicleNumber()
<< std::setw(15) << currentBooking->getVehicleBrand()
<< std::setw(15) << currentBooking->getVehicleModel()
<< std::setw(20) << (currentBooking->getAssignedTechnician() == nullptr ? "Null" : currentBooking->getAssignedTechnician()->getName())
<< std::setw(15) << (currentBooking->getAssignedTechnicianId().empty() ? "Null" : currentBooking->getAssignedTechnicianId())
<< std::endl;
serviceBookingsMap.insert(currentIndex++, currentBooking);
}
}
if (!hasPendingService)
{
std::cout << "No pending service available." << std::endl;
return false;
}
return true;
}
static const ServiceBooking* selectPendingServiceBookings(util::Map<int, const ServiceBooking*>& serviceBookingsMap)
{
int userInputIndex;
std::cout << "Enter a valid service index: ";
util::read(userInputIndex);
if (serviceBookingsMap.find(userInputIndex) != -1)
{
return serviceBookingsMap.getValueAt(userInputIndex);
}
else
{
std::cout << "Enter a valid index.";
return nullptr;
}
}
static void listAvailableTechnicians( util::Map<std::string, const User*> currentAvailableTechnicians, int numberOfTechnicians, util::Map<int, const User*>& currentAvailableTechniciansMap)
{
bool hasTechnicians = false;
int currentIndex = 1;
std::cout << std::left
<< std::setw(6) << "Index"
<< std::setw(15) << "Technician ID"
<< std::setw(20) << "Name"
<< std::endl;
for (int iterator = 0; iterator < numberOfTechnicians; iterator++)
{
const User* currentTechnician = currentAvailableTechnicians.getValueAt(iterator);
if (currentTechnician->getState() == util::State::INACTIVE)
{
continue;
}
hasTechnicians = true;
std::cout << std::left
<< std::setw(6) << currentIndex
<< std::setw(15) << currentTechnician->getId()
<< std::setw(20) << currentTechnician->getName()
<< std::endl;
currentAvailableTechniciansMap.insert(currentIndex++, currentTechnician);
}
if (!hasTechnicians)
{
std::cout << "No technicians currently available.";
}
}
static const User* selectTechnician(util::Map<int, const User*>& currentAvailableTechniciansMap)
{
int userInputIndex;
util::read(userInputIndex);
if (currentAvailableTechniciansMap.find(userInputIndex) != -1)
{
return currentAvailableTechniciansMap.getValueAt(userInputIndex);
}
else
{
std::cout << "Enter a valid index.";
return nullptr;
}
}
void AdminMenu::assignJob() void AdminMenu::assignJob()
{ {
util::clear(); util::clear();
std::cout << "Assign Job to Technician\n";
std::string selectedService; std::string selectedService;
bool hasPendingService = false; bool hasPendingService = false;
auto currentBookings = m_controller.getServiceBookings(); auto currentBookings = m_controller.getServiceBookings();
auto pendingServiceBookings = filterActiveServiceBookings(currentBookings);
auto availableTechnicians = m_controller.getUsers(util::UserType::TECHNICIAN); auto availableTechnicians = m_controller.getUsers(util::UserType::TECHNICIAN);
int bookingsSize = pendingServiceBookings.getSize(); int bookingsSize = currentBookings.getSize();
util::Map<int, const ServiceBooking*> serviceBookingsMap; util::Map<int, const ServiceBooking*> serviceBookingsMap;
util::Map<int, const User*> currentAvailableTechniciansMap; util::Map<int, const User*> currentAvailableTechniciansMap;
if (listServiceBookings(pendingServiceBookings, bookingsSize, serviceBookingsMap)) if (listServiceBookings(currentBookings, bookingsSize, serviceBookingsMap))
{ {
const ServiceBooking* selectedService = selectPendingServiceBookings(serviceBookingsMap); const ServiceBooking* selectedService = selectPendingServiceBookings(serviceBookingsMap);
if (selectedService) if (selectedService)
@@ -367,80 +542,158 @@ void AdminMenu::assignJob()
{ {
m_controller.createJobCard(selectedService->getId(), selectedTechnician->getId(), servicesInBooking.getValueAt(iterator)->getId()); m_controller.createJobCard(selectedService->getId(), selectedTechnician->getId(), servicesInBooking.getValueAt(iterator)->getId());
} }
std::cout << "Job card created for each service and technician successfully assigned.\n\n";
} }
} }
else else
{ {
std::cout << "No technicians are currently available.\n\n"; std::cout << "No technicians are currently available.";
} }
} }
} }
else
{ }
std::cout << "No pending service bookings available.\n\n";
} static void selectInventoryItems(util::Map<std::string, const InventoryItem*>& currentInventoryItems, util::Vector<std::string>& selectedInventoryItems)
util::pressEnter(); {
bool doRun = true, hasInventoryItems = false;
util::Map<int, const InventoryItem*> currentInventoryMap;
int currentIndex = 1;
int choice;
if (currentInventoryItems.getSize() == 0)
{
std::cout << "Inventory empty.";
}
while (doRun)
{
bool hasInventoryItems = false;
int currentIndex = 1;
currentInventoryMap.clear();
std::cout << std::left
<< std::setw(6) << "Index"
<< std::setw(12) << "Item ID"
<< std::setw(20) << "Part Name"
<< std::setw(10) << "Price"
<< std::setw(10) << "Quantity"
<< std::endl;
for (int iterator = 0; iterator < currentInventoryItems.getSize(); iterator++)
{
const InventoryItem* currentInventoryItem = currentInventoryItems.getValueAt(iterator);
if (currentInventoryItem->getState() == util::State::INACTIVE)
{
continue;
}
std::cout << std::left
<< std::setw(6) << currentIndex
<< std::setw(12) << currentInventoryItem->getId()
<< std::setw(20) << currentInventoryItem->getPartName()
<< std::setw(10) << currentInventoryItem->getPrice()
<< std::setw(10) << currentInventoryItem->getQuantity()
<< std::endl;
hasInventoryItems = true;
currentInventoryMap.insert(currentIndex++, currentInventoryItem);
}
if (!hasInventoryItems)
{
std::cout << "No items present in the inventory." << std::endl;
doRun = false;
break;
}
std::cout << "Select the item (Index) or enter -1 to exit: ";
util::read(choice);
if (choice == -1)
{
doRun = false;
}
else if (currentInventoryMap.find(choice) != -1)
{
selectedInventoryItems.push_back(currentInventoryMap.getValueAt(choice)->getId());
std::cout << "Item added successfully." << std::endl;
}
else
{
std::cout << "Enter a valid integer." << std::endl;
}
}
} }
/*
Function: createService
Description: Allows the admin to create a new service by selecting inventory items and specifying labor cost.
Parameters:
- None
Returns:
- void
*/
void AdminMenu::createService() void AdminMenu::createService()
{ {
util::clear(); util::clear();
std::cout << "Create Service\n";
std::string serviceName; std::string serviceName;
double labourCost; double labourCost;
std::cout << "Enter the service name: "; std::cout << "Enter the service name: ";
util::read(serviceName); util::read(serviceName);
util::Map<std::string, const InventoryItem*> currentInventoryItems = m_controller.getInventoryItems(); util::Map<std::string, const InventoryItem*> currentInventoryItems = m_controller.getInventoryItems();
util::Map<std::string, const InventoryItem*> activeInventoryItems = filterActiveItems(currentInventoryItems);
util::Vector<std::string> selectedInventoryItems; util::Vector<std::string> selectedInventoryItems;
selectInventoryItems(activeInventoryItems,selectedInventoryItems); selectInventoryItems(currentInventoryItems,selectedInventoryItems);
if (selectedInventoryItems.isEmpty()) std::cout << "Enter the labour cost: ";
{
util::pressEnter();
return;
}
std::cout << "\nEnter the labour cost: ";
util::read(labourCost); util::read(labourCost);
m_controller.createService(serviceName, selectedInventoryItems, labourCost); m_controller.createService(serviceName, selectedInventoryItems, labourCost);
std::cout << "\nService created sucessfully.\n\n"; std::cout << "Service created sucessfully.\n";
util::pressEnter(); }
static std::string selectServicesToRemove(util::Map<std::string, const Service*> currentServices)
{
util::Map<int, const Service*> currentServicesMap;
bool hasServices = false;
int currentIndex = 1, choice;
std::cout << std::left
<< std::setw(6) << "Index"
<< std::setw(12) << "Service ID"
<< std::setw(20) << "Name"
<< std::setw(10) << "Labor Cost"
<< std::endl;
for (int iterator = 0; iterator < currentServices.getSize(); iterator++)
{
const Service* currentService = currentServices.getValueAt(iterator);
if (currentService->getState() == util::State::INACTIVE)
{
continue;
}
std::cout << std::left
<< std::setw(6) << currentIndex
<< std::setw(12) << currentService->getId()
<< std::setw(20) << currentService->getName()
<< std::setw(10) << currentService->getLaborCost()
<< std::endl;
hasServices = true;
currentServicesMap.insert(currentIndex++, currentService);
}
if (!hasServices)
{
std::cout << "No services currently available." << std::endl;
return "";
}
std::cout << "Enter your choice: ";
util::read(choice);
if (currentServicesMap.find(choice) != -1)
{
return currentServicesMap.getValueAt(currentServicesMap.find(choice))->getId();
}
else
{
std::cout << "Invalid choice." << std::endl;
return "";
}
} }
/*
Function: removeService
Description: Allows the admin to remove an existing service by selecting from available services.
Parameters:
- None
Returns:
- void
*/
void AdminMenu::removeService() void AdminMenu::removeService()
{ {
util::clear(); util::clear();
std::cout << "Remove Service\n";
std::string selectedServiceID; std::string selectedServiceID;
util::Map<std::string, const Service*> currentServices = m_controller.getServices(); util::Map<std::string, const Service*> currentServices = m_controller.getServices();
util::Map<std::string, const Service*> currentActiveServices = filterActiveServices(currentServices); selectedServiceID = selectServicesToRemove(currentServices);
selectedServiceID = selectServicesToRemove(currentActiveServices);
if (selectedServiceID != "") if (selectedServiceID != "")
{ {
m_controller.removeService(selectedServiceID); m_controller.removeService(selectedServiceID);
std::cout << "Service removed successfully.\n\n"; std::cout << "Service removed sucessfully.";
} }
else else
{ {
std::cout << "Failed to remove service.\n\n"; std::cout << "Failed to remove service.";
} }
util::pressEnter();
} }
/* /*
@@ -453,40 +706,95 @@ void AdminMenu::addTechnician()
{ {
util::clear(); util::clear();
std::string username, name, password, email, phoneNumber; std::string username, name, password, email, phoneNumber;
std::cout << "Add Technician\n"; std::cout << std::left << std::setw(25) << "Enter Technician Username:";
std::cout << "Enter Technician Username: ";
util::read(username); util::read(username);
std::cout << "Enter Technician Name: "; std::cout << std::setw(25) << "Enter Technician Password:";
util::read(name);
std::cout << "Enter Technician Password: ";
util::read(password); util::read(password);
if(!util::isPasswordValid(password)) if(!util::isPasswordValid(password))
{ {
std::cout << "\nError: Password is invalid!\n\n"; std::cout << "Error: Password is invalid!";
util::pressEnter(); util::pressEnter();
return; return;
} }
std::cout << "Enter Technician Email: "; std::cout << std::left << std::setw(25) << "Enter Technician Name:";
util::read(name);
std::cout << std::setw(25) << "Enter Technician Email:";
util::read(email); util::read(email);
if(!util::isEmailValid(email)) if(!util::isEmailValid(email))
{ {
std::cout << "\nError: Email is invalid!\n\n"; std::cout << "Error: Email is invalid!";
util::pressEnter(); util::pressEnter();
return; return;
} }
std::cout << "Enter Technician Phone: "; std::cout << std::setw(25) << "Enter Technician Phone:";
util::read(phoneNumber); util::read(phoneNumber);
if(!util::isPhoneNumberValid(phoneNumber)) if(!util::isPhoneNumberValid(phoneNumber))
{ {
std::cout << "\nError: Phone Number is invalid!\n\n"; std::cout << "Error: Phone Number is invalid!";
util::pressEnter(); util::pressEnter();
return; return;
} }
m_controller.createTechnician(username, name, password, email, phoneNumber); m_controller.createTechnician(username, name, password, email, phoneNumber);
std::cout << "\nTechnician Added Successfully.\n\n"; std::cout << "\nTechnician Added Successfully.\n";
util::pressEnter(); util::pressEnter();
} }
/*
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*>
*/
static 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
*/
static 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: removeUser Function: removeUser
Description: Removes a selected active user (customer or technician) from the system. Description: Removes a selected active user (customer or technician) from the system.
@@ -500,7 +808,6 @@ void AdminMenu::removeUser()
auto listOfUsers = m_controller.getUsers(); auto listOfUsers = m_controller.getUsers();
auto listOfActiveUsers = filterActiveUsers(listOfUsers); auto listOfActiveUsers = filterActiveUsers(listOfUsers);
int activeUserCount = listOfActiveUsers.getSize(); int activeUserCount = listOfActiveUsers.getSize();
std::cout << "Remove User \n";
if (activeUserCount < 1) if (activeUserCount < 1)
{ {
std::cout << "No Active users." << std::endl; std::cout << "No Active users." << std::endl;
@@ -526,6 +833,55 @@ void AdminMenu::removeUser()
util::pressEnter(); util::pressEnter();
} }
/*
Function: selectServiceFromServices
Description: Displays active services and allows the admin to select one by index.
Parameter: const util::Map<std::string, const Service*>& services - list of services
Return type: const Service* - selected service
*/
static const Service* selectServiceFromServices(const util::Map<std::string, const Service*>& services)
{
util::Map<int, const Service*> activeServicesMap;
int currentIndex = 1;
int userInputIndex;
std::cout << std::left
<< std::setw(10) << "Index"
<< std::setw(15) << "Service ID"
<< std::setw(25) << "Service Name"
<< std::setw(15) << "Estimated Cost"
<< std::endl;
for (int index = 0; index < services.getSize(); index++)
{
const Service* currentService = services.getValueAt(index);
if (currentService->getState() != util::State::ACTIVE)
{
continue;
}
activeServicesMap.insert(currentIndex, currentService);
double partsCost = util::calculatePartsCost(currentService);
std::cout << std::left
<< std::setw(10) << currentIndex
<< std::setw(15) << currentService->getId()
<< std::setw(25) << currentService->getName()
<< std::setw(15) << (currentService->getLaborCost() + partsCost)
<< std::endl;
currentIndex++;
}
if (activeServicesMap.getSize() == 0)
{
std::cout << "No active services available." << std::endl;
return nullptr;
}
std::cout << "Enter service index: ";
util::read(userInputIndex);
if (activeServicesMap.find(userInputIndex) == -1)
{
std::cout << "Invalid service index." << std::endl;
return nullptr;
}
return activeServicesMap[userInputIndex];
}
/* /*
Function: createComboPackages Function: createComboPackages
Description: Creates a new combo package by selecting two active services and applying a discount. Description: Creates a new combo package by selecting two active services and applying a discount.
@@ -535,50 +891,20 @@ Return type: void
void AdminMenu::createComboPackages() void AdminMenu::createComboPackages()
{ {
util::clear(); util::clear();
std::cout << "Create Combo Packages\n";
auto serviceList = m_controller.getServices(); auto serviceList = m_controller.getServices();
auto activeServices = filterActiveServices(serviceList); const int numberOfServicesInPackage = 2;
int currentActiveServicesCount = activeServices.getSize();
const int NUMBER_OF_SERVICE_PER_PACKAGE = 2;
util::Vector<std::string> selectedServiceID; util::Vector<std::string> selectedServiceID;
for (int iterator = 0; iterator < NUMBER_OF_SERVICE_PER_PACKAGE; iterator++) for (int iterator = 0; iterator < numberOfServicesInPackage; iterator++)
{ {
const Service* chosenService = nullptr; const Service* chosenService = selectServiceFromServices(serviceList);
while (true) if (chosenService == nullptr)
{ {
chosenService = selectServiceFromServices(activeServices); std::cout << "Failed to create combo package!";
if (!chosenService) util::pressEnter();
{ return;
std::cout << "Failed to create combo package!\n\n";
util::pressEnter();
return;
}
bool alreadyChosen = false;
for (int iteratorOne = 0; iteratorOne < selectedServiceID.getSize(); iteratorOne++)
{
if (selectedServiceID[iteratorOne] == chosenService->getId())
{
alreadyChosen = true;
break;
}
}
if (alreadyChosen)
{
if (currentActiveServicesCount < 2)
{
break;
}
std::cout << "Service already selected. Please choose a different one." << std::endl;
continue;
}
selectedServiceID.push_back(chosenService->getId());
break;
} }
if (currentActiveServicesCount < 2) selectedServiceID.push_back(chosenService->getId());
{ util::clear();
std::cout << "All the available services selected\n\n";
break;
}
} }
std::string packageName; std::string packageName;
double discountPercentage; double discountPercentage;
@@ -597,6 +923,81 @@ void AdminMenu::createComboPackages()
util::pressEnter(); util::pressEnter();
} }
/*
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
*/
static 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
*/
static 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 "";
}
}
/* /*
Function: removeComboPackage Function: removeComboPackage
Description: Removes a selected combo package from the system. Description: Removes a selected combo package from the system.
@@ -606,17 +1007,16 @@ Return type: void
void AdminMenu::removeComboPackage() void AdminMenu::removeComboPackage()
{ {
util::clear(); util::clear();
std::cout << "Remove Combo Package\n";
util::Map<std::string, const ComboPackage*> currentComboPackages = m_controller.getComboPackages(); util::Map<std::string, const ComboPackage*> currentComboPackages = m_controller.getComboPackages();
std::string selectedComboPackageID = selectComboPackage(currentComboPackages); std::string selectedComboPackageID = selectComboPackage(currentComboPackages);
if (!selectedComboPackageID.empty()) if (selectedComboPackageID != "")
{ {
m_controller.removeComboPackage(selectedComboPackageID); m_controller.removeComboPackage(selectedComboPackageID);
std::cout << "Combo Package removed successfully.\n\n"; std::cout << "Combo Package removed successfully.\n";
} }
else else
{ {
std::cout << "Combo package removal failed.\n\n"; std::cout << "Combo package removal failed.\n";
} }
util::pressEnter(); util::pressEnter();
} }
@@ -6,7 +6,6 @@ Description: Header file declaring the AdminMenu class, which provides
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#pragma once #pragma once
#include "Controller.h" #include "Controller.h"
@@ -1,36 +1,41 @@
/* /*
File: CustomerMenu.cpp File: CustomerMenu.cpp
Description: Implementation file containing the method definitions of the Description: Implements the CustomerMenu class which provides the customers console interface
CustomerMenu class, including menu handling, service selection, in the Vehicle Service Management System. Handles menu display, user input, and
combo package booking, profile updates, and password management. customer-specific operations such as booking services, viewing history, managing payments,
invoices, and notifications.
Author: Trenser Author: Trenser
Date:19-May-2026 Date: 19-May-2026
*/ */
#include <iomanip> #include <iomanip>
#include <iostream>
#include "ComboPackage.h" #include "ComboPackage.h"
#include "CustomerMenu.h" #include "CustomerMenu.h"
#include "MenuHelper.h"
#include "Enums.h" #include "Enums.h"
#include "InputHelper.h" #include "InputHelper.h"
#include "OutputHelper.h"
#include "InventoryItem.h" #include "InventoryItem.h"
#include "Invoice.h" #include "Invoice.h"
#include "Map.h" #include "Map.h"
#include "MenuHelper.h"
#include "OutputHelper.h"
#include "Service.h" #include "Service.h"
#include "ServiceBooking.h" #include "ServiceBooking.h"
#include "Timestamp.h" #include "Timestamp.h"
#include "User.h" #include "User.h"
#include "Utility.h"
#include "Validator.h" #include "Validator.h"
#include "Vector.h" #include "Vector.h"
/* /*
Function: showMenu Function: showMenu
Description: Displays the customer menu and handles user input until logout is selected. Description: Displays the customer menu in a loop until the user chooses to logout.
Parameter: None Handles exceptions and ensures smooth user interaction.
Return type: void Parameters:
- None
Returns:
- void
*/ */
void CustomerMenu::showMenu() void CustomerMenu::showMenu()
{ {
while (true) while (true)
@@ -65,12 +70,6 @@ void CustomerMenu::showMenu()
} }
} }
/*
Function: handleOperation
Description: Executes the corresponding customer operation based on the selected menu choice.
Parameter: int choice - selected menu option
Return type: bool - true if menu continues, false if logout
*/
bool CustomerMenu::handleOperation(int choice) bool CustomerMenu::handleOperation(int choice)
{ {
switch (choice) switch (choice)
@@ -112,44 +111,37 @@ bool CustomerMenu::handleOperation(int choice)
return true; return true;
} }
/*
Function: logout
Description: Logs out the currently authenticated customer user.
Parameter: None
Return type: void
*/
void CustomerMenu::logout() void CustomerMenu::logout()
{ {
m_controller.logout(); m_controller.logout();
} }
/*
Function: changePassword
Description: Allows the customer to change their password after validation.
Parameter: None
Return type: void
*/
void CustomerMenu::changePassword() void CustomerMenu::changePassword()
{ {
changePasswordHelper(m_controller); std::string newPassword;
util::clear();
std::cout << "Enter new password: ";
util::read(newPassword);
m_controller.changePassword(newPassword);
if (!util::isPasswordValid(newPassword))
{
std::cout << "Error: Password is not strong enough!";
util::pressEnter();
return;
}
std::cout << "Password changed successfully";
util::pressEnter();
} }
/*
Function: updateDetails
Description: Allows the customer to update their email and phone number after validation.
Parameter: None
Return type: void
*/
void CustomerMenu::updateDetails() void CustomerMenu::updateDetails()
{ {
std::string email, phone; std::string email, phone;
util::clear(); util::clear();
std::cout << "Update Details\n";
std::cout << "Enter new email: "; std::cout << "Enter new email: ";
util::read(email); util::read(email);
if (!util::isEmailValid(email)) if (!util::isEmailValid(email))
{ {
std::cout << "Error: Email is invalid!\n"; std::cout << "Error: Email is invalid!";
util::pressEnter(); util::pressEnter();
return; return;
} }
@@ -157,35 +149,64 @@ void CustomerMenu::updateDetails()
util::read(phone); util::read(phone);
if (!util::isPhoneNumberValid(phone)) if (!util::isPhoneNumberValid(phone))
{ {
std::cout << "Error: Phone number is invalid!\n"; std::cout << "Error: Phone number is invalid!";
util::pressEnter(); util::pressEnter();
return; return;
} }
m_controller.updateUserDetails(email, phone); m_controller.updateUserDetails(email, phone);
std::cout << "Profile details updated successfully\n"; std::cout << "Profile details updated successfully";
util::pressEnter(); util::pressEnter();
} }
/* static const Service* selectServiceFromServices(const util::Map<std::string, const Service*>& services)
Function: selectService {
Description: Allows the customer to select a service, provide vehicle details, util::Map<int, const Service*> activeServicesMap;
and book the service through the controller. int currentIndex = 1;
Parameter: None int userInputIndex;
Return type: void std::cout << std::left
*/ << std::setw(10) << "Index"
<< std::setw(15) << "Service ID"
<< std::setw(25) << "Service Name"
<< std::setw(15) << "Estimated Cost"
<< std::endl;
for (int index = 0; index < services.getSize(); index++)
{
const Service* currentService = services.getValueAt(index);
if (currentService->getState() != util::State::ACTIVE)
{
continue;
}
activeServicesMap.insert(currentIndex, currentService);
double partsCost = util::calculatePartsCost(currentService);
std::cout << std::left
<< std::setw(10) << currentIndex
<< std::setw(15) << currentService->getId()
<< std::setw(25) << currentService->getName()
<< std::setw(15) << (currentService->getLaborCost() + partsCost)
<< std::endl;
currentIndex++;
}
if (activeServicesMap.getSize() == 0)
{
std::cout << "No active services available." << std::endl;
return nullptr;
}
std::cout << "Enter service index: ";
util::read(userInputIndex);
if (activeServicesMap.find(userInputIndex) == -1)
{
std::cout << "Invalid service index." << std::endl;
return nullptr;
}
return activeServicesMap[userInputIndex];
}
void CustomerMenu::selectService() void CustomerMenu::selectService()
{ {
std::string vehicleNumber, vehicleBrand, vehicleModel; std::string vehicleNumber, vehicleBrand, vehicleModel;
util::clear();
std::cout << "Select a Service\n";
auto services = m_controller.getServices(); auto services = m_controller.getServices();
if (services.isEmpty())
{
std::cout << "No services available!";
util::pressEnter();
return;
}
util::Vector<std::string> selectedServices; util::Vector<std::string> selectedServices;
util::clear();
const Service* selectedService = selectServiceFromServices(services); const Service* selectedService = selectServiceFromServices(services);
if (selectedService == nullptr) if (selectedService == nullptr)
{ {
@@ -195,7 +216,6 @@ void CustomerMenu::selectService()
} }
selectedServices.push_back(selectedService->getId()); selectedServices.push_back(selectedService->getId());
util::clear(); util::clear();
std::cout << "Enter Vehicle Details\n";
std::cout << "Enter vehicle number: "; std::cout << "Enter vehicle number: ";
util::read(vehicleNumber); util::read(vehicleNumber);
std::cout << "Enter vehicle brand: "; std::cout << "Enter vehicle brand: ";
@@ -207,37 +227,61 @@ void CustomerMenu::selectService()
util::pressEnter(); util::pressEnter();
} }
/* static const ComboPackage* selectComboPackageFromPackages(const util::Map<std::string, const ComboPackage*>& comboPackages)
Function: selectComboPackage {
Description: Allows the customer to select a combo package, provide vehicle details, util::Map<int, const ComboPackage*> activeComboPackages;
and book the package through the controller. int currentIndex = 1;
Parameter: None int userInputIndex;
Return type: void std::cout << std::left
*/ << std::setw(10) << "Index"
<< std::setw(15) << "Combo Package ID"
<< std::setw(15) << "Combo Package Name"
<< std::setw(15) << "Estimate Cost"
<< std::endl;
for (int index = 0; index < comboPackages.getSize(); index++)
{
const ComboPackage* currentComboPackage = comboPackages.getValueAt(index);
if (currentComboPackage->getState() != util::State::ACTIVE)
{
continue;
}
activeComboPackages.insert(currentIndex, currentComboPackage);
std::cout << std::left
<< std::setw(10) << currentIndex
<< std::setw(15) << currentComboPackage->getId()
<< std::setw(25) << currentComboPackage->getPackageName()
<< std::setw(15) << util::calculateComboServiceEstimatedCost(currentComboPackage)
<< std::endl;
currentIndex++;
}
if (activeComboPackages.getSize() == 0)
{
std::cout << "No active combo packages available." << std::endl;
return nullptr;
}
std::cout << "Enter combo package index: ";
util::read(userInputIndex);
if (activeComboPackages.find(userInputIndex) == -1)
{
std::cout << "Invalid combo package index." << std::endl;
return nullptr;
}
return activeComboPackages[userInputIndex];
}
void CustomerMenu::selectComboPackage() void CustomerMenu::selectComboPackage()
{ {
std::string vehicleNumber, vehicleBrand, vehicleModel; std::string vehicleNumber, vehicleBrand, vehicleModel;
util::clear();
std::cout << "Select a Combo Package\n";
auto comboPackages = m_controller.getComboPackages(); auto comboPackages = m_controller.getComboPackages();
util::Map<std::string, const ComboPackage*> activeComboPackages = filterComboPackages(comboPackages); util::clear();
if (activeComboPackages.isEmpty()) const ComboPackage* selectedComboPackage = selectComboPackageFromPackages(comboPackages);
{
std::cout << "No combo packages available!\n\n";
util::pressEnter();
return;
}
const ComboPackage* selectedComboPackage = selectComboPackageFromPackages(activeComboPackages);
if (selectedComboPackage == nullptr) if (selectedComboPackage == nullptr)
{ {
std::cout << "Failed to book combo package!\n\n"; std::cout << "Failed to book combo package!";
util::pressEnter(); util::pressEnter();
return; return;
} }
std::cout << "Combo Package selected\n";
util::pressEnter();
util::clear(); util::clear();
std::cout << "Enter the vehicle details\n";
std::cout << "Enter vehicle number: "; std::cout << "Enter vehicle number: ";
util::read(vehicleNumber); util::read(vehicleNumber);
std::cout << "Enter vehicle brand: "; std::cout << "Enter vehicle brand: ";
@@ -245,37 +289,27 @@ void CustomerMenu::selectComboPackage()
std::cout << "Enter vehicle model: "; std::cout << "Enter vehicle model: ";
util::read(vehicleModel); util::read(vehicleModel);
m_controller.purchaseComboPackage(selectedComboPackage->getId(), vehicleNumber, vehicleBrand, vehicleModel); m_controller.purchaseComboPackage(selectedComboPackage->getId(), vehicleNumber, vehicleBrand, vehicleModel);
std::cout << "Combo Package has been booked successfully\n\n"; std::cout << "Combo Package has been booked successfully";
util::pressEnter(); util::pressEnter();
} }
/*
Function: viewServiceHistory
Description: Displays the customers past service bookings in tabular format,
including booking ID, technician, vehicle details, discount percentage, and status.
Parameters:
- None
Returns:
- void
*/
void CustomerMenu::viewServiceHistory() void CustomerMenu::viewServiceHistory()
{ {
util::clear(); util::clear();
bool hasServiceHistory = false; bool hasServiceHistory = false;
const User* currentUser = m_controller.getAuthenticatedUser(); const User* currentUser = m_controller.getAuthenticatedUser();
std::string currentUserID = currentUser->getId(); std::string currentUserID = currentUser->getId();
util::Map<std::string, const ServiceBooking*> serviceBookingsByCurrentUser = m_controller.getServiceBookingsByUser(currentUserID); util::Map<std::string, const ServiceBooking*> serviceBookingsByCurrentUser = m_controller.getServiceBookingsByUser(currentUserID);
std::cout << "View Service History" << std::endl;
if (serviceBookingsByCurrentUser.getSize() != 0) if (serviceBookingsByCurrentUser.getSize() != 0)
{ {
std::cout << std::left std::cout << std::left
<< std::setw(15) << "Booking ID" << std::setw(12) << "Booking ID"
<< std::setw(20) << "Technician" << std::setw(20) << "Technician"
<< std::setw(20) << "Vehicle Brand" << std::setw(15) << "Vehicle Brand"
<< std::setw(20) << "Vehicle Number" << std::setw(15) << "Vehicle Number"
<< std::setw(20) << "Vehicle Model" << std::setw(15) << "Vehicle Model"
<< std::setw(20) << "Discount %" << std::setw(10) << "Discount %"
<< std::setw(20) << "Status" << std::setw(12) << "Status"
<< std::endl; << std::endl;
for (int iterator = 0; iterator < serviceBookingsByCurrentUser.getSize(); iterator++) for (int iterator = 0; iterator < serviceBookingsByCurrentUser.getSize(); iterator++)
{ {
@@ -284,13 +318,13 @@ void CustomerMenu::viewServiceHistory()
? "Not Assigned" ? "Not Assigned"
: currentBooking->getAssignedTechnician()->getName(); : currentBooking->getAssignedTechnician()->getName();
std::cout << std::left std::cout << std::left
<< std::setw(15) << currentBooking->getId() << std::setw(12) << currentBooking->getId()
<< std::setw(20) << technicianName << std::setw(20) << technicianName
<< std::setw(20) << currentBooking->getVehicleBrand() << std::setw(15) << currentBooking->getVehicleBrand()
<< std::setw(20) << currentBooking->getVehicleNumber() << std::setw(15) << currentBooking->getVehicleNumber()
<< std::setw(20) << currentBooking->getVehicleModel() << std::setw(15) << currentBooking->getVehicleModel()
<< std::setw(20) << currentBooking->getDiscountPercentage() << std::setw(10) << currentBooking->getDiscountPercentage()
<< std::setw(20) << util::getServiceJobStatusString(currentBooking->getStatus()) << std::setw(12) << util::getServiceJobStatusString(currentBooking->getStatus())
<< std::endl; << std::endl;
hasServiceHistory = true; hasServiceHistory = true;
} }
@@ -299,73 +333,155 @@ void CustomerMenu::viewServiceHistory()
{ {
std::cout << "No history available." << std::endl; std::cout << "No history available." << std::endl;
} }
util::pressEnter();
} }
/* static std::string selectInvoiceFromUserForPayment(const util::Map<std::string, const Invoice*>& currentInvoices)
Function: completePayments {
Description: Allows the customer to complete pending payments for invoices. int currentIndex = 1, choice;
Validates invoice selection and payment mode before completing payment. util::Map<int, const Invoice*> pendingInvoicesForPayment;
Parameters: std::cout << std::left
- None << std::setw(6) << "Index"
Returns: << std::setw(12) << "BookingID"
- void << std::setw(15) << "VehicleBrand"
*/ << std::setw(15) << "VehicleNumber"
<< std::setw(12) << "TechID"
<< std::setw(20) << "TechnicianName"
<< std::setw(10) << "Discount(%)"
<< std::setw(12) << "TotalAmount"
<< std::setw(20) << "InvoiceDate"
<< std::endl;
for (int iterator = 0; iterator < currentInvoices.getSize(); iterator++)
{
const Invoice* currentInvoice = currentInvoices.getValueAt(iterator);
if (currentInvoice && currentInvoice->getStatus() == util::PaymentStatus::PENDING)
{
std::cout << std::left
<< std::setw(6) << currentIndex
<< std::setw(12) << currentInvoice->getBookingId()
<< std::setw(15) << currentInvoice->getBooking()->getVehicleBrand()
<< std::setw(15) << currentInvoice->getBooking()->getVehicleNumber()
<< std::setw(12) << currentInvoice->getBooking()->getAssignedTechnician()->getId()
<< std::setw(20) << currentInvoice->getBooking()->getAssignedTechnician()->getName()
<< std::setw(10) << currentInvoice->getDiscountPercentage()
<< std::setw(12) << currentInvoice->getTotalAmount()
<< std::setw(20) << currentInvoice->getInvoiceDate().toString()
<< std::endl;
pendingInvoicesForPayment.insert(currentIndex++, currentInvoice);
}
}
if (pendingInvoicesForPayment.getSize() == 0)
{
std::cout << "No pending invoices available for payment.\n";
return "";
}
std::cout << "Select the Invoice to pay (Index): ";
util::read(choice);
int selectedIndex = pendingInvoicesForPayment.find(choice);
if (selectedIndex != -1)
{
const Invoice* selectedInvoice = pendingInvoicesForPayment.getValueAt(selectedIndex);
return selectedInvoice->getId();
}
else
{
std::cout << "Invalid choice.\n";
return "";
}
}
static util::PaymentMode selectPaymentMode()
{
int choice;
std::cout << "Enter the payment Mode\n1.OFFLINE\n2.ONLINE\nChoice: ";
util::read(choice);
if (choice == 1)
{
std::cout << "Offline mode selected.\n";
return util::PaymentMode::OFFLINE;
}
else if (choice == 2)
{
std::cout << "Online mode selected.\n";
return util::PaymentMode::ONLINE;
}
else
{
std::cout << "Invalid choice, Offline mode selected.\n";
return util::PaymentMode::OFFLINE;
}
}
void CustomerMenu::completePayments() void CustomerMenu::completePayments()
{ {
util::clear(); util::clear();
std::cout << "Complete Payments\n";
util::Map<std::string, const Invoice*> currentInvoices = m_controller.getInvoicesByUser(); util::Map<std::string, const Invoice*> currentInvoices = m_controller.getInvoicesByUser();
if (currentInvoices.isEmpty())
{
std::cout << "No pending invoices available for payment.\n";
util::pressEnter();
return;
}
bool hasPending = false;
for (int index = 0; index < currentInvoices.getSize(); ++index)
{
const Invoice* invoice = currentInvoices.getValueAt(index);
if (invoice && invoice->getStatus() == util::PaymentStatus::PENDING)
{
hasPending = true;
break;
}
}
if (!hasPending)
{
std::cout << "No pending invoices available for payment.\n";
util::pressEnter();
return;
}
std::string selectedID = selectInvoiceFromUserForPayment(currentInvoices); std::string selectedID = selectInvoiceFromUserForPayment(currentInvoices);
if (selectedID == "") if (selectedID == "")
{ {
std::cout << "Payment failed.\n"; std::cout << "Payment failed.\n";
util::pressEnter();
return; return;
} }
util::PaymentMode paymentMode = selectPaymentMode(); util::PaymentMode paymentMode = selectPaymentMode();
m_controller.completePayment(selectedID, paymentMode); m_controller.completePayment(selectedID, paymentMode);
std::cout << "Payment completed successfully.\n"; std::cout << "Payment completed successfully.\n";
util::pressEnter();
} }
/* static void displayInvoices(util::Map<std::string, const Invoice*> currentUserInvoices)
Function: viewInvoices {
Description: Displays invoices associated with the customer by calling displayInvoices. if (currentUserInvoices.getSize() == 0)
Parameters: {
- None std::cout << "No invoices found for this account." << std::endl;
Returns: util::pressEnter();
- void return;
*/ }
else
{
for (int index = 0; index < currentUserInvoices.getSize(); index++)
{
const Invoice* currentInvoice = currentUserInvoices.getValueAt(index);
if (currentInvoice)
{
std::cout << "\nInvoice Details\n";
std::cout << "Booking ID: " << currentInvoice->getBookingId() << std::endl;
std::cout << "Vehicle Brand: " << currentInvoice->getBooking()->getVehicleBrand() << std::endl;
std::cout << "Vehicle Number: " << currentInvoice->getBooking()->getVehicleNumber() << std::endl;
std::cout << "Technician ID: " << currentInvoice->getBooking()->getAssignedTechnician()->getId() << std::endl;
std::cout << "Technician Name: " << currentInvoice->getBooking()->getAssignedTechnician()->getName() << std::endl;
std::cout << "Discount(%): " << currentInvoice->getDiscountPercentage() << std::endl;
std::cout << "Total Amount: " << currentInvoice->getTotalAmount() << std::endl;
std::cout << "Invoice Date: " << currentInvoice->getInvoiceDate().toString() << std::endl;
std::cout << "Payment Status: " << util::getPaymentStatusString(currentInvoice->getStatus()) << std::endl;
auto inventoryItemsInInvoice = currentInvoice->getParts();
std::cout << "\nItems Used:\n";
std::cout << std::left
<< std::setw(20) << "ItemName"
<< std::setw(10) << "Quantity"
<< std::setw(10) << "Price"
<< std::endl;
std::cout << std::string(40, '-') << std::endl;
for (int iterator = 0; iterator < inventoryItemsInInvoice.getSize(); iterator++)
{
InventoryItem* currentItem = inventoryItemsInInvoice.getValueAt(iterator);
std::cout << std::left
<< std::setw(20) << currentItem->getPartName()
<< std::setw(10) << currentItem->getQuantity()
<< std::setw(10) << currentItem->getPrice()
<< std::endl;
}
}
else
{
throw std::runtime_error("Null invoice encountered while displaying invoices.");
}
}
}
}
void CustomerMenu::viewInvoices() void CustomerMenu::viewInvoices()
{ {
util::clear(); util::clear();
std::cout << "View Invoices\n";
util::Map<std::string, const Invoice*> currentUserInvoices = m_controller.getInvoicesByUser(); util::Map<std::string, const Invoice*> currentUserInvoices = m_controller.getInvoicesByUser();
displayInvoices(currentUserInvoices); displayInvoices(currentUserInvoices);
util::pressEnter();
} }
/* /*
@@ -381,6 +497,38 @@ void CustomerMenu::viewNotifications()
viewAndDeleteNotification(m_controller); viewAndDeleteNotification(m_controller);
} }
/*
Function: getNotificationPreference (static helper)
Description: Helper function to configure notification preferences for a specific service.
Parameters:
- serviceName: Name of the service for which notifications are being configured.
Returns:
- bool: True if notifications are enabled, False if disabled.
*/
static bool getNotificationPreference(const std::string& serviceName)
{
int choice;
while (true)
{
util::clear();
std::cout << " Configure Notification Preferences\n";
std::cout << "\n" << serviceName << " Notifications\n";
std::cout << "1. Enable Notifications\n";
std::cout << "2. Disable Notifications\n";
std::cout << "Enter your choice: ";
util::read(choice);
if (choice == 1)
{
return true;
}
if (choice == 2)
{
return false;
}
std::cout << "\nInvalid choice. Please enter 1 or 2.\n";
util::pressEnter();
}
}
/* /*
Function: configureNotifications Function: configureNotifications
@@ -398,4 +546,4 @@ void CustomerMenu::configureNotifications()
util::clear(); util::clear();
std::cout << "Notification preferences updated successfully.\n"; std::cout << "Notification preferences updated successfully.\n";
util::pressEnter(); util::pressEnter();
} }
@@ -1,11 +1,10 @@
/* /*
File: CustomerMenu.h File: CustomerMenu.h
Description: Header file declaring the CustomerMenu class, which provides Description: Declares the CustomerMenu class which provides the customer-facing console menu in the Vehicle Service Management System.
customer operations such as selecting services, booking combo Supports operations such as account management, service selection, combo package booking, viewing service history,
packages, updating profile details, managing payments, viewing handling payments and invoices, and managing notifications.
invoices, and configuring notifications.
Author: Trenser Author: Trenser
Date:19-May-2026 Date: 19-May-2026
*/ */
#pragma once #pragma once
File diff suppressed because it is too large Load Diff
@@ -7,6 +7,7 @@ Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#include <iomanip>
#include "Enums.h" #include "Enums.h"
#include "InputHelper.h" #include "InputHelper.h"
#include "JobCard.h" #include "JobCard.h"
@@ -82,28 +83,69 @@ bool TechnicianMenu::handleOperation(int choice)
return true; return true;
} }
/* static std::string selectJobCardToComplete(util::Map<std::string, const JobCard*>& assignedJobCards, util::Map<int, const JobCard*>& incompleteJobCards)
Function: completeJob {
Description: Allows the technician to mark a selected job card as completed. int currentIndex = 1;
Validates selection and updates job status through the controller. int choice;
Parameters: bool hasIncompleteJobCard = false;
- None std::cout << std::left
Returns: << std::setw(6) << "Index"
- void << std::setw(12) << "BookingID"
*/ << std::setw(12) << "JobID"
<< std::setw(20) << "ServiceName"
<< std::setw(12) << "ServiceID"
<< std::endl;
for (int iterator = 0; iterator < assignedJobCards.getSize(); iterator++)
{
const JobCard* currentJobCard = assignedJobCards.getValueAt(iterator);
if (currentJobCard && (currentJobCard->getStatus() == util::ServiceJobStatus::STARTED))
{
std::cout << std::left << std::setw(6) << currentIndex
<< std::setw(12) << currentJobCard->getBookingId()
<< std::setw(12) << currentJobCard->getId()
<< std::setw(20) << currentJobCard->getService()->getName()
<< std::setw(12) << currentJobCard->getServiceId()
<< std::endl;
hasIncompleteJobCard = true;
incompleteJobCards.insert(currentIndex++, currentJobCard);
}
}
if (!hasIncompleteJobCard)
{
std::cout << "No pending jobs are present.\n";
return "";
}
std::cout << "Select the Job Card to complete (Index): ";
util::read(choice);
int selectedJobCardIndex = incompleteJobCards.find(choice);
if (selectedJobCardIndex != -1)
{
const JobCard* selectedJobCard = incompleteJobCards.getValueAt(selectedJobCardIndex);
return selectedJobCard->getId();
}
else
{
std::cout << "Invalid choice.\n";
return "";
}
}
void TechnicianMenu::completeJob() void TechnicianMenu::completeJob()
{ {
util::clear();
std::cout << "Complete Job\n";
util::Map<std::string, const JobCard*> assignedJobCards = m_controller.getJobCardsByUser(); util::Map<std::string, const JobCard*> assignedJobCards = m_controller.getJobCardsByUser();
util::Map<std::string, const JobCard*> startedJobCards = filterStartedJobCards(assignedJobCards); util::Map<int, const JobCard*> incompleteJobCards;
std::string selectedJobID = selectJobCardToComplete(startedJobCards); std::cout << "Jobs to be completed.\n";
if (!selectedJobID.empty()) std::string selectedJobID = selectJobCardToComplete(assignedJobCards, incompleteJobCards);
if (selectedJobID == "")
{
std::cout << "Failed to complete the job.\n";
}
else
{ {
m_controller.completeJob(selectedJobID); m_controller.completeJob(selectedJobID);
std::cout << "\nJob marked as completed.\n\n"; std::cout << "Job marked as completed.\n";
} }
util::pressEnter();
} }
/* /*
@@ -127,7 +169,7 @@ Return type: void
*/ */
void TechnicianMenu::logout() void TechnicianMenu::logout()
{ {
m_controller.logout(); m_controller.logout();
} }
/* /*
@@ -136,8 +178,23 @@ Description: Allows the technician to change their password after validation.
Parameter: None Parameter: None
Return type: void Return type: void
*/ */
void TechnicianMenu::changePassword() void TechnicianMenu::changePassword()
{ {
changePasswordHelper(m_controller); std::string newPassword;
} while (true)
{
util::clear();
std::cout << "Enter new password: ";
util::read(newPassword);
if (!util::isPasswordValid(newPassword))
{
std::cout << "Error: Password is not strong enough!\n";
util::pressEnter();
continue;
}
m_controller.changePassword(newPassword);
std::cout << "Password changed successfully\n";
util::pressEnter();
break;
}
}
@@ -6,7 +6,6 @@ Description: Header file declaring the TechnicianMenu class, which provides
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#pragma once #pragma once
#include "Controller.h" #include "Controller.h"
@@ -6,14 +6,11 @@ Description: Implementation file containing the method definitions of the
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#include "UserInterface.h"
#include <iostream>
#include <stdexcept>
#include "Enums.h" #include "Enums.h"
#include "InputHelper.h" #include "InputHelper.h"
#include "OutputHelper.h" #include "OutputHelper.h"
#include "User.h" #include "User.h"
#include "UserInterface.h"
#include "Validator.h" #include "Validator.h"
/* /*
@@ -25,44 +22,29 @@ Return type: void
*/ */
void UserInterface::run() void UserInterface::run()
{ {
try m_controller.loadSystemData();
m_controller.runSystemChecks();
bool isMenuActive = true;
while (isMenuActive)
{ {
m_controller.loadSystemData(); try
m_controller.runSystemChecks();
bool isMenuActive = true;
while (isMenuActive)
{ {
try int choice;
util::clear();
std::cout << "Vehicle Service System\n1. Login\n2. Register Customer\n3. Exit\nEnter your Choice: ";
util::read(choice);
if (!handleOperation(choice))
{ {
int choice; isMenuActive = false;
util::clear();
std::cout << "Vehicle Service System\n1. Login\n2. Register Customer\n3. Exit\nEnter your Choice: ";
util::read(choice);
if (!handleOperation(choice))
{
isMenuActive = false;
}
}
catch (const std::exception& e)
{
std::cout << "Exception: " << e.what() << std::endl;
util::pressEnter();
} }
} }
m_controller.saveSystemData(); catch (const std::exception& e)
} {
catch (const std::invalid_argument& exception) std::cout << "Exception: " << e.what() << std::endl;
{ util::pressEnter();
std::cout << "Exception: Invalid Argument: " << exception.what() << std::endl; }
}
catch (const std::exception& exception)
{
std::cout << "Exception: " << exception.what() << std::endl;
}
catch (...)
{
std::cout << "Unknown error occurred." << std::endl;
} }
m_controller.saveSystemData();
} }
/* /*
@@ -102,7 +84,6 @@ void UserInterface::login()
{ {
std::string username, password; std::string username, password;
util::clear(); util::clear();
std::cout << "Login\n";
std::cout << "Enter username: "; std::cout << "Enter username: ";
util::read(username); util::read(username);
std::cout << "Enter password: "; std::cout << "Enter password: ";
@@ -110,7 +91,7 @@ void UserInterface::login()
if (m_controller.login(username, password)) if (m_controller.login(username, password))
{ {
const User* authenticatedUser = m_controller.getAuthenticatedUser(); const User* authenticatedUser = m_controller.getAuthenticatedUser();
if (authenticatedUser && authenticatedUser->getState() != util::State::INACTIVE) if (authenticatedUser != nullptr)
{ {
switch (authenticatedUser->getUserType()) switch (authenticatedUser->getUserType())
{ {
@@ -128,32 +109,25 @@ void UserInterface::login()
break; break;
} }
} }
else if (authenticatedUser && authenticatedUser->getState() == util::State::INACTIVE)
{
std::cout << "\nError: Your account has been disabled. Please contact your Administrator.";
util::pressEnter();
}
} }
else else
{ {
std::cout << "\nError: Invalid Username or Password"; std::cout << "\nError: Invalid Username or Password";
util::pressEnter();
} }
} }
/* /*
Function: registerCustomer Function: registerCustomer
Description: Registers a new customer by collecting and validating details such as Description: Handles the registration process for new customers.
username, name, email, password, and phone number. Delegates creation Parameters:
to the controller. - None
Parameter: None Returns:
Return type: void - void
*/ */
void UserInterface::registerCustomer() void UserInterface::registerCustomer()
{ {
std::string username, name, email, phone, password; std::string username, name, email, phone, password;
util::clear(); util::clear();
std::cout << "Register Customer\n";
std::cout << "Enter username: "; std::cout << "Enter username: ";
util::read(username); util::read(username);
std::cout << "Enter name: "; std::cout << "Enter name: ";
@@ -7,7 +7,6 @@ Description: Header file declaring the UserInterface class, which provides
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#pragma once #pragma once
#include "Controller.h" #include "Controller.h"
#include "AdminMenu.h" #include "AdminMenu.h"