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
54 changed files with 2263 additions and 6062 deletions
@@ -102,7 +102,7 @@
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(ProjectDir)models;$(ProjectDir)controllers;$(ProjectDir)factories;$(ProjectDir)views;$(ProjectDir)services;$(ProjectDir)utilities;$(ProjectDir)core\patterns;$(ProjectDir)datastores;$(ProjectDir)datastores\sharedmemory;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(ProjectDir)models;$(ProjectDir)controllers;$(ProjectDir)factories;$(ProjectDir)views;$(ProjectDir)services;$(ProjectDir)utilities;$(ProjectDir)core\patterns;$(ProjectDir)datastores;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
@@ -117,7 +117,7 @@
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(ProjectDir)models;$(ProjectDir)controllers;$(ProjectDir)factories;$(ProjectDir)views;$(ProjectDir)services;$(ProjectDir)utilities;$(ProjectDir)core\patterns;$(ProjectDir)datastores;$(ProjectDir)datastores\sharedmemory;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(ProjectDir)models;$(ProjectDir)controllers;$(ProjectDir)factories;$(ProjectDir)views;$(ProjectDir)services;$(ProjectDir)utilities;$(ProjectDir)core\patterns;$(ProjectDir)datastores;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
@@ -129,7 +129,6 @@
<ClCompile Include="core\patterns\Observer.cpp" /> <ClCompile Include="core\patterns\Observer.cpp" />
<ClCompile Include="core\patterns\Subject.cpp" /> <ClCompile Include="core\patterns\Subject.cpp" />
<ClCompile Include="datastores\DataStore.cpp" /> <ClCompile Include="datastores\DataStore.cpp" />
<ClCompile Include="datastores\sharedmemory\SharedMemory.cpp" />
<ClCompile Include="models\ComboPackage.cpp" /> <ClCompile Include="models\ComboPackage.cpp" />
<ClCompile Include="models\InventoryItem.cpp" /> <ClCompile Include="models\InventoryItem.cpp" />
<ClCompile Include="models\Invoice.cpp" /> <ClCompile Include="models\Invoice.cpp" />
@@ -157,13 +156,6 @@
<ClInclude Include="core\patterns\Observer.h" /> <ClInclude Include="core\patterns\Observer.h" />
<ClInclude Include="core\patterns\Subject.h" /> <ClInclude Include="core\patterns\Subject.h" />
<ClInclude Include="datastores\DataStore.h" /> <ClInclude Include="datastores\DataStore.h" />
<ClInclude Include="datastores\DataStoreLockGuard.h" />
<ClInclude Include="datastores\sharedmemory\FileHeader.h" />
<ClInclude Include="datastores\sharedmemory\MappingInfo.h" />
<ClInclude Include="datastores\sharedmemory\RecordState.h" />
<ClInclude Include="datastores\sharedmemory\SerializedRecords.h" />
<ClInclude Include="datastores\sharedmemory\SharedMemory.h" />
<ClInclude Include="datastores\sharedmemory\TrackedRecord.h" />
<ClInclude Include="factories\Factory.h" /> <ClInclude Include="factories\Factory.h" />
<ClInclude Include="models\ComboPackage.h" /> <ClInclude Include="models\ComboPackage.h" />
<ClInclude Include="models\InventoryItem.h" /> <ClInclude Include="models\InventoryItem.h" />
@@ -64,12 +64,6 @@
<Filter Include="Source Files\Core\Patterns"> <Filter Include="Source Files\Core\Patterns">
<UniqueIdentifier>{8057b93d-51a9-42df-b06e-01ce395f6308}</UniqueIdentifier> <UniqueIdentifier>{8057b93d-51a9-42df-b06e-01ce395f6308}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="Header Files\DataStores\SharedMemory">
<UniqueIdentifier>{ec639004-44c6-4bd6-9963-077adde82b5f}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\DataStores\SharedMemory">
<UniqueIdentifier>{7aa8722e-adfa-466e-8211-de63f3b7892b}</UniqueIdentifier>
</Filter>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="Trenser.VehicleServiceSystem.cpp"> <ClCompile Include="Trenser.VehicleServiceSystem.cpp">
@@ -147,9 +141,6 @@
<ClCompile Include="models\ComboPackage.cpp"> <ClCompile Include="models\ComboPackage.cpp">
<Filter>Source Files\Models</Filter> <Filter>Source Files\Models</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="datastores\sharedmemory\SharedMemory.cpp">
<Filter>Source Files\DataStores\SharedMemory</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="utilities\InputHelper.h"> <ClInclude Include="utilities\InputHelper.h">
@@ -242,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>
@@ -254,29 +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>
<ClInclude Include="datastores\sharedmemory\FileHeader.h">
<Filter>Header Files\DataStores\SharedMemory</Filter>
</ClInclude>
<ClInclude Include="datastores\sharedmemory\MappingInfo.h">
<Filter>Header Files\DataStores\SharedMemory</Filter>
</ClInclude>
<ClInclude Include="datastores\sharedmemory\RecordState.h">
<Filter>Header Files\DataStores\SharedMemory</Filter>
</ClInclude>
<ClInclude Include="datastores\sharedmemory\TrackedRecord.h">
<Filter>Header Files\DataStores\SharedMemory</Filter>
</ClInclude>
<ClInclude Include="datastores\sharedmemory\SerializedRecords.h">
<Filter>Header Files\DataStores\SharedMemory</Filter>
</ClInclude>
<ClInclude Include="datastores\sharedmemory\SharedMemory.h">
<Filter>Header Files\DataStores\SharedMemory</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>
@@ -1,14 +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"
@@ -16,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)
{ {
@@ -32,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
*/ */
@@ -43,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)
@@ -52,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();
@@ -94,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();
@@ -111,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();
@@ -152,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);
@@ -189,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;
} }
@@ -246,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();
@@ -265,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;
@@ -302,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);
@@ -321,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();
@@ -385,17 +277,9 @@ util::Map<std::string, const JobCard*> Controller::getJobCardsByUser()
return readOnlyJobCardMap; return readOnlyJobCardMap;
} }
/* void Controller::completeJob(const std::string& jobID)
Function: completeJob
Description: Marks a job card as completed.
Parameters:
- jobID: std::string, ID of the job card
Returns:
- void
*/
void Controller::updateJobStatus(const std::string& jobID)
{ {
m_serviceManagementService.updateJobStatus(jobID); m_serviceManagementService.completeJob(jobID);
} }
/* /*
@@ -410,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);
} }
@@ -441,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();
@@ -463,47 +340,6 @@ util::Map<std::string, const Invoice*> Controller::getInvoicesByUser()
return userInvoicesReadOnly; return userInvoicesReadOnly;
} }
/*
Function: getAllInvoices
Description: Retrieves all invoices from the PaymentManagementService and returns them as a read-only map.
Parameters:
- none
Returns:
- util::Map<std::string, const Invoice*>: Map of invoice IDs to invoice objects
*/
util::Map<std::string, const Invoice*> Controller::getAllInvoices()
{
auto invoices = m_paymentManagementService.getAllInvoices();
util::Map<std::string, const Invoice*> readOnlyInvoice;
for (int iterator = 0; iterator < invoices.getSize(); iterator++)
{
readOnlyInvoice.insert(invoices.getKeyAt(iterator), invoices.getValueAt(iterator));
}
return readOnlyInvoice;
}
/*
Function: confirmPayment
Description: Delegates payment confirmation for a given invoice ID to the PaymentManagementService.
Parameters:
- invoiceID: std::string, ID of the invoice to confirm
Returns:
- void
*/
void Controller::confirmPayment(const std::string& invoiceID)
{
m_paymentManagementService.confirmPayment(invoiceID);
}
/*
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);
@@ -587,38 +423,45 @@ void Controller::configureNotifications(bool paymentNotifications, bool serviceN
} }
} }
/* void Controller::loadSystemData()
Function: initialize
Description: Initializes the system and run system checks to ensure critical configurations, such as verifying admin existence.
Parameters:
- None
Returns:
- bool
*/
bool Controller::initialize()
{ {
auto& dataStore = DataStore::getInstance(); m_userManagementService.loadUsers();
m_inventoryManagementService.loadInventoryItems();
m_serviceManagementService.loadServices();
m_serviceManagementService.loadComboPackages();
m_serviceManagementService.loadServiceBookings();
m_serviceManagementService.loadJobCards();
m_paymentManagementService.loadInvoices();
m_serviceManagementService.loadObservers();
m_paymentManagementService.loadObservers();
m_inventoryManagementService.loadObservers();
}
if (!dataStore.initialize()) void Controller::saveSystemData()
{ {
return false; m_userManagementService.saveUsers();
} m_inventoryManagementService.saveInventoryItems();
m_serviceManagementService.saveServices();
m_serviceManagementService.saveComboPackages();
m_serviceManagementService.saveServiceBookings();
m_serviceManagementService.saveJobCards();
m_paymentManagementService.saveInvoices();
m_serviceManagementService.saveObservers();
m_paymentManagementService.saveObservers();
m_inventoryManagementService.saveObservers();
}
/*
Function: runSystemChecks
Description: Executes system checks including sending low stock alerts
and payment reminders.
Parameters: None
Return type: void
*/
void Controller::runSystemChecks()
{
m_userManagementService.ensureAdminExists(); m_userManagementService.ensureAdminExists();
m_inventoryManagementService.sendLowStockAlerts(); m_inventoryManagementService.sendLowStockAlerts();
m_paymentManagementService.sendPaymentReminders(); m_paymentManagementService.sendPaymentReminders();
return true;
} }
/*
Function: shutdown
Description: Shutdown the system, and do necessary cleanups
Parameters:
- None
Returns:
- void
*/
void Controller::shutdown()
{
auto& dataStore = DataStore::getInstance();
dataStore.shutdown();
}
@@ -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();
@@ -59,17 +58,16 @@ public:
void createService(const std::string& name, const util::Vector<std::string>& inventoryItemIDs, double laborCost); void createService(const std::string& name, const util::Vector<std::string>& inventoryItemIDs, double laborCost);
void removeService(const std::string& serviceID); void removeService(const std::string& serviceID);
util::Map<std::string, const JobCard*> getJobCardsByUser(); util::Map<std::string, const JobCard*> getJobCardsByUser();
void updateJobStatus(const std::string& jobID); void completeJob(const std::string& jobID);
void removeUser(const std::string& userID); void removeUser(const std::string& userID);
void createComboPackage(const std::string& name, const util::Vector<std::string>& serviceIDs, double discountPercentage); void createComboPackage(const std::string& name, const util::Vector<std::string>& serviceIDs, double discountPercentage);
void removeComboPackage(const std::string& comboPackageID); void removeComboPackage(const std::string& comboPackageID);
util::Map<std::string, const Invoice*> getInvoicesByUser(); util::Map<std::string, const Invoice*> getInvoicesByUser();
util::Map<std::string, const Invoice*> getAllInvoices();
void confirmPayment(const std::string& invoiceID);
void completePayment(const std::string& invoiceID, util::PaymentMode paymentMode); void completePayment(const std::string& invoiceID, util::PaymentMode paymentMode);
util::Vector<const Notification*> getNotifications(); util::Vector<const Notification*> getNotifications();
void deleteNotification(const std::string& notificationID); void deleteNotification(const std::string& notificationID);
void configureNotifications(bool paymentNotifications, bool serviceNotifications); void configureNotifications(bool paymentNotifications, bool serviceNotifications);
bool initialize(); void loadSystemData();
void shutdown(); void saveSystemData();
void runSystemChecks();
}; };
@@ -9,200 +9,6 @@ Date: 19-May-2026
*/ */
#include "DataStore.h" #include "DataStore.h"
#include "Config.h"
#include "SerializedRecords.h"
#include "FileHelper.h"
/*
Function: DataStore
Description: Constructs the DataStore singleton and initializes
internal handles to their default values.
Parameters:
- None
Returns:
- None
*/
DataStore::DataStore() :
m_globalMutex(NULL) {}
/*
Function: ~DataStore
Description: Destroys the DataStore singleton and releases all
cached application objects owned by the datastore.
This includes users, notifications, services,
combo packages, inventory items, service bookings,
job cards, and invoices.
Parameters:
- None
Returns:
- None
*/
DataStore::~DataStore()
{
clearCache(m_userCache);
clearCache(m_notificationCache);
clearCache(m_serviceCache);
clearCache(m_comboPackageCache);
clearCache(m_inventoryItemCache);
clearCache(m_serviceBookingCache);
clearCache(m_jobCardCache);
clearCache(m_invoiceCache);
}
/*
Function: initialize
Description: Initializes the shared-memory datastore.
Creates or opens the global datastore mutex,
configures all mapping metadata, and creates
or opens the file mappings used to persist
application data. After successful completion,
all datastore files are mapped into memory and
ready for use by the application.
Parameter: None
Return type: bool
- true : Initialization completed successfully.
- false : Failed to create the mutex or open
one or more file mappings.
*/
bool DataStore::initialize()
{
m_globalMutex = CreateMutexA(NULL, FALSE, "VehicleServiceSystemMutex");
if (m_globalMutex == NULL)
{
return false;
}
if (!lockDataStore())
{
CloseHandle(m_globalMutex);
m_globalMutex = NULL;
return false;
}
bool success = true;
do
{
util::ensureDirectoryExists(config::file::DIRECTORY);
m_users.fileName = config::file::USER_FILE;
m_users.recordSize = sizeof(SerializedUser);
m_notifications.fileName = config::file::NOTIFICATION_FILE;
m_notifications.recordSize = sizeof(SerializedNotification);
m_services.fileName = config::file::SERVICE_FILE;
m_services.recordSize = sizeof(SerializedService);
m_comboPackages.fileName = config::file::COMBOPACKAGE_FILE;
m_comboPackages.recordSize = sizeof(SerializedComboPackage);
m_inventoryItems.fileName = config::file::INVENTORYITEM_FILE;
m_inventoryItems.recordSize = sizeof(SerializedInventoryItem);
m_serviceBookings.fileName = config::file::SERVICEBOOKING_FILE;
m_serviceBookings.recordSize = sizeof(SerializedServiceBooking);
m_jobCards.fileName = config::file::JOBCARD_FILE;
m_jobCards.recordSize = sizeof(SerializedJobCard);
m_invoices.fileName = config::file::INVOICE_FILE;
m_invoices.recordSize = sizeof(SerializedInvoice);
m_serviceManagementObservers.fileName = config::file::SERVICEMANAGEMENTOBSERVERS;
m_serviceManagementObservers.recordSize = sizeof(SerializedObserver);
m_paymentManagementObservers.fileName = config::file::PAYMENTMANAGEMENTOBSERVERS;
m_paymentManagementObservers.recordSize = sizeof(SerializedObserver);
m_inventoryManagementObservers.fileName = config::file::INVENTORYMANAGEMENTOBSERVERS;
m_inventoryManagementObservers.recordSize = sizeof(SerializedObserver);
if (!SharedMemory::createOrOpenMapping(m_users))
{
success = false;
break;
}
if (!SharedMemory::createOrOpenMapping(m_notifications))
{
success = false;
break;
}
if (!SharedMemory::createOrOpenMapping(m_services))
{
success = false;
break;
}
if (!SharedMemory::createOrOpenMapping(m_comboPackages))
{
success = false;
break;
}
if (!SharedMemory::createOrOpenMapping(m_inventoryItems))
{
success = false;
break;
}
if (!SharedMemory::createOrOpenMapping(m_serviceBookings))
{
success = false;
break;
}
if (!SharedMemory::createOrOpenMapping(m_jobCards))
{
success = false;
break;
}
if (!SharedMemory::createOrOpenMapping(m_invoices))
{
success = false;
break;
}
if (!SharedMemory::createOrOpenMapping(m_payments))
{
success = false;
break;
}
if (!SharedMemory::createOrOpenMapping(m_serviceManagementObservers))
{
success = false;
break;
}
if (!SharedMemory::createOrOpenMapping(m_paymentManagementObservers))
{
success = false;
break;
}
if (!SharedMemory::createOrOpenMapping(m_inventoryManagementObservers))
{
success = false;
break;
}
} while (false);
unlockDataStore();
if (!success)
{
shutdown();
}
return success;
}
/*
Function: shutdown
Description: Releases all shared-memory resources owned by the
datastore. Closes every file mapping, unmaps all
mapped views, and releases the datastore mutex.
After this call, the datastore must be initialized
again before use.
Parameter: None
Return type: void
*/
void DataStore::shutdown()
{
SharedMemory::closeMapping(m_users);
SharedMemory::closeMapping(m_notifications);
SharedMemory::closeMapping(m_services);
SharedMemory::closeMapping(m_comboPackages);
SharedMemory::closeMapping(m_inventoryItems);
SharedMemory::closeMapping(m_serviceBookings);
SharedMemory::closeMapping(m_jobCards);
SharedMemory::closeMapping(m_invoices);
SharedMemory::closeMapping(m_payments);
SharedMemory::closeMapping(m_serviceManagementObservers);
SharedMemory::closeMapping(m_paymentManagementObservers);
SharedMemory::closeMapping(m_inventoryManagementObservers);
if (m_globalMutex != NULL)
{
CloseHandle(m_globalMutex);
m_globalMutex = NULL;
}
}
/* /*
Function: getInstance Function: getInstance
@@ -220,367 +26,104 @@ DataStore& DataStore::getInstance()
/* /*
Function: getUsers Function: getUsers
Description: Retrieves all user records from the datastore. Description: Retrieves the internal map of users.
Parameters: Parameters:
- None - None
Returns: Returns:
- util::Map<std::string, TrackedRecord<User>>: Collection of user records - Reference to util::Map<std::string, User*> containing all users.
*/ */
util::Map<std::string, TrackedRecord<User>>& DataStore::getUsers() util::Map<std::string, User*>& DataStore::getUsers()
{ {
auto users = loadRecords<User, SerializedUser>(m_users); return m_users;
refreshCache(m_userCache, users);
auto& notifications = getNotifications();
int numberOfNotifications = m_notificationCache.getSize();
for (int index = 0; index < numberOfNotifications; index++)
{
Notification* notification = notifications.getValueAt(index).data;
const std::string& recipientUserId = notification->getRecipientUserId();
int userIndex = m_userCache.find(recipientUserId);
if (userIndex == -1)
{
throw std::runtime_error("Invalid recipient user ID");
}
User* user = m_userCache.getValueAt(userIndex).data;
user->addNotification(notification);
}
return m_userCache;
}
/*
Function: getNotifications
Description: Retrieves all notification records from the datastore.
Parameters:
- None
Returns:
- util::Map<std::string, TrackedRecord<Notification>>: Collection of notification records
*/
util::Map<std::string, TrackedRecord<Notification>>& DataStore::getNotifications()
{
auto notifications = loadRecords<Notification, SerializedNotification>(m_notifications);
refreshCache(m_notificationCache, notifications);
return m_notificationCache;
} }
/* /*
Function: getServices Function: getServices
Description: Retrieves all service records from the datastore. Description: Retrieves the internal map of services.
Parameters: Parameters:
- None - None
Returns: Returns:
- util::Map<std::string, TrackedRecord<Service>>: Collection of service records - Reference to util::Map<std::string, Service*> containing all services.
*/ */
util::Map<std::string, TrackedRecord<Service>>& DataStore::getServices() util::Map<std::string, Service*>& DataStore::getServices()
{ {
return m_serviceCache; return m_services;
} }
/* /*
Function: getComboPackages Function: getComboPackages
Description: Retrieves all combo package records from the datastore. Description: Retrieves the internal map of combo packages.
Parameters: Parameters:
- None - None
Returns: Returns:
- util::Map<std::string, TrackedRecord<ComboPackage>>: Collection of combo package records - Reference to util::Map<std::string, ComboPackage*> containing all combo packages.
*/ */
util::Map<std::string, TrackedRecord<ComboPackage>>& DataStore::getComboPackages() util::Map<std::string, ComboPackage*>& DataStore::getComboPackages()
{ {
return m_comboPackageCache; return m_comboPackages;
}
/*
Function: getInventoryItems
Description: Retrieves all inventory item records from the datastore.
Parameters:
- None
Returns:
- util::Map<std::string, TrackedRecord<InventoryItem>>: Collection of inventory item records
*/
util::Map<std::string, TrackedRecord<InventoryItem>>& DataStore::getInventoryItems()
{
return m_inventoryItemCache;
} }
/* /*
Function: getServiceBookings Function: getServiceBookings
Description: Retrieves all service booking records from the datastore. Description: Retrieves the internal map of service bookings.
Parameters: Parameters:
- None - None
Returns: Returns:
- util::Map<std::string, TrackedRecord<ServiceBooking>>: Collection of service booking records - Reference to util::Map<std::string, ServiceBooking*> containing all service bookings.
*/ */
util::Map<std::string, TrackedRecord<ServiceBooking>>& DataStore::getServiceBookings() util::Map<std::string, ServiceBooking*>& DataStore::getServiceBookings()
{ {
return m_serviceBookingCache; return m_serviceBookings;
} }
/* /*
Function: getJobCards Function: getJobCards
Description: Retrieves all job card records from the datastore. Description: Retrieves the internal map of job cards.
Parameters: Parameters:
- None - None
Returns: Returns:
- util::Map<std::string, TrackedRecord<JobCard>>: Collection of job card records - Reference to util::Map<std::string, JobCard*> containing all job cards.
*/ */
util::Map<std::string, TrackedRecord<JobCard>>& DataStore::getJobCards() util::Map<std::string, JobCard*>& DataStore::getJobCards()
{ {
return m_jobCardCache; return m_jobCards;
}
/*
Function: getInventoryItems
Description: Retrieves the internal map of inventory items.
Parameters:
- None
Returns:
- Reference to util::Map<std::string, InventoryItem*> containing all inventory items.
*/
util::Map<std::string, InventoryItem*>& DataStore::getInventoryItems()
{
return m_inventoryItems;
} }
/* /*
Function: getInvoices Function: getInvoices
Description: Retrieves all invoice records from the datastore. Description: Retrieves the internal map of invoices.
Parameters: Parameters:
- None - None
Returns: Returns:
- util::Map<std::string, TrackedRecord<Invoice>>: Collection of invoice records - Reference to util::Map<std::string, Invoice*> containing all invoices.
*/ */
util::Map<std::string, TrackedRecord<Invoice>>& DataStore::getInvoices() util::Map<std::string, Invoice*>& DataStore::getInvoices()
{ {
return m_invoiceCache; return m_invoices;
} }
/* /*
Function: getServiceManagementObservers Function: getPayments
Description: Retrieves all service management observer records from the datastore. Description: Retrieves the internal map of payments.
Parameters: Parameters:
- None - None
Returns: Returns:
- util::Map<std::string, User*>: Collection of observer records - Reference to util::Map<std::string, Payment*> containing all payments.
*/ */
util::Map<std::string, User*> DataStore::getServiceManagementObservers() util::Map<std::string, Payment*>& DataStore::getPayments()
{ {
return util::Map<std::string, User*>(); return m_payments;
} }
/*
Function: getPaymentManagementObservers
Description: Retrieves all payment management observer records from the datastore.
Parameters:
- None
Returns:
- util::Map<std::string, User*>: Collection of observer records
*/
util::Map<std::string, User*> DataStore::getPaymentManagementObservers()
{
return util::Map<std::string, User*>();
}
/*
Function: getInventoryManagementObservers
Description: Retrieves all inventory management observer records from the datastore.
Parameters:
- None
Returns:
- util::Map<std::string, User*>: Collection of observer records
*/
util::Map<std::string, User*> DataStore::getInventoryManagementObservers()
{
return util::Map<std::string, User*>();
}
/*
Function: saveUsers
Description: Persists all user records to the datastore.
Parameters:
- None
Returns:
- None
*/
void DataStore::saveUsers()
{
saveRecords<User, SerializedUser>(m_users, m_userCache);
saveNotifications();
}
/*
Function: saveNotifications
Description: Persists all notification records to the datastore.
Parameters:
- None
Returns:
- None
*/
void DataStore::saveNotifications()
{
saveRecords<Notification, SerializedNotification>(m_notifications, m_notificationCache);
}
/*
Function: saveServices
Description: Persists all service records to the datastore.
Parameters:
- None
Returns:
- None
*/
void DataStore::saveServices()
{
}
/*
Function: saveComboPackages
Description: Persists all combo package records to the datastore.
Parameters:
- None
Returns:
- None
*/
void DataStore::saveComboPackages()
{
}
/*
Function: saveInventoryItems
Description: Persists all inventory item records to the datastore.
Parameters:
- None
Returns:
- None
*/
void DataStore::saveInventoryItems()
{
}
/*
Function: saveServiceBookings
Description: Persists all service booking records to the datastore.
Parameters:
- None
Returns:
- None
*/
void DataStore::saveServiceBookings()
{
}
/*
Function: saveJobCards
Description: Persists all job card records to the datastore.
Parameters:
- None
Returns:
- None
*/
void DataStore::saveJobCards()
{
}
/*
Function: saveInvoices
Description: Persists all invoice records to the datastore.
Parameters:
- None
Returns:
- None
*/
void DataStore::saveInvoices()
{
}
/*
Function: saveServiceManagementObservers
Description: Persists all service management observer records to the datastore.
Parameters:
- observers: util::Map<std::string, TrackedRecord<std::string>>&, collection of observer records
Returns:
- None
*/
void DataStore::saveServiceManagementObservers(util::Map<std::string, User*>& observers)
{
}
/*
Function: savePaymentManagementObservers
Description: Persists all payment management observer records to the datastore.
Parameters:
- observers: util::Map<std::string, User*>&, collection of observer records
Returns:
- None
*/
void DataStore::savePaymentManagementObservers(util::Map<std::string, User*>& observers)
{
}
/*
Function: saveInventoryManagementObservers
Description: Persists all inventory management observer records to the datastore.
Parameters:
- observers: util::Map<std::string, User*>&, collection of observer records
Returns:
- None
*/
void DataStore::saveInventoryManagementObservers(util::Map<std::string, User*>& observers)
{
}
/*
Function: lockDataStore
Description: Acquires exclusive access to the datastore.
Parameters:
- None
Returns:
- bool: True if the datastore was successfully locked, otherwise false
*/
bool DataStore::lockDataStore()
{
return false;
}
/*
Function: unlockDataStore
Description: Releases exclusive access to the datastore.
Parameters:
- None
Returns:
- bool: True if the datastore was successfully unlocked, otherwise false
*/
bool DataStore::unlockDataStore()
{
return false;
}
/*
Function: lockDataStore
Description: Acquires the datastore mutex, providing
exclusive access to the shared-memory
datastore. This function blocks until
the mutex becomes available or an error
occurs.
Parameter: None
Return type:
bool
- true : Mutex successfully acquired.
- false : Failed to acquire the mutex.
*/
bool DataStore::lockDataStore()
{
if (m_globalMutex == NULL)
{
return false;
}
DWORD result = WaitForSingleObject(m_globalMutex, INFINITE);
return result == WAIT_OBJECT_0;
}
/*
Function: unlockDataStore
Description: Releases the datastore mutex after a
successful call to lockDataStore(),
allowing other processes to access the
shared-memory datastore.
Parameter: None
Return type:
bool
- true : Mutex successfully released.
- false : Failed to release the mutex.
*/
bool DataStore::unlockDataStore()
{
if (m_globalMutex == NULL)
{
return false;
}
return ReleaseMutex(m_globalMutex) != 0;
}
@@ -6,232 +6,42 @@ Date: 19-May-2026
*/ */
#pragma once #pragma once
#include <windows.h>
#include <string> #include <string>
#include "Map.h" #include "Map.h"
#include "MappingInfo.h"
#include "TrackedRecord.h"
#include "SharedMemory.h"
class User; class User;
class Notification;
class Service; class Service;
class ComboPackage; class ComboPackage;
class InventoryItem;
class ServiceBooking; class ServiceBooking;
class JobCard; class JobCard;
class InventoryItem;
class Invoice; class Invoice;
class Payment;
class DataStore class DataStore
{ {
private: private:
DataStore(); util::Map<std::string, User*> m_users;
~DataStore(); util::Map<std::string, Service*> m_services;
util::Map<std::string, ComboPackage*> m_comboPackages;
util::Map<std::string, ServiceBooking*> m_serviceBookings;
util::Map<std::string, JobCard*> m_jobCards;
util::Map<std::string, InventoryItem*> m_inventoryItems;
util::Map<std::string, Invoice*> m_invoices;
util::Map<std::string, Payment*> m_payments;
DataStore() {}
public:
static DataStore& getInstance();
DataStore(const DataStore&) = delete; DataStore(const DataStore&) = delete;
DataStore& operator=(const DataStore&) = delete; DataStore& operator=(const DataStore&) = delete;
DataStore(DataStore&&) = delete; DataStore(DataStore&&) = delete;
DataStore& operator=(DataStore&&) = delete; DataStore& operator=(DataStore&&) = delete;
HANDLE m_globalMutex; util::Map<std::string, User*>& getUsers();
MappingInfo m_users; util::Map<std::string, Service*>& getServices();
MappingInfo m_notifications; util::Map<std::string, ComboPackage*>& getComboPackages();
MappingInfo m_services; util::Map<std::string, ServiceBooking*>& getServiceBookings();
MappingInfo m_comboPackages; util::Map<std::string, JobCard*>& getJobCards();
MappingInfo m_inventoryItems; util::Map<std::string, InventoryItem*>& getInventoryItems();
MappingInfo m_serviceBookings; util::Map<std::string, Invoice*>& getInvoices();
MappingInfo m_jobCards; util::Map<std::string, Payment*>& getPayments();
MappingInfo m_invoices; };
MappingInfo m_payments;
MappingInfo m_serviceManagementObservers;
MappingInfo m_paymentManagementObservers;
MappingInfo m_inventoryManagementObservers;
util::Map<std::string, TrackedRecord<User>> m_userCache;
util::Map<std::string, TrackedRecord<Notification>> m_notificationCache;
util::Map<std::string, TrackedRecord<Service>> m_serviceCache;
util::Map<std::string, TrackedRecord<ComboPackage>> m_comboPackageCache;
util::Map<std::string, TrackedRecord<InventoryItem>> m_inventoryItemCache;
util::Map<std::string, TrackedRecord<ServiceBooking>> m_serviceBookingCache;
util::Map<std::string, TrackedRecord<JobCard>> m_jobCardCache;
util::Map<std::string, TrackedRecord<Invoice>> m_invoiceCache;
public:
static DataStore& getInstance();
bool initialize();
void shutdown();
util::Map<std::string, TrackedRecord<User>>& getUsers();
util::Map<std::string, TrackedRecord<Notification>>& getNotifications();
util::Map<std::string, TrackedRecord<Service>>& getServices();
util::Map<std::string, TrackedRecord<ComboPackage>>& getComboPackages();
util::Map<std::string, TrackedRecord<InventoryItem>>& getInventoryItems();
util::Map<std::string, TrackedRecord<ServiceBooking>>& getServiceBookings();
util::Map<std::string, TrackedRecord<JobCard>>& getJobCards();
util::Map<std::string, TrackedRecord<Invoice>>& getInvoices();
util::Map<std::string, User*> getServiceManagementObservers();
util::Map<std::string, User*> getPaymentManagementObservers();
util::Map<std::string, User*> getInventoryManagementObservers();
void saveUsers();
void saveNotifications();
void saveServices();
void saveComboPackages();
void saveInventoryItems();
void saveServiceBookings();
void saveJobCards();
void saveInvoices();
void saveServiceManagementObservers(util::Map<std::string, User*>& observers);
void savePaymentManagementObservers(util::Map<std::string, User*>& observers);
void saveInventoryManagementObservers(util::Map<std::string, User*>& observers);
bool lockDataStore();
bool unlockDataStore();
private:
template<typename TObject, typename TSerialized>
util::Map<std::string, TrackedRecord<TObject>> loadRecords(MappingInfo& mapping);
template<typename TObject, typename TSerialized>
void saveRecords(MappingInfo& mapping, util::Map<std::string, TrackedRecord<TObject>>& records);
template<typename TObject> void clearCache(util::Map<std::string, TrackedRecord<TObject>>&cache);
template<typename TObject> void refreshCache(util::Map<std::string, TrackedRecord<TObject>>&cache, util::Map<std::string, TrackedRecord<TObject>>&refreshedCache);
};
/*
Function: loadRecords
Description: Loads all serialized records from the specified
shared-memory mapping, deserializes them into
application objects, and returns them as a map
of tracked records. Each loaded record is marked
as CLEAN and assigned its corresponding slot index
within the mapping so that future modifications
can be written back efficiently.
Parameter:
- mapping: Reference to the mapping containing the
serialized records.
Return type:
util::Map<std::string, TrackedRecord<TObject>>
A map containing all loaded records keyed by
their unique identifier.
*/
template<typename TObject, typename TSerialized>
util::Map<std::string, TrackedRecord<TObject>> DataStore::loadRecords(MappingInfo& mapping)
{
util::Map<std::string, TrackedRecord<TObject>> records;
SharedMemory::ensureLatestMapping(mapping);
size_t recordCount = SharedMemory::getRecordCount(mapping);
for (size_t index = 0; index < recordCount; ++index)
{
TSerialized* serialized = static_cast<TSerialized*>(SharedMemory::getRecordAddress(mapping,index));
TObject* object = TObject::deserialize(*serialized);
TrackedRecord<TObject> trackedRecord;
trackedRecord.data = object;
trackedRecord.state = RecordState::CLEAN;
trackedRecord.slotIndex = index;
records.insert(object->getId(), trackedRecord);
}
return records;
}
/*
Function: saveRecords
Description: Persists all modified and newly added records
contained in the provided map to the specified
shared-memory mapping. Modified records overwrite
their existing slots, while new records are
appended to the end of the mapping. Records marked
as CLEAN are ignored.
Parameter:
- mapping: Reference to the mapping where records are
stored.
- records: Map containing the records to be persisted.
Return type: void
*/
template<typename TObject, typename TSerialized> void DataStore::saveRecords(MappingInfo& mapping, util::Map<std::string, TrackedRecord<TObject>>& records)
{
SharedMemory::ensureLatestMapping(mapping);
for (int index = 0; index < records.getSize(); ++index)
{
TrackedRecord<TObject>& record = records.getValueAt(index);
if (record.state == RecordState::CLEAN)
{
continue;
}
TSerialized serialized = record.data->serialize();
if (record.state == RecordState::MODIFIED)
{
TSerialized* destination = static_cast<TSerialized*>(SharedMemory::getRecordAddress(mapping, record.slotIndex));
if (destination)
{
*destination = serialized;
}
}
else if (record.state == RecordState::NEW_RECORD)
{
if (!SharedMemory::ensureCapacityForInsert(mapping))
{
continue;
}
size_t recordCount = SharedMemory::getRecordCount(mapping);
TSerialized* destination = static_cast<TSerialized*>(SharedMemory::getRecordAddress(mapping,recordCount));
*destination = serialized;
SharedMemory::setRecordCount(mapping, recordCount + 1);
record.slotIndex = recordCount;
}
record.state = RecordState::CLEAN;
}
}
/*
Function: clearCache
Description: Releases all objects owned by the cache and
clears the cache contents.
Parameters:
- cache: Cache to be cleared.
Returns:
- None
*/
template<typename TObject>
void DataStore::clearCache(util::Map<std::string, TrackedRecord<TObject>>&cache)
{
for (int index = 0; index < cache.getSize(); ++index)
{
delete cache.getValueAt(index).data;
cache.getValueAt(index).data = nullptr;
}
cache.clear();
}
/*
Function: refreshCache
Description: Refreshes the cache while preserving object addresses
for records that already exist. Existing objects are
updated in-place so that pointers held elsewhere remain
valid after the refresh.
Parameters:
- cache: Existing cache to refresh.
- refreshedCache: Newly loaded cache contents.
Returns:
- None
*/
template<typename TObject>
void DataStore::refreshCache(util::Map<std::string, TrackedRecord<TObject>>& cache, util::Map<std::string, TrackedRecord<TObject>>& refreshedCache)
{
util::Map<std::string, TrackedRecord<TObject>> oldCache = cache;
cache.clear();
for (int index = 0; index < refreshedCache.getSize(); ++index)
{
const std::string& id = refreshedCache.getKeyAt(index);
TrackedRecord<TObject>& refreshedRecord = refreshedCache.getValueAt(index);
int oldIndex = oldCache.find(id);
if (oldIndex != -1)
{
TrackedRecord<TObject>& oldRecord = oldCache.getValueAt(oldIndex);
*oldRecord.data = *refreshedRecord.data;
oldRecord.slotIndex = refreshedRecord.slotIndex;
oldRecord.state = refreshedRecord.state;
delete refreshedRecord.data;
refreshedRecord.data = oldRecord.data;
}
cache.insert(id, refreshedRecord);
}
for (int index = 0; index < oldCache.getSize(); ++index)
{
const std::string& id = oldCache.getKeyAt(index);
if (cache.find(id) == -1)
{
delete oldCache.getValueAt(index).data;
}
}
}
@@ -1,28 +0,0 @@
/*
File: DataStoreLockGuard.h
Description: Defines the DataStoreLockGuard class used to manage DataStore
locking and unlocking automatically within a scope.
Author: Trenser
Date: 12-June-2026
*/
#pragma once
#include "DataStore.h"
class DataStoreLockGuard
{
public:
explicit DataStoreLockGuard(DataStore& dataStore)
: m_dataStore(dataStore)
{
m_dataStore.lockDataStore();
}
~DataStoreLockGuard()
{
m_dataStore.unlockDataStore();
}
DataStoreLockGuard(const DataStoreLockGuard&) = delete;
DataStoreLockGuard& operator=(const DataStoreLockGuard&) = delete;
private:
DataStore& m_dataStore;
};
@@ -1,17 +0,0 @@
/*
File: FileHeader.h
Description: Defines the FileHeader structure used to store
metadata for binary record files, including
record count and capacity.
Author: Trenser
Created: 10-June-2026
*/
#pragma once
#include <cstddef>
struct FileHeader
{
size_t recordCount;
size_t capacity;
};
@@ -1,29 +0,0 @@
/*
File: MappingInfo.h
Description: Defines the MappingInfo structure used for
managing Windows file mapping operations.
Stores handles, mapped view pointer,
file metadata, and capacity information.
Author: Trenser
Created: 10-June-2026
*/
#pragma once
#include <windows.h>
#include <string>
struct MappingInfo
{
HANDLE fileHandle;
HANDLE mappingHandle;
void* mappedView;
std::string fileName;
size_t recordSize;
size_t mappedCapacity;
MappingInfo()
: fileHandle(NULL),
mappingHandle(NULL),
mappedView(nullptr),
recordSize(0),
mappedCapacity(0) {}
};
@@ -1,17 +0,0 @@
/*
File: RecordState.h
Description: Defines the RecordState enumeration used to
represent the state of a record in storage.
States include CLEAN, NEW_RECORD, and MODIFIED.
Author: Trenser
Created: 10-June-2026
*/
#pragma once
enum class RecordState : int
{
CLEAN,
NEW_RECORD,
MODIFIED
};
@@ -1,109 +0,0 @@
/*
File: SerializedRecords.h
Description: Defines serialized structures for persistent storage
and retrieval of system entities including User,
Notification, Service, ComboPackage, InventoryItem,
ServiceBooking, JobCard, Invoice, and Observer.
These structures use fixed-size character arrays
and primitive types for binary serialization.
Author: Trenser
Created: 10-June-2026
*/
#pragma once
#include "Utility.h"
#include "Enums.h"
#include "Timestamp.h"
struct SerializedUser
{
char id[64];
char username[64];
char password[64];
char name[128];
char phone[32];
char email[128];
util::UserType userType;
util::State status;
};
struct SerializedNotification
{
char id[64];
char recipientUserId[64];
char title[128];
char message[1024];
util::Timestamp createdAt;
util::State state;
};
struct SerializedService
{
char id[64];
char name[128];
char inventoryItemIDs[1024];
double laborCost;
util::State status;
};
struct SerializedComboPackage
{
char id[64];
char packageName[128];
double discountPercentage;
char serviceIDs[1024];
util::State status;
};
struct SerializedInventoryItem
{
char id[64];
char partName[128];
int quantity;
double price;
util::State status;
};
struct SerializedServiceBooking
{
char id[64];
util::ServiceJobStatus status;
char serviceIDs[1024];
char customerId[64];
char vehicleNumber[64];
char vehicleBrand[64];
char vehicleModel[64];
char assignedTechnicianId[64];
double discountPercentage;
};
struct SerializedJobCard
{
char id[64];
char bookingId[64];
char serviceId[64];
char technicianId[64];
util::Timestamp assignedDate;
util::ServiceJobStatus status;
util::Timestamp completionDate;
};
struct SerializedInvoice
{
char id[64];
char bookingId[64];
util::Timestamp invoiceDate;
char partIDs[1024];
double laborCost;
double partsCost;
double discountPercentage;
double totalAmount;
util::Timestamp paymentDate;
util::PaymentMode paymentMethod;
util::PaymentStatus status;
};
struct SerializedObserver
{
char id[64];
};
@@ -1,386 +0,0 @@
/*
File: SharedMemory.cpp
Description: Implements shared memory utilities for managing
Windows file mapping operations. Provides functions
to create, open, resize, and close mappings, as well
as access headers, records, and ensure synchronization
across processes.
Author: Trenser
Created: 11-June-2026
*/
#include "SharedMemory.h"
#include "Windows.h"
#include "Config.h"
/*
Function: invalidateMapping
Description: Releases all mapping resources and resets the mapping to an invalid state.
Parameters:
- mapping: MappingInfo&, mapping information and handles
Returns:
- None
*/
static void invalidateMapping(MappingInfo& mapping)
{
if (mapping.mappedView != nullptr)
{
UnmapViewOfFile(mapping.mappedView);
mapping.mappedView = nullptr;
}
if (mapping.mappingHandle != NULL)
{
CloseHandle(mapping.mappingHandle);
mapping.mappingHandle = NULL;
}
if (mapping.fileHandle != INVALID_HANDLE_VALUE)
{
CloseHandle(mapping.fileHandle);
mapping.fileHandle = INVALID_HANDLE_VALUE;
}
mapping.mappedCapacity = 0;
}
/*
Function: createOrOpenMapping
Description: Creates or opens a file mapping and maps it into the process address space.
Parameters:
- mapping: MappingInfo&, mapping information and handles
Returns:
- bool: True if the mapping was successfully created/opened, otherwise false
*/
bool SharedMemory::createOrOpenMapping(MappingInfo& mapping)
{
if (mapping.recordSize == 0)
{
return false;
}
mapping.fileHandle =
CreateFileA(
mapping.fileName.c_str(),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (mapping.fileHandle == INVALID_HANDLE_VALUE)
{
return false;
}
LARGE_INTEGER fileSize;
if (!GetFileSizeEx(mapping.fileHandle, &fileSize))
{
invalidateMapping(mapping);
return false;
}
bool isNewFile = (fileSize.QuadPart == 0);
const size_t initialCapacity = config::file::INITIAL_CAPACITY;
if (isNewFile)
{
LARGE_INTEGER newSize;
newSize.QuadPart = sizeof(FileHeader) + initialCapacity * mapping.recordSize;
if (!SetFilePointerEx(mapping.fileHandle, newSize, NULL, FILE_BEGIN))
{
invalidateMapping(mapping);
return false;
}
if (!SetEndOfFile(mapping.fileHandle))
{
invalidateMapping(mapping);
return false;
}
}
mapping.mappingHandle =
CreateFileMappingA(
mapping.fileHandle,
NULL,
PAGE_READWRITE,
0,
0,
NULL);
if (mapping.mappingHandle == NULL)
{
invalidateMapping(mapping);
return false;
}
mapping.mappedView =
MapViewOfFile(
mapping.mappingHandle,
FILE_MAP_ALL_ACCESS,
0,
0,
0);
if (mapping.mappedView == nullptr)
{
invalidateMapping(mapping);
return false;
}
FileHeader* header = getHeader(mapping);
if (header == nullptr)
{
invalidateMapping(mapping);
return false;
}
if (isNewFile)
{
header->recordCount = 0;
header->capacity = initialCapacity;
}
mapping.mappedCapacity = header->capacity;
return true;
}
/*
Function: closeMapping
Description: Unmaps and closes all resources associated with a file mapping.
Parameters:
- mapping: MappingInfo&, mapping to close
Returns:
- None
*/
void SharedMemory::closeMapping(MappingInfo& mapping)
{
invalidateMapping(mapping);
}
/*
Function: getHeader
Description: Returns the file header stored at the beginning of the mapped memory region.
Parameters:
- mapping: MappingInfo&, mapping information and handles
Returns:
- FileHeader*: Pointer to the file header, or nullptr if the mapping is not valid
*/
FileHeader* SharedMemory::getHeader(MappingInfo& mapping)
{
if (mapping.mappedView == nullptr)
{
return nullptr;
}
return reinterpret_cast<FileHeader*>(mapping.mappedView);
}
/*
Function: getRecordAddress
Description: Returns the address of a record at the specified index within the mapped memory region.
Parameters:
- mapping: MappingInfo&, mapping information and handles
- index: size_t, record index
Returns:
- void*: Pointer to the record, or nullptr if the mapping is not valid
*/
void* SharedMemory::getRecordAddress(MappingInfo& mapping, size_t index)
{
if (mapping.mappedView == nullptr)
{
return nullptr;
}
return reinterpret_cast<char*>(mapping.mappedView) + sizeof(FileHeader) + index * mapping.recordSize;
}
/*
Function: getRecordCount
Description: Returns the number of records currently stored in the mapping.
Parameters:
- mapping: MappingInfo&, mapping information and handles
Returns:
- size_t: Number of records in the mapping
*/
size_t SharedMemory::getRecordCount(MappingInfo& mapping)
{
FileHeader* header = getHeader(mapping);
if (header == nullptr)
{
return 0;
}
return header->recordCount;
}
/*
Function: setRecordCount
Description: Updates the number of records stored in the mapping.
Parameters:
- mapping: MappingInfo&, mapping information and handles
- count: size_t, new record count
Returns:
- None
*/
void SharedMemory::setRecordCount(MappingInfo& mapping, size_t count)
{
FileHeader* header = getHeader(mapping);
if (header == nullptr)
{
return;
}
header->recordCount = count;
}
/*
Function: getCapacity
Description: Returns the current capacity of the mapping.
Parameters:
- mapping: MappingInfo&, mapping information and handles
Returns:
- size_t: Maximum number of records that can be stored in the mapping
*/
size_t SharedMemory::getCapacity(MappingInfo& mapping)
{
FileHeader* header = getHeader(mapping);
if (header == nullptr)
{
return 0;
}
return header->capacity;
}
/*
Function: resizeMapping
Description: Resizes the file mapping to the specified capacity.
Parameters:
- mapping: MappingInfo&, mapping information and handles
- newCapacity: size_t, new mapping capacity
Returns:
- bool: True if the resize succeeded, otherwise false
*/
bool SharedMemory::resizeMapping(MappingInfo& mapping, size_t newCapacity)
{
FileHeader* header = getHeader(mapping);
if (header == nullptr)
{
invalidateMapping(mapping);
return false;
}
header->capacity = newCapacity;
if (!FlushViewOfFile(mapping.mappedView, sizeof(FileHeader)))
{
return false;
}
if (!UnmapViewOfFile(mapping.mappedView))
{
return false;
}
mapping.mappedView = nullptr;
CloseHandle(mapping.mappingHandle);
mapping.mappingHandle = NULL;
LARGE_INTEGER newSize;
newSize.QuadPart = sizeof(FileHeader) + newCapacity * mapping.recordSize;
if (!SetFilePointerEx(mapping.fileHandle, newSize, NULL, FILE_BEGIN))
{
invalidateMapping(mapping);
return false;
}
if (!SetEndOfFile(mapping.fileHandle))
{
invalidateMapping(mapping);
return false;
}
mapping.mappingHandle =
CreateFileMappingA(
mapping.fileHandle,
NULL,
PAGE_READWRITE,
0,
0,
NULL);
if (mapping.mappingHandle == NULL)
{
invalidateMapping(mapping);
return false;
}
mapping.mappedView =
MapViewOfFile(
mapping.mappingHandle,
FILE_MAP_ALL_ACCESS,
0,
0,
0);
if (mapping.mappedView == nullptr)
{
invalidateMapping(mapping);
return false;
}
mapping.mappedCapacity = newCapacity;
return true;
}
/*
Function: ensureCapacityForInsert
Description: Ensures that the mapping has space for at least one additional record, growing it if necessary.
Parameters:
- mapping: MappingInfo&, mapping information and handles
Returns:
- bool: True if capacity is available, otherwise false
*/
bool SharedMemory::ensureCapacityForInsert(MappingInfo& mapping)
{
size_t recordCount = getRecordCount(mapping);
size_t capacity = getCapacity(mapping);
if (recordCount < capacity)
{
return true;
}
return resizeMapping(mapping, capacity * 2);
}
/*
Function: ensureLatestMapping
Description: Remaps the file if another process has resized it.
Parameters:
- mapping: MappingInfo&, mapping information and handles
Returns:
- bool: True if the mapping is valid and up to date, otherwise false
*/
bool SharedMemory::ensureLatestMapping(MappingInfo& mapping)
{
FileHeader* header = getHeader(mapping);
if (header == nullptr)
{
return false;
}
if (header->capacity == mapping.mappedCapacity)
{
return true;
}
if (!UnmapViewOfFile(mapping.mappedView))
{
invalidateMapping(mapping);
return false;
}
mapping.mappedView = nullptr;
CloseHandle(mapping.mappingHandle);
mapping.mappingHandle = NULL;
mapping.mappingHandle =
CreateFileMappingA(
mapping.fileHandle,
NULL,
PAGE_READWRITE,
0,
0,
NULL);
if (mapping.mappingHandle == NULL)
{
invalidateMapping(mapping);
return false;
}
mapping.mappedView =
MapViewOfFile(
mapping.mappingHandle,
FILE_MAP_ALL_ACCESS,
0,
0,
0);
if (mapping.mappedView == nullptr)
{
invalidateMapping(mapping);
return false;
}
header = getHeader(mapping);
if (header == nullptr)
{
invalidateMapping(mapping);
return false;
}
mapping.mappedCapacity = header->capacity;
return true;
}
@@ -1,29 +0,0 @@
/*
File: SharedMemory.h
Description: Declares functions for managing Windows file
mapping and shared memory operations. Provides
utilities for creating, resizing, and closing
mappings, as well as accessing headers and
record data.
Author: Trenser
Created: 10-June-2026
*/
#pragma once
#include <cstddef>
#include "MappingInfo.h"
#include "FileHeader.h"
namespace SharedMemory
{
bool createOrOpenMapping(MappingInfo& mapping);
void closeMapping(MappingInfo& mapping);
bool ensureLatestMapping(MappingInfo& mapping);
bool resizeMapping(MappingInfo& mapping, size_t newCapacity);
FileHeader* getHeader(MappingInfo& mapping);
void* getRecordAddress(MappingInfo& mapping, size_t index);
size_t getRecordCount(MappingInfo& mapping);
void setRecordCount(MappingInfo& mapping, size_t count);
size_t getCapacity(MappingInfo& mapping);
bool ensureCapacityForInsert(MappingInfo& mapping);
};
@@ -1,33 +0,0 @@
/*
File: TrackedRecord.h
Description: Defines the TrackedRecord template structure used
to manage objects with associated record state and
slot index. Supports tracking of CLEAN, NEW_RECORD,
and MODIFIED states for persistence and synchronization.
Author: Trenser
Created: 10-June-2026
*/
#pragma once
#include "RecordState.h"
static const size_t INVALID_SLOT = static_cast<size_t>(-1);
template<typename T>
struct TrackedRecord
{
T* data;
RecordState state;
size_t slotIndex;
TrackedRecord()
: data(nullptr),
state(RecordState::CLEAN),
slotIndex(INVALID_SLOT) {}
TrackedRecord(
T* object,
RecordState recordState,
size_t slot)
: data(object),
state(recordState),
slotIndex(slot) {}
};
@@ -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";
} }
@@ -8,7 +8,6 @@ Date: 19-May-2026
*/ */
#include <sstream> #include <sstream>
#include "SerializedRecords.h"
#include "User.h" #include "User.h"
#include "Notification.h" #include "Notification.h"
#include "Enums.h" #include "Enums.h"
@@ -29,8 +28,7 @@ Returns:
User::User() User::User()
: m_id("USR" + std::to_string(++m_uid)), : m_id("USR" + std::to_string(++m_uid)),
m_type(util::UserType::CUSTOMER), m_type(util::UserType::CUSTOMER),
m_status(util::State::ACTIVE) { m_status(util::State::ACTIVE) {}
}
/* /*
Function: User Function: User
@@ -53,25 +51,8 @@ User::User(const std::string& userName, const std::string& password, const std::
m_phone(phone), m_phone(phone),
m_email(email), m_email(email),
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),
@@ -325,45 +306,47 @@ void User::setState(util::State status)
m_status = status; m_status = status;
} }
/* std::string User::serialize() const
Function: serialize
Description: Serializes the User object into a SerializedUser record.
Parameters:
- None
Returns:
- SerializedUser: Serialized representation of the user
*/
SerializedUser User::serialize() const
{ {
SerializedUser serialized = {}; std::ostringstream serializedUser;
strcpy_s(serialized.id, sizeof(serialized.id), m_id.c_str()); serializedUser << m_id << ','
strcpy_s(serialized.username, sizeof(serialized.username), m_userName.c_str()); << m_userName << ','
strcpy_s(serialized.password, sizeof(serialized.password), m_password.c_str()); << m_password << ','
strcpy_s(serialized.name, sizeof(serialized.name), m_name.c_str()); << m_name << ','
strcpy_s(serialized.phone, sizeof(serialized.phone), m_phone.c_str()); << m_phone << ','
strcpy_s(serialized.email, sizeof(serialized.email), m_email.c_str()); << m_email << ','
serialized.userType = m_type; << util::getUserTypeString(m_type) << ','
serialized.status = m_status; << util::getStateString(m_status);
return serialized; return serializedUser.str();
} }
/* User* User::deserialize(const std::string& record)
Function: deserialize
Description: Deserializes a SerializedUser record into a User object.
Parameters:
- serializedUser: const SerializedUser&, serialized user record
Returns:
- User*: Pointer to the deserialized User object
*/
User* User::deserialize(const SerializedUser& serializedUser)
{ {
return Factory::getObject<User>( std::string id, name, username, phone, password, email;
serializedUser.id, std::string userTypeString, stateString;
serializedUser.username, std::istringstream serializedUser(record);
serializedUser.password, getline(serializedUser, id, ',');
serializedUser.name, getline(serializedUser, username, ',');
serializedUser.phone, getline(serializedUser, password, ',');
serializedUser.email, getline(serializedUser, name, ',');
serializedUser.userType, getline(serializedUser, phone, ',');
serializedUser.status); getline(serializedUser, email, ',');
} getline(serializedUser, userTypeString, ',');
getline(serializedUser, stateString);
util::UserType userType = util::getUserType(userTypeString);
util::State status = util::getState(stateString);
return Factory::getObject<User>(id,
username,
password,
name,
phone,
email,
userType,
status);
}
std::string User::getHeaders()
{
return "ID,Username,Password,Name,Phone,Email,UserType,UserStatus";
}
@@ -14,7 +14,6 @@ Date: 19-May-2026
#include "Enums.h" #include "Enums.h"
class Notification; class Notification;
struct SerializedUser;
class User : public Observer class User : public Observer
{ {
@@ -52,6 +51,7 @@ public:
void addNotification(Notification* notification) override; void addNotification(Notification* notification) override;
void setRole(util::UserType role); void setRole(util::UserType role);
void setState(util::State status); void setState(util::State status);
SerializedUser serialize() const; std::string serialize() const;
static User* deserialize(const SerializedUser& serializedUser); static User* deserialize(const std::string&);
static std::string getHeaders();
}; };
@@ -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,205 +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::PAID)
{
User* currentUser = invoice->getBooking()->getCustomer();
invoice->setPaymentMethod(paymentMode);
invoice->setPaymentDate(util::Timestamp());
invoice->setStatus(util::PaymentStatus::PAID);
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: getAllInvoice
Description: Provides access to all invoices stored in the data store.
Parameters:
- none
Returns:
- util::Map<std::string, Invoice*>&: Map of invoice IDs to invoice objects
*/
util::Map<std::string, Invoice*>& PaymentManagementService::getAllInvoices()
{
return m_dataStore.getInvoices();
}
/*
Function: confirmPayment
Description: Confirms payment for a specific invoice. Updates payment date and status,
then sends a notification to the customer.
Parameters:
- invoiceID: std::string, ID of the invoice to confirm
Returns:
- void
Throws:
- std::runtime_error if the invoice ID is invalid
*/
void PaymentManagementService::confirmPayment(const std::string& invoiceID)
{
auto& currentInvoices = m_dataStore.getInvoices();
int invoiceIndex = currentInvoices.find(invoiceID);
if (invoiceIndex == -1)
{
throw std::runtime_error("Payment confirmation failed: invalid invoice ID.");
}
Invoice* invoice = currentInvoices.getValueAt(invoiceIndex);
if (!invoice || invoice->getStatus() != util::PaymentStatus::PAID)
{
throw std::runtime_error("Payment confirmation failed: invoice is not awaiting confirmation.");
}
User* currentUser = invoice->getBooking()->getCustomer();
invoice->setStatus(util::PaymentStatus::COMPLETED);
std::string title = "Payment Confirmed";
std::string message = "Payment Confirmed for Invoice ID " + invoiceID;
sendNotification(currentUser, title, message);
}
@@ -28,8 +28,6 @@ public:
void generateInvoice(ServiceBooking* booking); void generateInvoice(ServiceBooking* booking);
util::Map<std::string, Invoice*> getInvoices(const std::string& customerID); util::Map<std::string, Invoice*> getInvoices(const std::string& customerID);
void completePayment(const std::string& invoiceID, util::PaymentMode paymentMode); void completePayment(const std::string& invoiceID, util::PaymentMode paymentMode);
util::Map<std::string, Invoice*>& getAllInvoices();
void confirmPayment(const std::string& invoiceID);
void sendPaymentReminders(); void sendPaymentReminders();
void sendNotification(User* user, const std::string& title, const std::string& message) override; void sendNotification(User* user, const std::string& title, const std::string& message) override;
void attach(User* user) override; void attach(User* user) override;
@@ -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"
@@ -37,7 +36,7 @@ public:
void createService(const std::string& name, const util::Vector<std::string>& inventoryItemIDs, double laborCost); void createService(const std::string& name, const util::Vector<std::string>& inventoryItemIDs, double laborCost);
void removeService(const std::string& serviceID); void removeService(const std::string& serviceID);
util::Map<std::string, JobCard*> getJobCards(const std::string& technicianID); util::Map<std::string, JobCard*> getJobCards(const std::string& technicianID);
void updateJobStatus(const std::string& jobID); void completeJob(const std::string& jobID);
void cancelCustomerServiceBookings(const std::string& customerID); void cancelCustomerServiceBookings(const std::string& customerID);
void cancelTechnicianJobs(const std::string& technicianID); void cancelTechnicianJobs(const std::string& technicianID);
void createComboPackage(const std::string& packageName, const util::Vector<std::string>& serviceIDs, double discountPercentage); void createComboPackage(const std::string& packageName, const util::Vector<std::string>& serviceIDs, double discountPercentage);
@@ -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,34 +12,22 @@ 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 "Vector.h"
#include "Validator.h"
#include "Utility.h" #include "Utility.h"
#include "TrackedRecord.h" #include "Vector.h"
#include "DataStoreLockGuard.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()
{ {
DataStoreLockGuard lock(m_dataStore);
auto& usersMap = m_dataStore.getUsers(); auto& usersMap = m_dataStore.getUsers();
int usersMapSize = usersMap.getSize(); int usersMapSize = usersMap.getSize();
bool isAdminFound = false; bool isAdminFound = false;
for (int index = 0; index < usersMapSize; index++) for (int index = 0; index < usersMapSize; index++)
{ {
User* user = usersMap.getValueAt(index).data; User* user = usersMap.getValueAt(index);
if (user && user->getUserType() == util::UserType::ADMIN) if (user && user->getUserType() == util::UserType::ADMIN)
{ {
isAdminFound = true; isAdminFound = true;
@@ -59,93 +46,103 @@ 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;
DataStoreLockGuard lock(m_dataStore); auto& usersMap = m_dataStore.getUsers();
auto& trackedUsersMap = m_dataStore.getUsers(); int index = usersMap.findIf(
auto usersMap = util::getObjects(trackedUsersMap); [&](const std::string&, User* user)
if (util::isUsernameDuplicate(username, usersMap)) {
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);
trackedUsersMap.insert(newUser->getId(), util::createNewRecord(newUser)); usersMap.insert(newUser->getId(), newUser);
paymentManagementService.attach(newUser); paymentManagementService.attach(newUser);
serviceManagementService.attach(newUser); serviceManagementService.attach(newUser);
if (newUser->getUserType() == util::UserType::ADMIN) if (newUser->getUserType() == util::UserType::ADMIN)
{ {
inventoryManagementService.attach(newUser); inventoryManagementService.attach(newUser);
} }
m_dataStore.saveUsers(); }
void UserManagementService::updateUserDetails(const std::string& userID, const std::string& email, const std::string& phone)
{
auto& usersMap = m_dataStore.getUsers();
int index = usersMap.find(userID);
if (index == -1)
{
throw std::runtime_error("User does not exist!");
}
User* user = usersMap.getValueAt(index);
user->setEmail(email);
user->setPhone(phone);
} }
/* /*
Function: updateUserDetails Function: getUsers
Description: Updates the email and phone details of an existing user. Description: Retrieves all users stored in the DataStore.
Throws an exception if the user does not exist. Parameter: None
Parameter: const std::string& userID - ID of the user to update Return type: util::Map<std::string, User*>
const std::string& email - new email address */
const std::string& phone - new phone number 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 Return type: void
*/ */
void UserManagementService::updateUserDetails(const std::string& userID, const std::string& email, const std::string& phone) void UserManagementService::removeUser(const std::string& userID)
{ {
DataStoreLockGuard lock(m_dataStore); int index = m_dataStore.getUsers().find(userID);
auto& trackedUsersMap = m_dataStore.getUsers(); if (index != -1)
auto usersMap = util::getObjects(trackedUsersMap);
int index = trackedUsersMap.find(userID);
if (index == -1)
{ {
throw std::runtime_error("User does not exist!\n"); User* user = m_dataStore.getUsers().getValueAt(index);
} if (user != nullptr)
User* user = trackedUsersMap.getValueAt(index).data;
bool isModified = false;
if (email != user->getEmail())
{
if (util::isEmailDuplicate(email, usersMap))
{ {
throw std::runtime_error("Email already exists!\n"); user->setState(util::State::INACTIVE);
} }
user->setEmail(email);
isModified = true;
}
if (phone != user->getPhone())
{
if (util::isPhoneDuplicate(phone, usersMap))
{
throw std::runtime_error("Phone number already exists!\n");
}
user->setPhone(phone);
isModified = true;
}
if (isModified)
{
trackedUsersMap.getValueAt(index).state = RecordState::MODIFIED;
m_dataStore.saveUsers();
} }
} }
@@ -161,13 +158,12 @@ Throws:
*/ */
util::Vector<Notification*> UserManagementService::getUserNotifications(const std::string& userID) util::Vector<Notification*> UserManagementService::getUserNotifications(const std::string& userID)
{ {
DataStoreLockGuard lock(m_dataStore); auto& usersMap = m_dataStore.getUsers();
auto& trackedUsersMap = m_dataStore.getUsers(); if (usersMap.find(userID) == -1)
if (trackedUsersMap.find(userID) == -1)
{ {
throw std::runtime_error("No user found with given UserID"); throw std::runtime_error("No user found with given UserID");
} }
User* user = trackedUsersMap[userID].data; User* user = usersMap[userID];
if (user) if (user)
{ {
auto& notifications = user->getNotifications(); auto& notifications = user->getNotifications();
@@ -175,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;
} }
@@ -187,136 +183,74 @@ util::Vector<Notification*> UserManagementService::getUserNotifications(const st
/* /*
Function: deleteNotification Function: deleteNotification
Description: Marks a specific notification associated with a given user Description: Deletes a specific notification associated with a given user ID.
as inactive.
Parameters: Parameters:
- notificationID: The unique ID of the notification to be deleted. - notificationID: The unique ID of the notification to be deleted.
- userID: The unique ID of the user whose notification is to be deleted. - userID: The unique ID of the user whose notification is to be deleted.
Returns: Returns:
- void - void
Throws: Throws:
- std::runtime_error if no user is found with the given UserID or - std::runtime_error if no user is found with the given UserID or if no notification is found with the given NotificationID.
if no notification is found with the given NotificationID.
*/ */
void UserManagementService::deleteNotification(const std::string& notificationID, const std::string& userID) void UserManagementService::deleteNotification(const std::string& notificationID, const std::string& userID)
{ {
DataStoreLockGuard lock(m_dataStore); auto& usersMap = m_dataStore.getUsers();
auto& trackedUsersMap = m_dataStore.getUsers(); if (usersMap.find(userID) == -1)
auto& trackedNotificationsMap = m_dataStore.getNotifications();
int userIndex = trackedUsersMap.find(userID);
if (userIndex == -1)
{ {
throw std::runtime_error("No user found with given UserID"); throw std::runtime_error("No user found with given UserID");
} }
User* user = trackedUsersMap.getValueAt(userIndex).data; User* user = usersMap[userID];
auto& notifications = user->getNotifications(); auto& notifications = user->getNotifications();
if (notifications.find(notificationID) == -1) if (notifications.find(notificationID) == -1)
{ {
throw std::runtime_error("No notification found with given NotificationID"); throw std::runtime_error("No notification found with given NotificationID");
} }
int notificationIndex = trackedNotificationsMap.find(notificationID); notifications.remove(notificationID);
if (notificationIndex == -1)
{
throw std::runtime_error("No notification found with given NotificationID");
}
notifications[notificationID]->setState(util::State::INACTIVE);
trackedNotificationsMap.getValueAt(notificationIndex).state = RecordState::MODIFIED;
m_dataStore.saveNotifications();
} }
/* void UserManagementService::loadUsers()
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()
{ {
DataStoreLockGuard lock(m_dataStore); util::FileManager<User> userFileManager(config::file::USER_FILE);
auto users = util::getObjects(m_dataStore.getUsers()); util::FileManager<Notification> notificationFileManager(config::file::NOTIFICATION_FILE);
return users; auto& users = m_dataStore.getUsers();
auto usersMap = userFileManager.load();
auto notificationsMap = notificationFileManager.load();
int numberOfUsers = usersMap.getSize();
int numberOfNotifications = notificationsMap.getSize();
for (int index = 0; index < numberOfUsers; index++)
{
users[usersMap.getKeyAt(index)] = usersMap.getValueAt(index);
}
for (int index = 0; index < numberOfNotifications; index++)
{
Notification* notification = notificationsMap.getValueAt(index);
const std::string& recipientUserId = notification->getRecipientUserId();
int userIndex = users.find(recipientUserId);
if (userIndex == -1)
{
throw std::runtime_error("Invalid recipient user ID");
}
User* user = users.getValueAt(userIndex);
user->addNotification(notification);
}
} }
/* void UserManagementService::saveUsers()
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)
{ {
DataStoreLockGuard lock(m_dataStore); util::FileManager<User> userFileManager(config::file::USER_FILE);
auto& trackedUsersMap = m_dataStore.getUsers(); util::FileManager<Notification> notificationFileManager(config::file::NOTIFICATION_FILE);
int index = trackedUsersMap.find(userID); auto& users = m_dataStore.getUsers();
if (index != -1) util::Map<std::string, Notification*> notifications;
{ for (int userIndex = 0; userIndex < users.getSize(); userIndex++)
return trackedUsersMap.getValueAt(index).data; {
} User* user = users.getValueAt(userIndex);
return nullptr; auto& userNotifications = user->getNotifications();
for (int notificationIndex = 0; notificationIndex < userNotifications.getSize(); notificationIndex++)
{
notifications[userNotifications.getKeyAt(notificationIndex)] =
userNotifications.getValueAt(notificationIndex);
}
}
userFileManager.save(users);
notificationFileManager.save(notifications);
} }
/*
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;
DataStoreLockGuard lock(m_dataStore);
auto& trackedUsersMap = m_dataStore.getUsers();
int index = trackedUsersMap.find(userID);
if (index != -1)
{
User* user = trackedUsersMap.getValueAt(index).data;
if (user != nullptr)
{
if (user->getUserType() == util::UserType::CUSTOMER)
{
serviceManagementService.cancelCustomerServiceBookings(userID);
}
if (user->getUserType() == util::UserType::TECHNICIAN)
{
serviceManagementService.cancelTechnicianJobs(userID);
}
inventoryManagementService.detach(user);
paymentManagementService.detach(user);
serviceManagementService.detach(user);
user->setState(util::State::INACTIVE);
trackedUsersMap.getValueAt(index).state = RecordState::MODIFIED;
m_dataStore.saveUsers();
}
}
}
/*
Function: getUsers
Description: Retrieves all active users of the specified type from
the DataStore.
Parameters:
- type: The user type to filter by
(ADMIN, CUSTOMER, or TECHNICIAN).
Returns:
- util::Map<std::string, User*>:
Collection of active users matching the specified type,
keyed by user ID.
*/
util::Map<std::string, User*> UserManagementService::getUsers(util::UserType type)
{
DataStoreLockGuard lock(m_dataStore);
auto& trackedUsersMap = m_dataStore.getUsers();
util::Map<std::string, User*> currentUsers = util::getObjects(trackedUsersMap);
util::Map<std::string, User*> filteredUsersMap;
for (int index = 0; index < currentUsers.getSize(); index++)
{
User* currentUser = currentUsers.getValueAt(index);
if (currentUser && currentUser->getState() == util::State::ACTIVE && currentUser->getUserType() == type)
{
filteredUsersMap.insert(currentUser->getId(), currentUser);
}
}
return filteredUsersMap;
}
@@ -1,12 +1,10 @@
/* /*
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
*/ */
#pragma once #pragma once
#include <string> #include <string>
#include "Map.h" #include "Map.h"
@@ -31,4 +29,6 @@ public:
util::Vector<Notification*> getUserNotifications(const std::string& userID); util::Vector<Notification*> getUserNotifications(const std::string& userID);
void deleteNotification(const std::string& notificationID, const std::string& userID); void deleteNotification(const std::string& notificationID, const std::string& userID);
void ensureAdminExists(); void ensureAdminExists();
void loadUsers();
void saveUsers();
}; };
@@ -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
*/ */
@@ -28,18 +27,16 @@ namespace config
namespace file namespace file
{ {
const size_t INITIAL_CAPACITY = 100; constexpr const char* INVENTORYITEM_FILE = "files/InventoryItem.csv";
constexpr const char* DIRECTORY = "files/"; constexpr const char* USER_FILE = "files/User.csv";
constexpr const char* INVENTORYITEM_FILE = "files/InventoryItem.dat"; constexpr const char* NOTIFICATION_FILE = "files/Notification.csv";
constexpr const char* USER_FILE = "files/User.dat"; constexpr const char* SERVICE_FILE = "files/Service.csv";
constexpr const char* NOTIFICATION_FILE = "files/Notification.dat"; constexpr const char* COMBOPACKAGE_FILE = "files/ComboPackage.csv";
constexpr const char* SERVICE_FILE = "files/Service.dat"; constexpr const char* SERVICEBOOKING_FILE = "files/ServiceBooking.csv";
constexpr const char* COMBOPACKAGE_FILE = "files/ComboPackage.dat"; constexpr const char* JOBCARD_FILE = "files/JobCard.csv";
constexpr const char* SERVICEBOOKING_FILE = "files/ServiceBooking.dat"; constexpr const char* INVOICE_FILE = "files/Invoice.csv";
constexpr const char* JOBCARD_FILE = "files/JobCard.dat"; constexpr const char* SERVICEMANAGEMENTOBSERVERS = "files/ServiceManagementObservers.csv";
constexpr const char* INVOICE_FILE = "files/Invoice.dat"; constexpr const char* PAYMENTMANAGEMENTOBSERVERS = "files/PaymentManagementObservers.csv";
constexpr const char* SERVICEMANAGEMENTOBSERVERS = "files/ServiceManagementObservers.dat"; constexpr const char* INVENTORYMANAGEMENTOBSERVERS = "files/InventoryManagementObservers.csv";
constexpr const char* PAYMENTMANAGEMENTOBSERVERS = "files/PaymentManagementObservers.dat";
constexpr const char* INVENTORYMANAGEMENTOBSERVERS = "files/InventoryManagementObservers.dat";
} }
} }
@@ -12,37 +12,35 @@ Date: 19-May-2026
namespace util namespace util
{ {
enum class UserType : int enum class UserType
{ {
ADMIN, ADMIN,
TECHNICIAN, TECHNICIAN,
CUSTOMER CUSTOMER
}; };
enum class PaymentMode : int enum class PaymentMode
{ {
ONLINE, ONLINE,
OFFLINE, OFFLINE,
NOTSET NOTSET
}; };
enum class PaymentStatus : int enum class PaymentStatus
{ {
PENDING, PENDING,
COMPLETED, COMPLETED
PAID
}; };
enum class ServiceJobStatus : int enum class ServiceJobStatus
{ {
PENDING, PENDING,
STARTED, STARTED,
COMPLETED, COMPLETED,
IN_PROGRESS,
CANCELLED CANCELLED
}; };
enum class State : int enum class State
{ {
ACTIVE, ACTIVE,
INACTIVE INACTIVE
@@ -139,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");
} }
@@ -162,8 +156,6 @@ namespace util
return "PENDING"; return "PENDING";
case PaymentStatus::COMPLETED: case PaymentStatus::COMPLETED:
return "COMPLETED"; return "COMPLETED";
case PaymentStatus::PAID:
return "PAID";
} }
throw std::invalid_argument("Invalid PaymentStatus"); throw std::invalid_argument("Invalid PaymentStatus");
} }
@@ -213,8 +205,6 @@ namespace util
return "COMPLETED"; return "COMPLETED";
case ServiceJobStatus::CANCELLED: case ServiceJobStatus::CANCELLED:
return "CANCELLED"; return "CANCELLED";
case ServiceJobStatus::IN_PROGRESS:
return "IN_PROGRESS";
} }
throw std::invalid_argument("Invalid ServiceJobStatus"); throw std::invalid_argument("Invalid ServiceJobStatus");
} }
@@ -247,10 +237,6 @@ namespace util
{ {
return ServiceJobStatus::CANCELLED; return ServiceJobStatus::CANCELLED;
} }
if (value == "IN_PROGRESS")
{
return ServiceJobStatus::IN_PROGRESS;
}
throw std::invalid_argument("Invalid ServiceJobStatus string"); throw std::invalid_argument("Invalid ServiceJobStatus string");
} }
@@ -296,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);
@@ -106,4 +44,4 @@ namespace util
file << records[index] << '\n'; file << records[index] << '\n';
} }
} }
} }
@@ -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)
{ {
@@ -10,7 +10,6 @@
#include <limits> #include <limits>
#include <string> #include <string>
#include <stdexcept> #include <stdexcept>
#include <conio.h>
namespace util namespace util
{ {
@@ -55,48 +54,6 @@ namespace util
value = cleanedValue; value = cleanedValue;
} }
/*
* Function: readPassword
* Description: Reads a password from console without echoing characters;
* displays '*' for each character typed, handles backspace,
* and cleans commas from the result.
* Parameters:
* value - reference to a string where the password will be stored
* Returns:
* void - no return value
*/
inline void readPassword(std::string& value)
{
value.clear();
char currentCharacter;
while ((currentCharacter = _getch()) != '\r')
{
if (currentCharacter == '\b')
{
if (!value.empty())
{
value.pop_back();
std::cout << "\b \b";
}
}
else
{
value += currentCharacter;
std::cout << '*';
}
}
std::cout << std::endl;
std::string cleanedValue;
for (int iterator = 0; iterator < value.length(); iterator++)
{
if (value[iterator] != ',')
{
cleanedValue += value[iterator];
}
}
value = cleanedValue;
}
/* /*
* Function: pressEnter * Function: pressEnter
* Description: Pauses execution until the user presses Enter. * Description: Pauses execution until the user presses Enter.
@@ -105,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,95 +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);
} }
template<typename TObject>
Map<std::string, TObject*> getObjects(const Map<std::string, TrackedRecord<TObject>>& trackedRecords);
template<typename TObject>
Map<std::string, const TObject*> getConstObjects(const Map<std::string, TrackedRecord<TObject>>& trackedRecords);
template<typename TObject>
TrackedRecord<TObject> createNewRecord(TObject* object);
} }
/*
Function: getObjects
Description: Extracts the object pointers from a tracked-record
collection and returns them as a map keyed by the
same identifiers.
Parameters:
- trackedRecords: Collection of tracked records.
Returns:
- Map<std::string, TObject*>: Collection of object pointers.
*/
template<typename TObject>
util::Map<std::string, TObject*> util::getObjects(const util::Map<std::string, TrackedRecord<TObject>>& trackedRecords)
{
util::Map<std::string, TObject*> objects;
for (int index = 0; index < trackedRecords.getSize(); ++index)
{
const std::string& key = trackedRecords.getKeyAt(index);
TObject* object = trackedRecords.getValueAt(index).data;
objects.insert(key, object);
}
return objects;
}
/*
Function: getConstObjects
Description: Extracts the object pointers from a tracked-record
collection and returns them as a read-only map
keyed by the same identifiers.
Parameters:
- trackedRecords: Collection of tracked records.
Returns:
- Map<std::string, const TObject*>:
Collection of read-only object pointers.
*/
template<typename TObject>
util::Map<std::string, const TObject*> util::getConstObjects(
const util::Map<std::string, TrackedRecord<TObject>>& trackedRecords)
{
util::Map<std::string, const TObject*> objects;
for (int index = 0; index < trackedRecords.getSize(); ++index)
{
const std::string& key = trackedRecords.getKeyAt(index);
const TObject* object = trackedRecords.getValueAt(index).data;
objects.insert(key, object);
}
return objects;
}
/*
Function: createNewRecord
Description: Creates a tracked record for a newly created
object. The record is initialized with
NEW_RECORD state.
Parameters:
- object: Pointer to the newly created object.
Returns:
- TrackedRecord<TObject>: Initialized tracked record.
*/
template<typename TObject>
TrackedRecord<TObject> util::createNewRecord(TObject* object)
{
TrackedRecord<TObject> record;
record.data = object;
record.state = RecordState::NEW_RECORD;
return record;
}
@@ -106,68 +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
*/
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);
}
);
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*>&);
} }
File diff suppressed because it is too large Load Diff
@@ -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"
@@ -24,14 +23,10 @@ public:
void removeInventoryItem(); void removeInventoryItem();
void checkStockAvailability(); void checkStockAvailability();
void assignJob(); void assignJob();
void displayServices();
void createService(); void createService();
void removeService(); void removeService();
void displayUsers();
void confirmPayment();
void addTechnician(); void addTechnician();
void removeUser(); void removeUser();
void displayComboPackages();
void createComboPackages(); void createComboPackages();
void removeComboPackage(); void removeComboPackage();
void viewNotifications(); void viewNotifications();
@@ -1,34 +1,40 @@
/* /*
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()
{ {
@@ -64,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)
@@ -111,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;
} }
@@ -156,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)
{ {
@@ -194,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: ";
@@ -206,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: ";
@@ -244,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++)
{ {
@@ -283,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;
} }
@@ -298,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::string selectedID = selectInvoiceFromUserForPayment(currentInvoices);
{
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, util::PaymentStatus::PENDING);
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();
} }
/* /*
@@ -380,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
@@ -397,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"
@@ -34,11 +35,10 @@ void TechnicianMenu::showMenu()
int choice; int choice;
util::clear(); util::clear();
std::cout << "Technician Menu" std::cout << "Technician Menu"
<< "\n1. Display My Jobs" << "\n1. Mark Job as Completed"
<< "\n2. Update Job Status" << "\n2. View Notifications"
<< "\n3. View Notifications" << "\n3. Change Password"
<< "\n4. Change Password" << "\n4. Logout"
<< "\n5. Logout"
<< "\nEnter a choice: "; << "\nEnter a choice: ";
util::read(choice); util::read(choice);
if (!handleOperation(choice)) if (!handleOperation(choice))
@@ -65,18 +65,15 @@ bool TechnicianMenu::handleOperation(int choice)
switch (choice) switch (choice)
{ {
case 1: case 1:
displayJobs(); completeJob();
break; break;
case 2: case 2:
updateJobStatus();
break;
case 3:
viewNotifications(); viewNotifications();
break; break;
case 4: case 3:
changePassword(); changePassword();
break; break;
case 5: case 4:
logout(); logout();
return false; return false;
default: default:
@@ -86,65 +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: displayJobs
Description: Displays all Jobs assigned to a Technician
Parameters:
- None
Returns:
- void
*/
void TechnicianMenu::displayJobs()
{ {
util::clear(); int currentIndex = 1;
std::cout << "My Jobs\n";
util::Map<std::string, const JobCard*> assignedJobCards = m_controller.getJobCardsByUser();
util::Map<std::string, const JobCard*> jobCards = filterStartedJobCards(assignedJobCards);
displayAllJobs(jobCards);
util::pressEnter();
}
/*
Function: updateJobStatus
Description: Allows the technician to update a selected job card.
Validates selection and updates job status through the controller.
Parameters:
- None
Returns:
- void
*/
void TechnicianMenu::updateJobStatus()
{
util::clear();
std::cout << "Update Job Status\n";
int choice; int choice;
std::string selectedJobID; bool hasIncompleteJobCard = false;
util::ServiceJobStatus selectedJobStatus = util::ServiceJobStatus::PENDING; std::cout << std::left
util::Map<std::string, const JobCard*> assignedJobCards = m_controller.getJobCardsByUser(); << std::setw(6) << "Index"
std::cout << "Select the type of job you want to update:\n1.Started\n2.In Progress\nChoice: "; << std::setw(12) << "BookingID"
util::read(choice); << std::setw(12) << "JobID"
if (choice == 1) << std::setw(20) << "ServiceName"
<< std::setw(12) << "ServiceID"
<< std::endl;
for (int iterator = 0; iterator < assignedJobCards.getSize(); iterator++)
{ {
selectedJobStatus = util::ServiceJobStatus::STARTED; 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);
}
} }
else if (choice == 2) if (!hasIncompleteJobCard)
{ {
selectedJobStatus = util::ServiceJobStatus::IN_PROGRESS; 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 else
{ {
std::cout << "Invalid choice. Please try again.\n"; std::cout << "Invalid choice.\n";
util::pressEnter(); return "";
return;
} }
util::Map<std::string, const JobCard*> selectedTypeJobCard = filterJobCards(assignedJobCards, selectedJobStatus); }
selectedJobID = selectJobCardToUpdate(selectedTypeJobCard, selectedJobStatus);
if (!selectedJobID.empty())
void TechnicianMenu::completeJob()
{
util::Map<std::string, const JobCard*> assignedJobCards = m_controller.getJobCardsByUser();
util::Map<int, const JobCard*> incompleteJobCards;
std::cout << "Jobs to be completed.\n";
std::string selectedJobID = selectJobCardToComplete(assignedJobCards, incompleteJobCards);
if (selectedJobID == "")
{ {
m_controller.updateJobStatus(selectedJobID); std::cout << "Failed to complete the job.\n";
std::cout << "\nJob status updated.\n\n"; }
else
{
m_controller.completeJob(selectedJobID);
std::cout << "Job marked as completed.\n";
} }
util::pressEnter();
} }
/* /*
@@ -168,7 +169,7 @@ Return type: void
*/ */
void TechnicianMenu::logout() void TechnicianMenu::logout()
{ {
m_controller.logout(); m_controller.logout();
} }
/* /*
@@ -177,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"
@@ -17,9 +16,8 @@ private:
bool handleOperation(int choice); bool handleOperation(int choice);
public: public:
void showMenu(); void showMenu();
void displayJobs(); void completeJob();
void updateJobStatus();
void viewNotifications(); void viewNotifications();
void logout(); void logout();
void changePassword(); void changePassword();
}; };
@@ -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,47 +22,29 @@ Return type: void
*/ */
void UserInterface::run() void UserInterface::run()
{ {
try m_controller.loadSystemData();
m_controller.runSystemChecks();
bool isMenuActive = true;
while (isMenuActive)
{ {
if (!m_controller.initialize()) try
{ {
std::cout << "Error: Failed to initialize the system!"; int choice;
return; util::clear();
} std::cout << "Vehicle Service System\n1. Login\n2. Register Customer\n3. Exit\nEnter your Choice: ";
bool isMenuActive = true; util::read(choice);
while (isMenuActive) if (!handleOperation(choice))
{
try
{ {
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.shutdown(); 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();
} }
/* /*
@@ -105,15 +84,14 @@ 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: ";
util::readPassword(password); util::read(password);
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())
{ {
@@ -131,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: ";
@@ -170,7 +141,7 @@ void UserInterface::registerCustomer()
return; return;
} }
std::cout << "Enter password: "; std::cout << "Enter password: ";
util::readPassword(password); util::read(password);
if (!util::isPasswordValid(password)) if (!util::isPasswordValid(password))
{ {
std::cout << "Error: Password is invalid!"; std::cout << "Error: Password is invalid!";
@@ -188,4 +159,4 @@ void UserInterface::registerCustomer()
m_controller.createCustomer(username, name, password, email, phone); m_controller.createCustomer(username, name, password, email, phone);
std::cout << "Registration is successful"; std::cout << "Registration is successful";
util::pressEnter(); util::pressEnter();
} }
@@ -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"
@@ -27,4 +26,4 @@ public:
void run(); void run();
void login(); void login();
void registerCustomer(); void registerCustomer();
}; };