Compare commits

..

22 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
Jissin Mathew 0adb864329 Merge branch 'feature-service-management-ser005' into feature-service-management 2026-05-21 18:34:12 +05:30
Jissin Mathew a3ad4d2e00 Merge branch 'feature-payment-management-pay003' into feature-payment-management 2026-05-21 18:11:09 +05:30
Jissin Mathew 86fd32bd2b Merge branch 'feature-service-management-ser004' into feature-service-management 2026-05-21 17:26:27 +05:30
Jissin Mathew fceb1cbec6 Merge branch 'feature-service-management-ser003' into feature-service-management 2026-05-21 17:10:53 +05:30
Jissin Mathew 53ff70a85f Merge branch 'feature-service-management-ser002' into feature-service-management 2026-05-21 16:54:07 +05:30
Jissin Mathew 4a4309d585 Merge branch 'feature-payment-management-pay002' into feature-payment-management 2026-05-21 16:20:42 +05:30
Jissin Mathew 61f70a54f6 Implement Generate Invoice
<UserStory> PAY001: Generate Invoice </UserStory>

<Changes>
    1. Added Utility.h to project configuration for supporting invoice generation utilities.
    2. Updated Invoice model to use string-based keys for parts mapping instead of integer keys.
    3. Implemented PaymentManagementService::generateInvoice to aggregate labour cost, parts cost, and apply discounts.
    4. Integrated invoice creation with Factory to instantiate Invoice objects and persist them into datastore.
    5. Enhanced Enums with PaymentMode::NOTSET to handle default invoice state.
</Changes>

<Test>

 Acceptance Criteria:
 1. Invoice auto-generates for each service booking once jobs are completed.
 2. Invoice shows a clear breakdown of charges including labour cost, parts cost, discount, and total amount.

 Precondition:
  1. Service booking exists with at least one service and required inventory items.
  2. Datastore is available for storing invoices.
  3. Payment mode and status enums are properly configured.

 Steps:
  1. Complete all jobs in a service booking.
    - Verify that PaymentManagementService::generateInvoice is triggered.
  2. Check datastore for newly created invoice.
    - Verify that invoice contains booking ID, labour cost, parts cost, discount, and total amount.
  3. Inspect invoice details.
    - Verify that breakdown of charges is accurate and discount is applied correctly.
  4. Confirm invoice status.
    - Verify that invoice is created with PaymentMode::NOTSET and PaymentStatus::PENDING.
</Test>

<Review>
Sreeja Reghukumar, please review
</Review>
2026-05-21 16:05:10 +05:30
Jissin Mathew 461857f971 Implement View Invoices for Customer
<UserStory> PAY003: View Invoices </UserStory>

<Changes>
    1. Added CustomerMenu::viewInvoices to fetch invoices via Controller and display them to the customer.
    2. Implemented displayInvoices helper to show invoice details including booking, vehicle, technician, discount, total amount, invoice date, and payment status.
    3. Enhanced invoice display to include a tabular breakdown of inventory items (ItemName, Quantity, Price) used in the service.
    4. Updated ServiceBooking to store assigned technician as a const User* for richer technician details in invoice output.
</Changes>

<Test>

 Acceptance Criteria:
 1. Invoice details should show total cost and discounts.
 2. Invoice details should show list of parts used.

 Precondition:
  1. Customer is logged into the system.
  2. At least one invoice exists for the customer in the datastore.
  3. Inventory items are linked to the invoice.

 Steps:
  1. Navigate to Customer menu and choose "View Invoices".
    - Verify that the system lists invoice details including booking ID, vehicle info, technician, discount, total amount, invoice date, and payment status.
  2. Check the parts list under each invoice.
    - Verify that inventory items are displayed in tabular form with ItemName, Quantity, and Price.
  3. Confirm that discounts and total cost are shown correctly.
</Test>

<Review>
Sreeja Reghukumar, please review
</Review>
2026-05-21 15:09:16 +05:30
Jissin Mathew cb3bed4050 Implement Complete Payments
<UserStory> PAY002: Complete Payments </UserStory>

<Changes>
    1. Integrated Controller with PaymentManagementService to support payment completion workflow.
    2. Implemented PaymentManagementService::completePayment with validation for invoice ID, payment mode, and status update.
    3. Enhanced CustomerMenu with helper functions to display pending invoices in tabular format and allow index-based selection.
    4. Added CustomerMenu::selectPaymentMode to capture payment mode choice (OFFLINE/ONLINE).
    5. Updated CustomerMenu::completePayments to handle invoice selection, payment mode input, and trigger payment completion via Controller.
    6. Implemented notification logic to send confirmation to customers upon successful payment.
</Changes>

<Test>

 Acceptance Criteria:
 1. Payment status marked completed.
 2. Confirmation message shown.
 3. Confirmation notification sent.

 Precondition:
  1. Customer is logged into the system.
  2. At least one pending invoice exists for the customer.
  3. Datastore is available for storing invoices and updating payment status.

 Steps:
  1. Navigate to Customer menu and choose "Complete Payments".
    - Verify that the system lists pending invoices with tabular details.
  2. Select an invoice by index.
    - Verify that the chosen invoice is retrieved correctly.
  3. Enter payment mode (OFFLINE/ONLINE).
    - Verify that the selected mode is applied to the invoice.
  4. Confirm payment completion.
    - Verify that the invoice status changes to COMPLETED.
    - Verify that a confirmation message is displayed.
    - Verify that a notification is sent to the customer.
</Test>

<Review>
Sreeja Reghukumar, please review
</Review>
2026-05-21 15:08:25 +05:30
Jissin Mathew 8162a2fe3d Implement Update Service Status
<UserStory> SER005: Update Service Status </UserStory>

<Changes>
    1. Integrated Controller with ServiceManagementService to support job completion workflow.
    2. Implemented ServiceManagementService::completeJob with validation for technician assignment, job existence, and status transition.
    3. Enhanced TechnicianMenu with job selection helper to display assigned jobs, allow index-based selection, and handle invalid choices.
    4. Updated TechnicianMenu::completeJob to mark job as completed via Controller and provide user feedback.
    5. Added logic to check if all jobs in a booking are completed, triggering invoice generation and customer notification.
</Changes>

<Test>

 Acceptance Criteria:
 1. Status updates are visible to customers immediately after technician marks job as completed.

 Precondition:
  1. Technician is logged into the system.
  2. At least one active job card is assigned to the technician.
  3. Datastore contains valid service bookings linked to jobs.

 Steps:
  1. Navigate to Technician menu and choose "Complete Job".
    - Verify that the system lists active jobs with index-based selection.
  2. Select a job card by index.
    - Verify that the job status changes from STARTED to COMPLETED.
  3. Check customer view.
    - Verify that the updated status is reflected in the customer’s booking history.
  4. If all jobs in the booking are completed:
    - Verify that an invoice is generated and a notification is sent to the customer.
</Test>

<Review>
Sreeja Reghukumar, please review
</Review>
2026-05-21 15:02:46 +05:30
Jissin Mathew fc7bb2569b Implement View Service History
<UserStory> SER004: View Service History </UserStory>

<Changes>
    1. Added integration between Controller and ServiceManagementService to fetch service bookings by customer ID.
    2. Enhanced ServiceBooking model to store technician as a User* instead of a string for richer details.
    3. Implemented Controller::getServiceBookingsByUser to return a read-only map of bookings for safe access.
    4. Updated CustomerMenu::viewServiceHistory to display bookings in tabular format with aligned columns.
    5. Added condition check to show technician name if assigned, otherwise display "Not Assigned".
    6. Included booking status and discount percentage in the service history output.
</Changes>

<Test>

 Acceptance Criteria:
 1. System should fetch real-time status.
 2. Status should update automatically when technician changes it.
 3. Customer should be able to view history.

  Precondition:
  1. Customer is logged into the console application.
  2. At least one active service booking exists for the customer.
  3. Technician has permission to update booking status.

  Steps:
  1. Navigate to Customer menu and choose "View Service History".
    - Verify that the console displays current booking status along with technician assignment.
  2. Technician updates the status of a booking.
    - Verify that the console view reflects the updated status automatically.
  3. Customer views service history again.
    - Verify that the history shows the latest status changes.
</Test>

<Review>
Sreeja Reghukumar, please review
</Review>
2026-05-21 14:59:18 +05:30
Jissin Mathew 70e1ef66d4 Implement Remove Service for admin
<UserStory> SER003: Remove Service </UserStory>

<Changes>
    1. Added integration between Controller and ServiceManagementService to support service removal.
    2. Implemented ServiceManagementService::removeService with validation for service existence and marking as INACTIVE.
    3. Enhanced Controller::getServices to return a read-only map of services for safe UI access.
    4. Added AdminMenu::selectServicesToRemove helper to list active services in tabular format and capture user choice.
    5. Updated AdminMenu::removeService to prompt for service selection, delegate removal to Controller, and display success/failure messages.
</Changes>

<Test>

 Acceptance Criteria:
 1. Admin selects service ID.
 2. System confirms deletion.
 3. Service removed from customer menu.

  Precondition:
  1. Admin is logged into the system.
  2. At least one active service exists in the datastore.
  3. Customer menu displays available services.

  Steps:
  1. Navigate to Admin menu and choose "Remove Service".
    - Verify that the system lists active services in tabular format.
  2. Select a service ID from the list.
    - Verify that the system confirms deletion.
  3. Check customer menu.
    - Verify that the removed service no longer appears.
</Test>

<Review>
Sreeja Reghukumar, please review
</Review>
2026-05-21 14:54:33 +05:30
Jissin Mathew e7f1b51d05 Implement Create Service for admin
<UserStory> SER002: Create Service </UserStory>

<Changes>
    1. Added integration between Controller and ServiceManagementService to support service creation.
    2. Implemented ServiceManagementService::createService with validation for duplicate service IDs and insertion into datastore.
    3. Enhanced AdminMenu with selectInventoryItems helper to display inventory in tabular format, allow selection, and handle exit condition.
    4. Updated AdminMenu::createService to prompt for service name, allow inventory selection, capture labour cost, and create service via Controller.
</Changes>

<Test>

 Acceptance Criteria:
 1. Admin enters new service name.
 2. Admin selects required parts for the services.
 3. Service created and visible to customers.

  Precondition:
  1. Admin is logged into the system.
  2. Inventory contains at least one active item.
  3. Datastore is available for storing services.

  Steps:
  1. Navigate to Admin menu and choose "Create Service".
    - Verify that the system prompts for service name.
  2. Select inventory items from the tabular list.
    - Verify that inactive items are skipped and active items can be added.
  3. Enter labour cost and confirm creation.
    - Verify that the service is created successfully and stored in datastore.
  4. Check customer view.
    - Verify that the newly created service is visible to customers.
</Test>

<Review>
Sreeja Reghukumar, please review
</Review>
2026-05-21 14:51:59 +05:30
Jissin Sam Mathew 9b7d9cf7c1 Implement Assign Job to Technician functionality
<UserStory> SER001: Assign job to technician </UserStory>

<Changes>
    1. Added ServiceManagementService logic to retrieve service bookings and create job cards for assigned technicians.
    2. Added UserManagementService support to retrieve technicians by user type and fetch technician details by ID.
    3. Connected Controller methods with ServiceManagementService and UserManagementService for service booking retrieval, technician listing, and job card creation.
    4. Updated JobCard model to use util::ServiceJobStatus consistently and simplified constructor initialization for assigned and completion timestamps.
    5. Added PENDING status in ServiceJobStatus enum for identifying unassigned service bookings.
    6. Implemented AdminMenu job assignment flow to list pending service bookings, display available technicians, allow technician selection, and assign jobs for services in the booking.
    7. Added notification trigger during job card creation for assigned technicians.
</Changes>

<Test>

Job assignment functionality validation

Precondition:
1. System is running.
2. Pending service bookings are available in the system.
3. Technician users are available in the system.
4. Admin user is logged in and admin menu is active.

Steps:
1. Launch the application and log in as an admin.
2. Select the Assign Job option from the admin menu.
3. View the list of available pending service bookings.
   - Verify that pending bookings are displayed.
4. Select a valid service booking.
5. View the list of available technicians.
   - Verify that technicians are listed for selection.
6. Select a technician to assign the job.
   - Verify that job cards are created for services in the booking.
   - Verify that assigned jobs are visible in the technician’s menu.
   - Verify that a confirmation message is shown.
   - Verify that a confirmation notification is sent to the assigned technician.

</Test>

<Review>
Sreeja Reghukumar, please review
</Review>
2026-05-21 14:50:43 +05:30
37 changed files with 2093 additions and 2148 deletions
@@ -233,6 +233,12 @@
<ClInclude Include="models\ComboPackage.h"> <ClInclude Include="models\ComboPackage.h">
<Filter>Header Files\Models</Filter> <Filter>Header Files\Models</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="views\MenuHelper.h">
<Filter>Header Files\Views</Filter>
</ClInclude>
<ClInclude Include="utilities\Utility.h">
<Filter>Header Files\Utilities</Filter>
</ClInclude>
<ClInclude Include="utilities\Config.h"> <ClInclude Include="utilities\Config.h">
<Filter>Header Files\Utilities</Filter> <Filter>Header Files\Utilities</Filter>
</ClInclude> </ClInclude>
@@ -245,11 +251,5 @@
<ClInclude Include="utilities\FileHelper.h"> <ClInclude Include="utilities\FileHelper.h">
<Filter>Header Files\Utilities</Filter> <Filter>Header Files\Utilities</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="utilities\Utility.h">
<Filter>Header Files\Utilities</Filter>
</ClInclude>
<ClInclude Include="views\MenuHelper.h">
<Filter>Header Files\Views</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>
@@ -1,24 +1,29 @@
/* /*
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 <stdexcept>
#include "Controller.h" #include "Controller.h"
#include "Enums.h"
#include "User.h"
#include "ComboPackage.h" #include "ComboPackage.h"
#include "Enums.h"
#include "InventoryItem.h"
#include "Invoice.h"
#include "JobCard.h"
#include "Service.h"
#include "ServiceBooking.h"
#include "User.h" #include "User.h"
#include "User.h"
#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)
{ {
@@ -27,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
*/ */
@@ -38,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)
@@ -47,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();
@@ -89,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();
@@ -108,7 +91,13 @@ void Controller::updateUserDetails(const std::string& email, const std::string&
util::Map<std::string, const Service*> Controller::getServices() util::Map<std::string, const Service*> Controller::getServices()
{ {
return util::Map<std::string, const Service*>(); util::Map<std::string, Service*> currentServices = m_serviceManagementService.getServices();
util::Map<std::string, const Service*> readOnlyServices;
for (int iterator = 0; iterator < currentServices.getSize(); iterator++)
{
readOnlyServices.insert(currentServices.getValueAt(iterator)->getId(), currentServices.getValueAt(iterator));
}
return readOnlyServices;
} }
/* /*
@@ -133,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);
@@ -170,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;
} }
@@ -229,12 +200,24 @@ void Controller::addInventoryItemStock(const std::string& selectedItemId, int qu
util::Map<std::string, const ServiceBooking*> Controller::getServiceBookings() util::Map<std::string, const ServiceBooking*> Controller::getServiceBookings()
{ {
return util::Map<std::string, const ServiceBooking*>(); auto serviceBookings = m_serviceManagementService.getServiceBookings();
util::Map<std::string, const ServiceBooking*> readOnlyServiceBookings;
for (int iterator = 0; iterator < serviceBookings.getSize(); iterator++)
{
readOnlyServiceBookings.insert(serviceBookings.getKeyAt(iterator), serviceBookings.getValueAt(iterator));
}
return readOnlyServiceBookings;
} }
util::Map<std::string, const ServiceBooking*> Controller::getServiceBookingsByUser(const std::string userID) util::Map<std::string, const ServiceBooking*> Controller::getServiceBookingsByUser(const std::string userID)
{ {
return util::Map<std::string, const ServiceBooking*>(); util::Map<std::string, const ServiceBooking*> readOnlyServiceBookingsByUserMap;
util::Map<std::string, ServiceBooking*> currentServiceBookingsByUser = m_serviceManagementService.getServiceBookings(userID);
for (int iterator = 0; iterator < currentServiceBookingsByUser.getSize(); iterator++)
{
readOnlyServiceBookingsByUserMap.insert(currentServiceBookingsByUser.getValueAt(iterator)->getId(), currentServiceBookingsByUser.getValueAt(iterator));
}
return readOnlyServiceBookingsByUserMap;
} }
/* /*
@@ -257,28 +240,46 @@ util::Map<std::string, const User*> Controller::getUsers()
util::Map<std::string, const User*> Controller::getUsers(util::UserType userType) util::Map<std::string, const User*> Controller::getUsers(util::UserType userType)
{ {
return util::Map<std::string, const User*>(); auto userMap = m_userManagementService.getUsers(userType);
util::Map<std::string, const User*> readOnlyUserMap;
for (int iterator = 0; iterator < userMap.getSize(); iterator++)
{
readOnlyUserMap.insert(userMap.getKeyAt(iterator), userMap.getValueAt(iterator));
}
return readOnlyUserMap;
} }
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);
} }
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);
} }
void Controller::removeService(const std::string& serviceID) void Controller::removeService(const std::string& serviceID)
{ {
m_serviceManagementService.removeService(serviceID);
} }
util::Map<std::string, const JobCard*> Controller::getJobCardsByUser() util::Map<std::string, const JobCard*> Controller::getJobCardsByUser()
{ {
return util::Map<std::string, const JobCard*>(); const User* currentUser = getAuthenticatedUser();
auto jobCardsAssignedToTechnician = m_serviceManagementService.getJobCards(currentUser->getId());
util::Map<std::string, const JobCard*> readOnlyJobCardMap;
for (int iterator = 0; iterator < jobCardsAssignedToTechnician.getSize(); iterator++)
{
JobCard* currentJobCard = jobCardsAssignedToTechnician.getValueAt(iterator);
readOnlyJobCardMap.insert(currentJobCard->getId(), currentJobCard);
}
return readOnlyJobCardMap;
} }
void Controller::completeJob(const std::string& jobID) void Controller::completeJob(const std::string& jobID)
{ {
m_serviceManagementService.completeJob(jobID);
} }
/* /*
@@ -328,11 +329,20 @@ void Controller::removeComboPackage(const std::string& comboPackageID)
util::Map<std::string, const Invoice*> Controller::getInvoicesByUser() util::Map<std::string, const Invoice*> Controller::getInvoicesByUser()
{ {
return util::Map<std::string, const Invoice*>(); User* currentUser = m_authenticationManagementService.getAuthenticatedUser();
util::Map<std::string, Invoice*> currentUserInvoices = m_paymentManagementService.getInvoices(currentUser->getId());
util::Map<std::string, const Invoice*> userInvoicesReadOnly;
for (int iterator = 0; iterator < currentUserInvoices.getSize(); iterator++)
{
Invoice* currentInvoice = currentUserInvoices.getValueAt(iterator);
userInvoicesReadOnly.insert(currentInvoice->getId(), currentInvoice);
}
return userInvoicesReadOnly;
} }
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);
} }
/* /*
@@ -413,16 +423,6 @@ void Controller::configureNotifications(bool paymentNotifications, bool serviceN
} }
} }
/*
Function: loadSystemData
Description: Loads all system data from persistent storage into memory.
Invokes the respective management services to load users, inventory items, services,
combo packages, service bookings, job cards, invoices, and observers.
Parameters:
- None
Returns:
- void
*/
void Controller::loadSystemData() void Controller::loadSystemData()
{ {
m_userManagementService.loadUsers(); m_userManagementService.loadUsers();
@@ -437,16 +437,6 @@ void Controller::loadSystemData()
m_inventoryManagementService.loadObservers(); m_inventoryManagementService.loadObservers();
} }
/*
Function: saveSystemData
Description: Saves all system data from memory back to persistent storage.
Invokes the respective management services to save users, inventory items, services,
combo packages, service bookings, job cards, invoices, and observers.
Parameters:
- None
Returns:
- void
*/
void Controller::saveSystemData() void Controller::saveSystemData()
{ {
m_userManagementService.saveUsers(); m_userManagementService.saveUsers();
@@ -463,8 +453,9 @@ void Controller::saveSystemData()
/* /*
Function: runSystemChecks Function: runSystemChecks
Description: Runs system checks to ensure critical configurations, such as verifying admin existence. Description: Executes system checks including sending low stock alerts
Parameter: None and payment reminders.
Parameters: None
Return type: void Return type: void
*/ */
void Controller::runSystemChecks() void Controller::runSystemChecks()
@@ -6,21 +6,15 @@ 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 "AuthenticationManagementService.h" #include "AuthenticationManagementService.h"
#include "Enums.h" #include "Enums.h"
#include "InventoryManagementService.h" #include "InventoryManagementService.h"
#include "Map.h" #include "Map.h"
#include "PaymentManagementService.h" #include "PaymentManagementService.h"
#include "PaymentManagementService.h"
#include "ServiceManagementService.h"
#include "ServiceManagementService.h"
#include "ServiceManagementService.h" #include "ServiceManagementService.h"
#include "UserManagementService.h" #include "UserManagementService.h"
#include "UserManagementService.h"
#include "UserManagementService.h"
#include <string>
class Service; class Service;
class ComboPackage; class ComboPackage;
@@ -45,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();
@@ -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,14 +233,6 @@ 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";
@@ -58,7 +58,8 @@ Invoice::Invoice(
const std::string& bookingId, const std::string& bookingId,
ServiceBooking* booking, ServiceBooking* booking,
const util::Timestamp& invoiceDate, const util::Timestamp& invoiceDate,
double laborCost, const util::Map<std::string, double laborCost,
const util::Map<std::string,
InventoryItem*>& parts, InventoryItem*>& parts,
double partsCost, double partsCost,
double discountPercentage, double discountPercentage,
@@ -121,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;
@@ -176,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;
@@ -193,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
{ {
@@ -429,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();
@@ -452,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;
@@ -472,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;
@@ -497,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;
@@ -559,14 +512,6 @@ 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";
@@ -40,8 +40,8 @@ public:
const std::string& bookingId, const std::string& bookingId,
ServiceBooking* booking, ServiceBooking* booking,
const util::Timestamp& invoiceDate, const util::Timestamp& invoiceDate,
double laborCost, const util::Map<std::string, double laborCost,
InventoryItem*>& parts, const util::Map<std::string,InventoryItem*>& parts,
double partsCost, double partsCost,
double discountPercentage, double discountPercentage,
double totalAmount, double totalAmount,
@@ -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,9 +6,9 @@ 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 "Timestamp.h" #include "Timestamp.h"
#include "Enums.h" #include "Enums.h"
@@ -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,8 +20,10 @@ 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("SRV" + std::to_string(++m_uid)), : m_id("SRV" + std::to_string(++m_uid)),
@@ -31,19 +33,18 @@ ServiceBooking::ServiceBooking()
/* /*
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,
@@ -76,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,
@@ -124,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;
@@ -138,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;
@@ -161,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
{ {
@@ -179,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
{ {
@@ -189,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
{ {
@@ -200,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
{ {
@@ -211,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
{ {
@@ -222,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
{ {
@@ -233,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
{ {
@@ -252,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
{ {
@@ -265,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)
{ {
@@ -277,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)
{ {
@@ -287,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)
{ {
@@ -305,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)
{ {
@@ -316,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)
{ {
@@ -327,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)
{ {
@@ -338,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)
{ {
@@ -349,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)
{ {
@@ -360,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)
{ {
@@ -382,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();
@@ -414,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;
@@ -434,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;
@@ -457,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;
@@ -505,14 +455,6 @@ ServiceBooking* ServiceBooking::deserialize(const std::string& record)
); );
} }
/*
Function: getHeaders
Description: Retrieves the CSV headers for service booking serialization.
Parameters:
- None
Returns:
- std::string: Header string ("ID,Status,ServiceIDs,CustomerID,VehicleNumber,VehicleBrand,VehicleModel,AssignedTechnicianID,DiscountPercentage")
*/
std::string ServiceBooking::getHeaders() std::string ServiceBooking::getHeaders()
{ {
return "ID,Status,ServiceIDs,CustomerID,VehicleNumber,VehicleBrand,VehicleModel,AssignedTechnicianID,DiscountPercentage"; return "ID,Status,ServiceIDs,CustomerID,VehicleNumber,VehicleBrand,VehicleModel,AssignedTechnicianID,DiscountPercentage";
@@ -53,22 +53,6 @@ User::User(const std::string& userName, const std::string& password, const std::
m_type(role), m_type(role),
m_status(util::State::ACTIVE) {} m_status(util::State::ACTIVE) {}
/*
Function: User (parameterized constructor with ID)
Description: Initializes a user with an existing ID, credentials, personal details,
role, and state. Updates UID tracking based on ID.
Parameters:
- userId: const std::string&, unique user ID
- userName: const std::string&, username
- password: const std::string&, password
- name: const std::string&, full name
- phone: const std::string&, phone number
- email: const std::string&, email address
- role: util::UserType, role of the user
- status: util::State, state of the user (ACTIVE/INACTIVE)
Returns:
- A new User object
*/
User::User(const std::string& userId, const std::string& userName, const std::string& password, const std::string& name, const std::string& phone, const std::string& email, util::UserType role, util::State status) User::User(const std::string& userId, const std::string& userName, const std::string& password, const std::string& name, const std::string& phone, const std::string& email, util::UserType role, util::State status)
: m_id(userId), : m_id(userId),
m_userName(userName), m_userName(userName),
@@ -322,14 +306,6 @@ void User::setState(util::State status)
m_status = status; m_status = status;
} }
/*
Function: serialize
Description: Serializes the user into a CSV-formatted string.
Parameters:
- None
Returns:
- std::string: Serialized user record
*/
std::string User::serialize() const std::string User::serialize() const
{ {
std::ostringstream serializedUser; std::ostringstream serializedUser;
@@ -344,14 +320,6 @@ std::string User::serialize() const
return serializedUser.str(); return serializedUser.str();
} }
/*
Function: deserialize
Description: Deserializes a CSV-formatted string into a User object.
Parameters:
- record: const std::string&, serialized user record
Returns:
- User*: Pointer to the deserialized User object
*/
User* User::deserialize(const std::string& record) User* User::deserialize(const std::string& record)
{ {
std::string id, name, username, phone, password, email; std::string id, name, username, phone, password, email;
@@ -377,15 +345,8 @@ User* User::deserialize(const std::string& record)
status); status);
} }
/*
Function: getHeaders
Description: Retrieves the CSV headers for user serialization.
Parameters:
- None
Returns:
- std::string: Header string ("ID,Username,Password,Name,Phone,Email,UserType,UserStatus")
*/
std::string User::getHeaders() std::string User::getHeaders()
{ {
return "ID,Username,Password,Name,Phone,Email,UserType,UserStatus"; return "ID,Username,Password,Name,Phone,Email,UserType,UserStatus";
} }
@@ -6,22 +6,12 @@ Description: Implementation file containing the method definitions of the
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#include <stdexcept> #include <stdexcept>
#include "AuthenticationManagementService.h" #include "AuthenticationManagementService.h"
#include "User.h" #include "User.h"
User* AuthenticationManagementService::m_authenticatedUser = nullptr; User* AuthenticationManagementService::m_authenticatedUser = nullptr;
/*
Function: login
Description: Authenticates a user by checking the provided username and password
against the stored users in the DataStore. If successful, sets the
authenticated user.
Parameter: const std::string& username - users username
const std::string& password - users password
Return type: bool - true if login successful, false otherwise
*/
bool AuthenticationManagementService::login(const std::string& username, const std::string& password) bool AuthenticationManagementService::login(const std::string& username, const std::string& password)
{ {
util::Map<std::string, User*> users = m_dataStore.getUsers(); util::Map<std::string, User*> users = m_dataStore.getUsers();
@@ -42,12 +32,6 @@ bool AuthenticationManagementService::login(const std::string& username, const s
return false; return false;
} }
/*
Function: getAuthenticatedUser
Description: Retrieves the currently authenticated user.
Parameter: None
Return type: User* - pointer to the authenticated user
*/
User* AuthenticationManagementService::getAuthenticatedUser() User* AuthenticationManagementService::getAuthenticatedUser()
{ {
return m_authenticatedUser; return m_authenticatedUser;
@@ -6,7 +6,6 @@ Description: Header file declaring the AuthenticationManagementService class, wh
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#pragma once #pragma once
#include <string> #include <string>
#include "DataStore.h" #include "DataStore.h"
@@ -1,180 +1,25 @@
/* /*
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)
Description: Sends low stock alert notifications to all admin users for a given inventory item.
Parameters:
- inventoryManagementService: InventoryManagementService&, service used to send notifications
- inventoryItem: const InventoryItem*, pointer to the low-stock inventory item
- adminUsers: const util::Vector<User*>&, list of admin users to notify
Returns:
- None
*/
static void sendLowStockAlertsToAdmins(InventoryManagementService& inventoryManagementService, const InventoryItem* inventoryItem, const util::Vector<User*>& adminUsers)
{
int adminUsersSize = adminUsers.getSize();
for (int index = 0; index < adminUsersSize; index++)
{
std::string title = "Low Stock Alert";
std::string message = "The inventory item with ID " + inventoryItem->getId() + " has very low quantity in the inventory";
inventoryManagementService.sendNotification(
adminUsers[index],
title,
message
);
}
}
/*
Function: sendLowStockAlerts
Description: Sends alerts to user for inventory items with low stock
Parameters:
- None
Returns:
- None
*/
void InventoryManagementService::sendLowStockAlerts()
{
auto& inventoryItems = m_dataStore.getInventoryItems();
int inventoryItemsSize = inventoryItems.getSize();
auto& usersMap = m_dataStore.getUsers();
int usersMapSize = usersMap.getSize();
util::Vector<User*> adminUsers;
for (int index = 0; index < usersMapSize; index++)
{
User* user = usersMap.getValueAt(index);
if (user->getUserType() == util::UserType::ADMIN)
{
adminUsers.push_back(user);
}
}
int adminUsersSize = adminUsers.getSize();
if (adminUsersSize < 1)
{
throw std::runtime_error("The system has no admins present!");
}
for (int index = 0; index <= inventoryItemsSize; index++)
{
InventoryItem* inventoryItem = inventoryItems.getValueAt(index);
if (inventoryItem && inventoryItem->getQuantity() < config::threshold::INVENTORY_LOW_STOCK_THRESHOLD)
{
sendLowStockAlertsToAdmins(*this, inventoryItem, adminUsers);
}
}
}
/*
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> observerIDs;
int numberOfObservers = m_observers.getSize();
for (int index = 0; index < numberOfObservers; index++)
{
User* observer = m_observers.getValueAt(index);
if (observer)
{
observerIDs.push_back(observer->getId());
}
}
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()
{
util::FileManager<InventoryItem> inventoryItemFileManager(config::file::INVENTORYITEM_FILE);
auto& inventoryItems = m_dataStore.getInventoryItems();
auto inventoryItemsMap = inventoryItemFileManager.load();
int numberOfInventoryItems = inventoryItemsMap.getSize();
for (int index = 0; index < numberOfInventoryItems; index++)
{
inventoryItems[inventoryItemsMap.getKeyAt(index)] = inventoryItemsMap.getValueAt(index);
}
}
/*
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()
{
util::FileManager<InventoryItem> inventoryItemFileManager(config::file::INVENTORYITEM_FILE);
auto& inventoryItems = m_dataStore.getInventoryItems();
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()
{
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()
{
util::saveObservers(config::file::INVENTORYMANAGEMENTOBSERVERS, this);
}
/* /*
Function: addInventoryItem Function: addInventoryItem
Description: Creates a new inventory item using the Factory and inserts it Description: Creates a new inventory item using the Factory and inserts it
@@ -257,14 +102,6 @@ InventoryItem* InventoryManagementService::getInventoryItem(const std::string& i
return nullptr; 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) void InventoryManagementService::attach(User* user)
{ {
if (user) if (user)
@@ -277,14 +114,6 @@ void InventoryManagementService::attach(User* 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) void InventoryManagementService::detach(User* user)
{ {
if (user) if (user)
@@ -297,18 +126,6 @@ void InventoryManagementService::detach(User* user)
} }
} }
/*
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) void InventoryManagementService::sendNotification(User* user, const std::string& title, const std::string& message)
{ {
if (user) if (user)
@@ -335,3 +152,94 @@ void InventoryManagementService::sendNotification(User* user, const std::string&
} }
} }
static void sendLowStockAlertsToAdmins(InventoryManagementService& inventoryManagementService, const InventoryItem* inventoryItem, const util::Vector<User*>& adminUsers)
{
int adminUsersSize = adminUsers.getSize();
for (int index = 0; index < adminUsersSize; index++)
{
inventoryManagementService.sendNotification(
adminUsers[index],
"Low Stock Alert",
"The inventory item with ID " + inventoryItem->getId() +
" has very low quantity in the inventory"
);
}
}
void InventoryManagementService::sendLowStockAlerts()
{
auto& inventoryItems = m_dataStore.getInventoryItems();
if (inventoryItems.isEmpty())
{
return;
}
int inventoryItemsSize = inventoryItems.getSize();
auto& usersMap = m_dataStore.getUsers();
int usersMapSize = usersMap.getSize();
util::Vector<User*> adminUsers;
for (int index = 0; index < usersMapSize; index++)
{
User* user = usersMap.getValueAt(index);
if (user->getUserType() == util::UserType::ADMIN)
{
adminUsers.push_back(user);
}
}
int adminUsersSize = adminUsers.getSize();
if (adminUsersSize < 1)
{
throw std::runtime_error("The system has no admins present!");
}
for (int index = 0; index <= inventoryItemsSize; index++)
{
InventoryItem* inventoryItem = inventoryItems.getValueAt(index);
if (inventoryItem && inventoryItem->getQuantity() < config::threshold::INVENTORY_LOW_STOCK_THRESHOLD)
{
sendLowStockAlertsToAdmins(*this, inventoryItem, adminUsers);
}
}
}
util::Vector<std::string> InventoryManagementService::getObserverIDs()
{
util::Vector<std::string> observerIDs;
int numberOfObservers = m_observers.getSize();
for (int index = 0; index < numberOfObservers; index++)
{
User* observer = m_observers.getValueAt(index);
if (observer)
{
observerIDs.push_back(observer->getId());
}
}
return observerIDs;
}
void InventoryManagementService::loadInventoryItems()
{
util::FileManager<InventoryItem> inventoryItemFileManager(config::file::INVENTORYITEM_FILE);
auto& inventoryItems = m_dataStore.getInventoryItems();
auto inventoryItemsMap = inventoryItemFileManager.load();
int numberOfInventoryItems = inventoryItemsMap.getSize();
for (int index = 0; index < numberOfInventoryItems; index++)
{
inventoryItems[inventoryItemsMap.getKeyAt(index)] = inventoryItemsMap.getValueAt(index);
}
}
void InventoryManagementService::saveInventoryItems()
{
util::FileManager<InventoryItem> inventoryItemFileManager(config::file::INVENTORYITEM_FILE);
auto& inventoryItems = m_dataStore.getInventoryItems();
inventoryItemFileManager.save(inventoryItems);
}
void InventoryManagementService::loadObservers()
{
util::loadObservers(config::file::INVENTORYMANAGEMENTOBSERVERS, this, m_dataStore);
}
void InventoryManagementService::saveObservers()
{
util::saveObservers(config::file::INVENTORYMANAGEMENTOBSERVERS, this);
}
@@ -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,12 +8,15 @@ 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"
#include "FileManager.h" #include "FileManager.h"
#include "InventoryItem.h"
#include "Invoice.h" #include "Invoice.h"
#include "PaymentManagementService.h" #include "JobCard.h"
#include "Service.h"
#include "ServiceBooking.h" #include "ServiceBooking.h"
#include "Timestamp.h" #include "Timestamp.h"
#include "User.h" #include "User.h"
@@ -21,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.
@@ -127,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());
} }
} }
} }
@@ -137,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;
@@ -161,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);
@@ -207,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);
@@ -224,31 +279,11 @@ 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);
@@ -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"
@@ -32,6 +31,7 @@ public:
void purchaseComboPackage(const std::string& comboPackageID, const std::string& vehicleNumber, const std::string& vehicleBrand, const std::string& vehicleModel); void purchaseComboPackage(const std::string& comboPackageID, const std::string& vehicleNumber, const std::string& vehicleBrand, const std::string& vehicleModel);
util::Map<std::string, ServiceBooking*> getServiceBookings(); util::Map<std::string, ServiceBooking*> getServiceBookings();
util::Map<std::string, ServiceBooking*> getServiceBookings(const std::string& customerID); util::Map<std::string, ServiceBooking*> getServiceBookings(const std::string& customerID);
ServiceBooking* getServiceBooking(const std::string& serviceID);
void createJobCard(const std::string& bookingID, const std::string& technicianID, const std::string& serviceID); void createJobCard(const std::string& bookingID, const std::string& technicianID, const std::string& serviceID);
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);
@@ -1,33 +1,25 @@
/* /*
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
*/ */
#include <stdexcept>
#include "Config.h" #include "Config.h"
#include "Enums.h" #include "Enums.h"
#include "Factory.h" #include "Factory.h"
#include "FileManager.h" #include "FileManager.h"
#include "InventoryManagementService.h" #include "InventoryManagementService.h"
#include "Notification.h" #include "Invoice.h"
#include "PaymentManagementService.h" #include "PaymentManagementService.h"
#include "ServiceManagementService.h" #include "ServiceManagementService.h"
#include "User.h" #include "User.h"
#include "UserManagementService.h" #include "UserManagementService.h"
#include "Utility.h"
#include "Vector.h" #include "Vector.h"
#include <stdexcept>
/*
Function: ensureAdminExists
Description: Ensures that at least one admin user exists in the system.
If no admin is found, creates a default admin user using
configuration constants.
Parameter: None
Return type: void
*/
void UserManagementService::ensureAdminExists() void UserManagementService::ensureAdminExists()
{ {
auto& usersMap = m_dataStore.getUsers(); auto& usersMap = m_dataStore.getUsers();
@@ -54,19 +46,6 @@ 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;
@@ -93,15 +72,6 @@ void UserManagementService::createUser(const std::string& username, const std::s
} }
} }
/*
Function: updateUserDetails
Description: Updates the email and phone details of an existing user.
Throws an exception if the user does not exist.
Parameter: const std::string& userID - ID of the user to update
const std::string& email - new email address
const std::string& phone - new phone number
Return type: void
*/
void UserManagementService::updateUserDetails(const std::string& userID, const std::string& email, const std::string& phone) void UserManagementService::updateUserDetails(const std::string& userID, const std::string& email, const std::string& phone)
{ {
auto& usersMap = m_dataStore.getUsers(); auto& usersMap = m_dataStore.getUsers();
@@ -115,6 +85,67 @@ void UserManagementService::updateUserDetails(const std::string& userID, const s
user->setPhone(phone); user->setPhone(phone);
} }
/*
Function: getUsers
Description: Retrieves all users stored in the DataStore.
Parameter: None
Return type: util::Map<std::string, User*>
*/
util::Map<std::string, User*> UserManagementService::getUsers()
{
return m_dataStore.getUsers();
}
util::Map<std::string, User*> UserManagementService::getUsers(util::UserType type)
{
util::Map<std::string, User*>& currentUsers = m_dataStore.getUsers();
util::Map<std::string, User*> filteredUsersMap;
for (int iterator = 0; iterator < currentUsers.getSize(); iterator++)
{
User* currentUser = currentUsers.getValueAt(iterator);
if (currentUser->getUserType() == type)
{
filteredUsersMap.insert(currentUser->getId(), currentUser);
}
}
return filteredUsersMap;
}
/*
Function: getUser
Description: Retrieves a specific user by ID from the DataStore.
Parameter: const std::string& userID - ID of the user
Return type: User*
*/
User* UserManagementService::getUser(const std::string& userID)
{
int index = m_dataStore.getUsers().find(userID);
if (index != -1)
{
return m_dataStore.getUsers().getValueAt(index);
}
return nullptr;
}
/*
Function: removeUser
Description: Marks a user as inactive in the DataStore instead of deleting them.
Parameter: const std::string& userID - ID of the user to remove
Return type: void
*/
void UserManagementService::removeUser(const std::string& userID)
{
int index = m_dataStore.getUsers().find(userID);
if (index != -1)
{
User* user = m_dataStore.getUsers().getValueAt(index);
if (user != nullptr)
{
user->setState(util::State::INACTIVE);
}
}
}
/* /*
Function: getUserNotifications Function: getUserNotifications
Description: Retrieves all notifications associated with a given user ID. Description: Retrieves all notifications associated with a given user ID.
@@ -177,18 +208,6 @@ void UserManagementService::deleteNotification(const std::string& notificationID
notifications.remove(notificationID); notifications.remove(notificationID);
} }
/*
Function: loadUsers
Description: Loads users and notifications from persistent storage into the datastore.
Validates that each notifications recipient exists and attaches the
notification to the corresponding user.
Parameters:
- None
Returns:
- void
Throws:
- std::runtime_error if a notification recipient user ID is invalid
*/
void UserManagementService::loadUsers() void UserManagementService::loadUsers()
{ {
util::FileManager<User> userFileManager(config::file::USER_FILE); util::FileManager<User> userFileManager(config::file::USER_FILE);
@@ -216,15 +235,6 @@ void UserManagementService::loadUsers()
} }
} }
/*
Function: saveUsers
Description: Saves users and their notifications from the datastore to persistent storage.
Collects notifications from all users into a single map before saving.
Parameters:
- None
Returns:
- void
*/
void UserManagementService::saveUsers() void UserManagementService::saveUsers()
{ {
util::FileManager<User> userFileManager(config::file::USER_FILE); util::FileManager<User> userFileManager(config::file::USER_FILE);
@@ -244,49 +254,3 @@ void UserManagementService::saveUsers()
userFileManager.save(users); userFileManager.save(users);
notificationFileManager.save(notifications); notificationFileManager.save(notifications);
} }
/*
Function: getUsers
Description: Retrieves all users stored in the DataStore.
Parameter: None
Return type: util::Map<std::string, User*>
*/
util::Map<std::string, User*> UserManagementService::getUsers()
{
return m_dataStore.getUsers();
}
/*
Function: getUser
Description: Retrieves a specific user by ID from the DataStore.
Parameter: const std::string& userID - ID of the user
Return type: User*
*/
User* UserManagementService::getUser(const std::string& userID)
{
int index = m_dataStore.getUsers().find(userID);
if (index != -1)
{
return m_dataStore.getUsers().getValueAt(index);
}
return nullptr;
}
/*
Function: removeUser
Description: Marks a user as inactive in the DataStore instead of deleting them.
Parameter: const std::string& userID - ID of the user to remove
Return type: void
*/
void UserManagementService::removeUser(const std::string& userID)
{
int index = m_dataStore.getUsers().find(userID);
if (index != -1)
{
User* user = m_dataStore.getUsers().getValueAt(index);
if (user != nullptr)
{
user->setState(util::State::INACTIVE);
}
}
}
@@ -1,8 +1,7 @@
/* /*
File: UserManagementService.h File: UserManagementService.h
Description: Header file declaring the UserManagementService class, which manages Description: Header file declaring the UserManagementService class, which manages
user creation, updates, retrieval, removal, notifications, and ensures user creation, updates, retrieval, removal, and notification handling.
the existence of an admin account.
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
@@ -1,8 +1,7 @@
/* /*
File: Config.h File: Config.h
Description: Header file declaring configuration constants for the Vehicle Service System. Description: Defines configuration constants for system thresholds in the Vehicle Service Management System.
Includes default admin account details such as username, name, password, Includes limits for inventory stock alerts and payment reminder intervals.
email, and phone number.
Author: Trenser Author: Trenser
Date: 21-May-2026 Date: 21-May-2026
*/ */
@@ -15,7 +14,7 @@ namespace config
{ {
constexpr const char* DEFAULT_ADMIN_USERNAME = "admin"; constexpr const char* DEFAULT_ADMIN_USERNAME = "admin";
constexpr const char* DEFAULT_ADMIN_NAME = "admin"; constexpr const char* DEFAULT_ADMIN_NAME = "admin";
constexpr const char* DEFAULT_ADMIN_PASSWORD = ""; constexpr const char* DEFAULT_ADMIN_PASSWORD = "admin";
constexpr const char* DEFAULT_ADMIN_EMAIL = "admin@vss"; constexpr const char* DEFAULT_ADMIN_EMAIL = "admin@vss";
constexpr const char* DEFAULT_ADMIN_PHONE = "0000000000"; constexpr const char* DEFAULT_ADMIN_PHONE = "0000000000";
} }
@@ -22,7 +22,8 @@ namespace util
enum class PaymentMode enum class PaymentMode
{ {
ONLINE, ONLINE,
OFFLINE OFFLINE,
NOTSET
}; };
enum class PaymentStatus enum class PaymentStatus
@@ -110,6 +111,8 @@ namespace util
return "ONLINE"; return "ONLINE";
case PaymentMode::OFFLINE: case PaymentMode::OFFLINE:
return "OFFLINE"; return "OFFLINE";
case PaymentMode::NOTSET:
return "NOTSET";
} }
throw std::invalid_argument("Invalid PaymentMode"); throw std::invalid_argument("Invalid PaymentMode");
} }
@@ -1,12 +1,3 @@
/*
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>
@@ -15,17 +6,6 @@ Date: 22-May-2026
namespace util namespace util
{ {
/*
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;
@@ -50,18 +30,6 @@ namespace util
return records; return records;
} }
/*
Function: saveRecords
Description: Saves records to a given file path. Overwrites existing content
and writes a header line followed by all records.
Parameters:
- filePath: const std::string&, path to the file
- records: const util::Vector<std::string>&, vector of records to save
Returns:
- void
Throws:
- std::runtime_error if the file cannot be opened for writing
*/
inline void saveRecords(const std::string& filePath, const util::Vector<std::string>& records) inline void saveRecords(const std::string& filePath, const util::Vector<std::string>& records)
{ {
std::ofstream file(filePath, std::ios::trunc); std::ofstream file(filePath, std::ios::trunc);
@@ -1,17 +1,6 @@
/*
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"
@@ -32,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()
{ {
@@ -81,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)
{ {
@@ -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,18 +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 "InventoryItem.h"
#include "NotificationManagementService.h" #include "NotificationManagementService.h"
#include "Service.h" #include "FileHelper.h"
#include "DataStore.h"
namespace util namespace util
{ {
@@ -38,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)
{ {
@@ -55,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);
@@ -85,16 +72,6 @@ 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();
@@ -1,13 +1,11 @@
/* /*
File: AdminMenu.cpp File: AdminMenu.cpp
Description: Implements the AdminMenu class which provides the administrators console interface Description: Implementation file containing the method definitions of the
in the Vehicle Service Management System. Handles menu display, user input, and AdminMenu class, including menu handling, inventory operations,
admin-specific operations such as inventory management, technician management, user management, and combo package management functions.
service creation, combo package management, job assignment, and notifications.
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#include <iomanip> #include <iomanip>
#include <iostream> #include <iostream>
#include "AdminMenu.h" #include "AdminMenu.h"
@@ -18,10 +16,12 @@ Date: 19-May-2026
#include "MenuHelper.h" #include "MenuHelper.h"
#include "OutputHelper.h" #include "OutputHelper.h"
#include "Service.h" #include "Service.h"
#include "ServiceBooking.h"
#include "User.h" #include "User.h"
#include "Utility.h" #include "Utility.h"
#include "Validator.h" #include "Validator.h"
/* /*
Function: showMenu Function: showMenu
Description: Displays the admin menu and handles user input until logout is selected. Description: Displays the admin menu and handles user input until logout is selected.
@@ -135,7 +135,6 @@ void AdminMenu::logout()
{ {
m_controller.logout(); m_controller.logout();
} }
/* /*
Function: changePassword Function: changePassword
Description: Allows the admin to change their password after validation. Description: Allows the admin to change their password after validation.
@@ -144,7 +143,23 @@ Return type: void
*/ */
void AdminMenu::changePassword() void AdminMenu::changePassword()
{ {
changePasswordHelper(m_controller); std::string newPassword;
while (true)
{
util::clear();
std::cout << "Enter new password: ";
util::read(newPassword);
if (!util::isPasswordValid(newPassword))
{
std::cout << "Error: Password is not strong enough!\n";
util::pressEnter();
continue;
}
m_controller.changePassword(newPassword);
std::cout << "Password changed successfully\n";
util::pressEnter();
break;
}
} }
/* /*
@@ -156,7 +171,6 @@ Return type: void
*/ */
void AdminMenu::viewStockLevels() void AdminMenu::viewStockLevels()
{ {
util::clear();
auto inventoryItems = m_controller.getInventoryItems(); auto inventoryItems = m_controller.getInventoryItems();
std::cout << std::left << std::setw(15) << "Item ID" std::cout << std::left << std::setw(15) << "Item ID"
<< std::setw(25) << "Part Name" << std::setw(25) << "Part Name"
@@ -180,6 +194,112 @@ void AdminMenu::viewStockLevels()
} }
} }
/*
Function: filterActiveItems
Description: Filters out inactive inventory items and returns a map
containing only active items.
Parameter: const util::Map<std::string, const InventoryItem*>& inventoryItems -
map of all inventory items
Return type: util::Map<std::string, const InventoryItem*>
*/
static util::Map<std::string, const InventoryItem*>
filterActiveItems(const util::Map<std::string, const InventoryItem*>& inventoryItems)
{
util::Map<std::string, const InventoryItem*> activeItems;
int inventorySize = inventoryItems.getSize();
for (int index = 0; index < inventorySize; index++)
{
const InventoryItem* item = inventoryItems.getValueAt(index);
if (item != nullptr && item->getState() != util::State::INACTIVE)
{
activeItems.insert(item->getId(), item);
}
}
return activeItems;
}
/*
Function: displayInventoryWithItems
Description: Displays inventory items in a tabular format with index, ID,
part name, quantity, and price.
Parameter: util::Map<std::string, const InventoryItem*>& inventoryItems -
map of inventory items to display
Return type: void
*/
static void displayInventoryWithItems(util::Map<std::string, const InventoryItem*>& inventoryItems)
{
int inventorySize = inventoryItems.getSize();
std::cout << std::left << std::setw(10) << "Index"
<< std::setw(15) << "Item ID"
<< std::setw(25) << "Part Name"
<< std::setw(10) << "Quantity"
<< std::setw(10) << "Price"
<< std::endl;
for (int iterator = 0; iterator < inventorySize; iterator++)
{
const InventoryItem* item = inventoryItems.getValueAt(iterator);
if (item != nullptr)
{
std::cout << std::left << std::setw(10) << (iterator + 1)
<< std::setw(15) << item->getId()
<< std::setw(25) << item->getPartName()
<< std::setw(10) << item->getQuantity()
<< std::setw(10) << item->getPrice()
<< std::endl;
}
}
}
/*
Function: addQuantityToItem
Description: Allows the admin to select an active inventory item and
increase its stock quantity.
Parameter: util::Map<std::string, const InventoryItem*>& inventoryItems -
map of inventory items
Controller& m_controller - controller instance to update stock
Return type: void
*/
static void addQuantityToItem(util::Map<std::string, const InventoryItem*>& inventoryItems, Controller& m_controller)
{
int itemIndex;
int quantity;
auto activeItems = filterActiveItems(inventoryItems);
int activeSize = activeItems.getSize();
if (activeSize == 0)
{
std::cout << "No active items available in Inventory" << std::endl;
return;
}
displayInventoryWithItems(activeItems);
std::cout << "Enter the index of the item to update: ";
util::read(itemIndex);
if (itemIndex < 1 || itemIndex > activeSize)
{
std::cout << "Invalid index selected." << std::endl;
return;
}
std::cout << "Enter quantity to add: ";
util::read(quantity);
if (quantity < 0)
{
std::cout << "The quantity should be Greater than 0." << std::endl;
return;
}
const InventoryItem* selectedItem = activeItems.getValueAt(itemIndex - 1);
if (selectedItem != nullptr)
{
std::string selectedItemId = selectedItem->getId();
m_controller.addInventoryItemStock(selectedItemId, quantity);
std::cout << "Updated " << selectedItem->getPartName()
<< " stock. New quantity: " << selectedItem->getQuantity()
<< std::endl;
}
else
{
std::cout << "Error: Selected item could not be found." << std::endl;
}
}
/* /*
Function: addInventoryItem Function: addInventoryItem
Description: Allows the admin to either add a new inventory item Description: Allows the admin to either add a new inventory item
@@ -249,7 +369,7 @@ void AdminMenu::removeInventoryItem()
util::pressEnter(); util::pressEnter();
return; return;
} }
const InventoryItem* selectedItem = activeItems.getValueAt(itemIndex - 1); const InventoryItem* selectedItem = inventoryItems.getValueAt(itemIndex - 1);
if (selectedItem != nullptr) if (selectedItem != nullptr)
{ {
if(selectedItem->getState() != util::State::INACTIVE) if(selectedItem->getState() != util::State::INACTIVE)
@@ -290,16 +410,290 @@ void AdminMenu::checkStockAvailability()
util::pressEnter(); util::pressEnter();
} }
static bool listServiceBookings(util::Map<std::string, const ServiceBooking*>& currentBookings, int& bookingsSize, util::Map<int, const ServiceBooking*>& serviceBookingsMap)
{
int currentIndex = 1;
bool hasPendingService = false;
std::cout << std::left
<< std::setw(10) << "Index"
<< std::setw(10) << "ID"
<< std::setw(12) << "Status"
<< std::setw(12) << "CustID"
<< std::setw(20) << "Customer"
<< std::setw(15) << "VehicleNo"
<< std::setw(15) << "Brand"
<< std::setw(15) << "Model"
<< std::setw(20) << "Technician"
<< std::setw(15) << "TechID"
<< std::endl;
for (int iterator = 0; iterator < bookingsSize; iterator++)
{
const ServiceBooking* currentBooking = currentBookings.getValueAt(iterator);
if (currentBooking && currentBooking->getStatus() == util::ServiceJobStatus::PENDING)
{
hasPendingService = true;
std::cout << std::left
<< std::setw(10) << currentIndex
<< std::setw(10) << currentBooking->getId()
<< std::setw(12) << util::getServiceJobStatusString(currentBooking->getStatus())
<< std::setw(12) << currentBooking->getCustomerId()
<< std::setw(20) << currentBooking->getCustomer()->getName()
<< std::setw(15) << currentBooking->getVehicleNumber()
<< std::setw(15) << currentBooking->getVehicleBrand()
<< std::setw(15) << currentBooking->getVehicleModel()
<< std::setw(20) << (currentBooking->getAssignedTechnician() == nullptr ? "Null" : currentBooking->getAssignedTechnician()->getName())
<< std::setw(15) << (currentBooking->getAssignedTechnicianId().empty() ? "Null" : currentBooking->getAssignedTechnicianId())
<< std::endl;
serviceBookingsMap.insert(currentIndex++, currentBooking);
}
}
if (!hasPendingService)
{
std::cout << "No pending service available." << std::endl;
return false;
}
return true;
}
static const ServiceBooking* selectPendingServiceBookings(util::Map<int, const ServiceBooking*>& serviceBookingsMap)
{
int userInputIndex;
std::cout << "Enter a valid service index: ";
util::read(userInputIndex);
if (serviceBookingsMap.find(userInputIndex) != -1)
{
return serviceBookingsMap.getValueAt(userInputIndex);
}
else
{
std::cout << "Enter a valid index.";
return nullptr;
}
}
static void listAvailableTechnicians( util::Map<std::string, const User*> currentAvailableTechnicians, int numberOfTechnicians, util::Map<int, const User*>& currentAvailableTechniciansMap)
{
bool hasTechnicians = false;
int currentIndex = 1;
std::cout << std::left
<< std::setw(6) << "Index"
<< std::setw(15) << "Technician ID"
<< std::setw(20) << "Name"
<< std::endl;
for (int iterator = 0; iterator < numberOfTechnicians; iterator++)
{
const User* currentTechnician = currentAvailableTechnicians.getValueAt(iterator);
if (currentTechnician->getState() == util::State::INACTIVE)
{
continue;
}
hasTechnicians = true;
std::cout << std::left
<< std::setw(6) << currentIndex
<< std::setw(15) << currentTechnician->getId()
<< std::setw(20) << currentTechnician->getName()
<< std::endl;
currentAvailableTechniciansMap.insert(currentIndex++, currentTechnician);
}
if (!hasTechnicians)
{
std::cout << "No technicians currently available.";
}
}
static const User* selectTechnician(util::Map<int, const User*>& currentAvailableTechniciansMap)
{
int userInputIndex;
util::read(userInputIndex);
if (currentAvailableTechniciansMap.find(userInputIndex) != -1)
{
return currentAvailableTechniciansMap.getValueAt(userInputIndex);
}
else
{
std::cout << "Enter a valid index.";
return nullptr;
}
}
void AdminMenu::assignJob() void AdminMenu::assignJob()
{ {
util::clear();
std::string selectedService;
bool hasPendingService = false;
auto currentBookings = m_controller.getServiceBookings();
auto availableTechnicians = m_controller.getUsers(util::UserType::TECHNICIAN);
int bookingsSize = currentBookings.getSize();
util::Map<int, const ServiceBooking*> serviceBookingsMap;
util::Map<int, const User*> currentAvailableTechniciansMap;
if (listServiceBookings(currentBookings, bookingsSize, serviceBookingsMap))
{
const ServiceBooking* selectedService = selectPendingServiceBookings(serviceBookingsMap);
if (selectedService)
{
if (availableTechnicians.getSize() != 0)
{
listAvailableTechnicians(availableTechnicians, availableTechnicians.getSize(), currentAvailableTechniciansMap);
const User* selectedTechnician = selectTechnician(currentAvailableTechniciansMap);
if (selectedTechnician)
{
auto& servicesInBooking = selectedService->getServices();
for (int iterator = 0; iterator < servicesInBooking.getSize(); iterator++)
{
m_controller.createJobCard(selectedService->getId(), selectedTechnician->getId(), servicesInBooking.getValueAt(iterator)->getId());
}
}
}
else
{
std::cout << "No technicians are currently available.";
}
}
}
}
static void selectInventoryItems(util::Map<std::string, const InventoryItem*>& currentInventoryItems, util::Vector<std::string>& selectedInventoryItems)
{
bool doRun = true, hasInventoryItems = false;
util::Map<int, const InventoryItem*> currentInventoryMap;
int currentIndex = 1;
int choice;
if (currentInventoryItems.getSize() == 0)
{
std::cout << "Inventory empty.";
}
while (doRun)
{
bool hasInventoryItems = false;
int currentIndex = 1;
currentInventoryMap.clear();
std::cout << std::left
<< std::setw(6) << "Index"
<< std::setw(12) << "Item ID"
<< std::setw(20) << "Part Name"
<< std::setw(10) << "Price"
<< std::setw(10) << "Quantity"
<< std::endl;
for (int iterator = 0; iterator < currentInventoryItems.getSize(); iterator++)
{
const InventoryItem* currentInventoryItem = currentInventoryItems.getValueAt(iterator);
if (currentInventoryItem->getState() == util::State::INACTIVE)
{
continue;
}
std::cout << std::left
<< std::setw(6) << currentIndex
<< std::setw(12) << currentInventoryItem->getId()
<< std::setw(20) << currentInventoryItem->getPartName()
<< std::setw(10) << currentInventoryItem->getPrice()
<< std::setw(10) << currentInventoryItem->getQuantity()
<< std::endl;
hasInventoryItems = true;
currentInventoryMap.insert(currentIndex++, currentInventoryItem);
}
if (!hasInventoryItems)
{
std::cout << "No items present in the inventory." << std::endl;
doRun = false;
break;
}
std::cout << "Select the item (Index) or enter -1 to exit: ";
util::read(choice);
if (choice == -1)
{
doRun = false;
}
else if (currentInventoryMap.find(choice) != -1)
{
selectedInventoryItems.push_back(currentInventoryMap.getValueAt(choice)->getId());
std::cout << "Item added successfully." << std::endl;
}
else
{
std::cout << "Enter a valid integer." << std::endl;
}
}
} }
void AdminMenu::createService() void AdminMenu::createService()
{ {
util::clear();
std::string serviceName;
double labourCost;
std::cout << "Enter the service name: ";
util::read(serviceName);
util::Map<std::string, const InventoryItem*> currentInventoryItems = m_controller.getInventoryItems();
util::Vector<std::string> selectedInventoryItems;
selectInventoryItems(currentInventoryItems,selectedInventoryItems);
std::cout << "Enter the labour cost: ";
util::read(labourCost);
m_controller.createService(serviceName, selectedInventoryItems, labourCost);
std::cout << "Service created sucessfully.\n";
}
static std::string selectServicesToRemove(util::Map<std::string, const Service*> currentServices)
{
util::Map<int, const Service*> currentServicesMap;
bool hasServices = false;
int currentIndex = 1, choice;
std::cout << std::left
<< std::setw(6) << "Index"
<< std::setw(12) << "Service ID"
<< std::setw(20) << "Name"
<< std::setw(10) << "Labor Cost"
<< std::endl;
for (int iterator = 0; iterator < currentServices.getSize(); iterator++)
{
const Service* currentService = currentServices.getValueAt(iterator);
if (currentService->getState() == util::State::INACTIVE)
{
continue;
}
std::cout << std::left
<< std::setw(6) << currentIndex
<< std::setw(12) << currentService->getId()
<< std::setw(20) << currentService->getName()
<< std::setw(10) << currentService->getLaborCost()
<< std::endl;
hasServices = true;
currentServicesMap.insert(currentIndex++, currentService);
}
if (!hasServices)
{
std::cout << "No services currently available." << std::endl;
return "";
}
std::cout << "Enter your choice: ";
util::read(choice);
if (currentServicesMap.find(choice) != -1)
{
return currentServicesMap.getValueAt(currentServicesMap.find(choice))->getId();
}
else
{
std::cout << "Invalid choice." << std::endl;
return "";
}
} }
void AdminMenu::removeService() void AdminMenu::removeService()
{ {
util::clear();
std::string selectedServiceID;
util::Map<std::string, const Service*> currentServices = m_controller.getServices();
selectedServiceID = selectServicesToRemove(currentServices);
if (selectedServiceID != "")
{
m_controller.removeService(selectedServiceID);
std::cout << "Service removed sucessfully.";
}
else
{
std::cout << "Failed to remove service.";
}
} }
/* /*
@@ -314,8 +708,6 @@ void AdminMenu::addTechnician()
std::string username, name, password, email, phoneNumber; std::string username, name, password, email, phoneNumber;
std::cout << std::left << std::setw(25) << "Enter Technician Username:"; std::cout << std::left << std::setw(25) << "Enter Technician Username:";
util::read(username); util::read(username);
std::cout << std::left << std::setw(25) << "Enter Technician Name: ";
util::read(name);
std::cout << std::setw(25) << "Enter Technician Password:"; std::cout << std::setw(25) << "Enter Technician Password:";
util::read(password); util::read(password);
if(!util::isPasswordValid(password)) if(!util::isPasswordValid(password))
@@ -324,6 +716,8 @@ void AdminMenu::addTechnician()
util::pressEnter(); util::pressEnter();
return; return;
} }
std::cout << std::left << std::setw(25) << "Enter Technician Name:";
util::read(name);
std::cout << std::setw(25) << "Enter Technician Email:"; std::cout << std::setw(25) << "Enter Technician Email:";
util::read(email); util::read(email);
if(!util::isEmailValid(email)) if(!util::isEmailValid(email))
@@ -345,6 +739,62 @@ void AdminMenu::addTechnician()
util::pressEnter(); util::pressEnter();
} }
/*
Function: filterActiveUsers
Description: Filters out inactive users and returns a map of active users.
Parameter: const util::Map<std::string, const User*>& listOfUsers - all users
Return type: util::Map<std::string, const User*>
*/
static util::Map<std::string, const User*>
filterActiveUsers(const util::Map<std::string, const User*>& listOfUsers)
{
util::Map<std::string, const User*> activeUsers;
int inventorySize = listOfUsers.getSize();
for (int index = 0; index < inventorySize; index++)
{
const User* user = listOfUsers.getValueAt(index);
if (user != nullptr && user->getState() != util::State::INACTIVE)
{
activeUsers.insert(user->getId(), user);
}
}
return activeUsers;
}
/*
Function: displayAllActiveUsers
Description: Displays all active users in a tabular format with index, ID, username, and type.
Parameter: util::Map<std::string, const User*>& activeUsers - active users list
int activeUserCount - number of active users
Return type: void
*/
static void displayAllActiveUsers(util::Map<std::string, const User*>& activeUsers, int activeUserCount)
{
std::cout << std::left << std::setw(10) << "Index"
<< std::setw(15) << "User ID"
<< std::setw(25) << "Username"
<< std::setw(25) << "User Type"
<< std::endl;
for (int iterator = 0; iterator < activeUserCount; iterator++)
{
const User* user = activeUsers.getValueAt(iterator);
if (user != nullptr)
{
std::cout << std::left << std::setw(10) << (iterator + 1)
<< std::setw(15) << user->getId()
<< std::setw(25) << user->getUserName()
<< std::setw(25) << util::getUserTypeString(user->getUserType())
<< std::endl;
}
else
{
std::cout << "No users found.\n";
util::pressEnter();
return;
}
}
}
/* /*
Function: removeUser Function: removeUser
Description: Removes a selected active user (customer or technician) from the system. Description: Removes a selected active user (customer or technician) from the system.
@@ -383,6 +833,55 @@ void AdminMenu::removeUser()
util::pressEnter(); util::pressEnter();
} }
/*
Function: selectServiceFromServices
Description: Displays active services and allows the admin to select one by index.
Parameter: const util::Map<std::string, const Service*>& services - list of services
Return type: const Service* - selected service
*/
static const Service* selectServiceFromServices(const util::Map<std::string, const Service*>& services)
{
util::Map<int, const Service*> activeServicesMap;
int currentIndex = 1;
int userInputIndex;
std::cout << std::left
<< std::setw(10) << "Index"
<< std::setw(15) << "Service ID"
<< std::setw(25) << "Service Name"
<< std::setw(15) << "Estimated Cost"
<< std::endl;
for (int index = 0; index < services.getSize(); index++)
{
const Service* currentService = services.getValueAt(index);
if (currentService->getState() != util::State::ACTIVE)
{
continue;
}
activeServicesMap.insert(currentIndex, currentService);
double partsCost = util::calculatePartsCost(currentService);
std::cout << std::left
<< std::setw(10) << currentIndex
<< std::setw(15) << currentService->getId()
<< std::setw(25) << currentService->getName()
<< std::setw(15) << (currentService->getLaborCost() + partsCost)
<< std::endl;
currentIndex++;
}
if (activeServicesMap.getSize() == 0)
{
std::cout << "No active services available." << std::endl;
return nullptr;
}
std::cout << "Enter service index: ";
util::read(userInputIndex);
if (activeServicesMap.find(userInputIndex) == -1)
{
std::cout << "Invalid service index." << std::endl;
return nullptr;
}
return activeServicesMap[userInputIndex];
}
/* /*
Function: createComboPackages Function: createComboPackages
Description: Creates a new combo package by selecting two active services and applying a discount. Description: Creates a new combo package by selecting two active services and applying a discount.
@@ -393,38 +892,19 @@ void AdminMenu::createComboPackages()
{ {
util::clear(); util::clear();
auto serviceList = m_controller.getServices(); auto serviceList = m_controller.getServices();
const int NUMBER_OF_SERVICE_PER_PACKAGE = 2; const int numberOfServicesInPackage = 2;
util::Vector<std::string> selectedServiceID; util::Vector<std::string> selectedServiceID;
for (int iterator = 0; iterator < NUMBER_OF_SERVICE_PER_PACKAGE; iterator++) for (int iterator = 0; iterator < numberOfServicesInPackage; iterator++)
{ {
const Service* chosenService = nullptr; const Service* chosenService = selectServiceFromServices(serviceList);
while (true)
{
chosenService = selectServiceFromServices(serviceList);
if (chosenService == nullptr) if (chosenService == nullptr)
{ {
std::cout << "Failed to create combo package!"; std::cout << "Failed to create combo package!";
util::pressEnter(); util::pressEnter();
return; return;
} }
bool alreadyChosen = false;
for (int iteratorOne = 0; iteratorOne < selectedServiceID.getSize(); iteratorOne++)
{
if (selectedServiceID[iteratorOne] == chosenService->getId())
{
alreadyChosen = true;
break;
}
}
if (alreadyChosen)
{
std::cout << "Service already selected. Please choose a different one." << std::endl;
continue;
}
selectedServiceID.push_back(chosenService->getId()); selectedServiceID.push_back(chosenService->getId());
util::clear(); util::clear();
break;
}
} }
std::string packageName; std::string packageName;
double discountPercentage; double discountPercentage;
@@ -443,6 +923,81 @@ void AdminMenu::createComboPackages()
util::pressEnter(); util::pressEnter();
} }
/*
Function: displayComboPackagesWithIndex
Description: Displays combo packages with index, ID, name, and discount percentage.
Parameter: util::Map<int, const ComboPackage*>& currentComboPackageIndexMap - combo packages map
Return type: void
*/
static void displayComboPackagesWithIndex(util::Map<int, const ComboPackage*>& currentComboPackageIndexMap)
{
for (int iterator = 0; iterator < currentComboPackageIndexMap.getSize(); iterator++)
{
const ComboPackage* currentComboPackage = currentComboPackageIndexMap.getValueAt(iterator);
if (currentComboPackage == nullptr)
{
throw std::runtime_error("Error accessing the combopackage.\n");
}
if (iterator == 0)
{
std::cout << std::left
<< std::setw(8) << "Index"
<< std::setw(10) << "ID"
<< std::setw(20) << "Package Name"
<< std::setw(15) << "Discount (%)"
<< "\n";
}
std::cout << std::left
<< std::setw(8) << currentComboPackageIndexMap.getKeyAt(iterator)
<< std::setw(10) << currentComboPackage->getId()
<< std::setw(20) << currentComboPackage->getPackageName()
<< std::setw(15) << currentComboPackage->getDiscountPercentage()
<< "\n";
}
}
/*
Function: selectComboPackage
Description: Allows the admin to select an active combo package by index.
Parameter: util::Map<std::string, const ComboPackage*>& currentComboPackages - combo packages list
Return type: std::string - ID of the selected combo package
*/
static std::string selectComboPackage(util::Map<std::string, const ComboPackage*>& currentComboPackages)
{
util::Map<int, const ComboPackage*> currentComboPackageIndexMap;
if (currentComboPackages.getSize() == 0)
{
throw std::runtime_error("No combo packages are available.\n");
}
int currentIndex = 1, choice, selectedIndex;
for (int iterator = 0; iterator < currentComboPackages.getSize(); iterator++)
{
if (currentComboPackages.getValueAt(iterator)->getState() == util::State::INACTIVE)
{
continue;
}
currentComboPackageIndexMap.insert(currentIndex++, currentComboPackages.getValueAt(iterator));
}
if (currentComboPackageIndexMap.getSize() == 0)
{
throw std::runtime_error("No combo packages currently active.");
}
displayComboPackagesWithIndex(currentComboPackageIndexMap);
std::cout << "Enter your choice(Index): ";
util::read(choice);
selectedIndex = currentComboPackageIndexMap.find(choice);
if (selectedIndex != -1)
{
std::string selectedComboPackageID = currentComboPackageIndexMap.getValueAt(selectedIndex)->getId();
return selectedComboPackageID;
}
else
{
std::cout << "Enter a valid choice.\n";
return "";
}
}
/* /*
Function: removeComboPackage Function: removeComboPackage
Description: Removes a selected combo package from the system. Description: Removes a selected combo package from the system.
@@ -6,7 +6,6 @@ Description: Header file declaring the AdminMenu class, which provides
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#pragma once #pragma once
#include "Controller.h" #include "Controller.h"
@@ -1,30 +1,41 @@
/* /*
File: CustomerMenu.cpp File: CustomerMenu.cpp
Description: Implementation file containing the method definitions of the Description: Implements the CustomerMenu class which provides the customers console interface
CustomerMenu class, including menu handling, service selection, in the Vehicle Service Management System. Handles menu display, user input, and
combo package booking, profile updates, and password management. customer-specific operations such as booking services, viewing history, managing payments,
invoices, and notifications.
Author: Trenser Author: Trenser
Date: 19-May-2026 Date: 19-May-2026
*/ */
#include <iomanip> #include <iomanip>
#include <iostream>
#include "ComboPackage.h" #include "ComboPackage.h"
#include "CustomerMenu.h" #include "CustomerMenu.h"
#include "Enums.h"
#include "InputHelper.h" #include "InputHelper.h"
#include "InventoryItem.h" #include "InventoryItem.h"
#include "Invoice.h"
#include "Map.h" #include "Map.h"
#include "MenuHelper.h" #include "MenuHelper.h"
#include "OutputHelper.h" #include "OutputHelper.h"
#include "Service.h" #include "Service.h"
#include "ServiceBooking.h"
#include "Timestamp.h"
#include "User.h"
#include "Utility.h"
#include "Validator.h" #include "Validator.h"
#include "Vector.h" #include "Vector.h"
/* /*
Function: showMenu Function: showMenu
Description: Displays the customer menu and handles user input until logout is selected. Description: Displays the customer menu in a loop until the user chooses to logout.
Parameter: None Handles exceptions and ensures smooth user interaction.
Return type: void Parameters:
- None
Returns:
- void
*/ */
void CustomerMenu::showMenu() void CustomerMenu::showMenu()
{ {
while (true) while (true)
@@ -59,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)
@@ -106,34 +111,28 @@ 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;
@@ -159,13 +158,49 @@ void CustomerMenu::updateDetails()
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;
@@ -192,13 +227,48 @@ 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;
@@ -225,14 +295,193 @@ void CustomerMenu::selectComboPackage()
void CustomerMenu::viewServiceHistory() void CustomerMenu::viewServiceHistory()
{ {
util::clear();
bool hasServiceHistory = false;
const User* currentUser = m_controller.getAuthenticatedUser();
std::string currentUserID = currentUser->getId();
util::Map<std::string, const ServiceBooking*> serviceBookingsByCurrentUser = m_controller.getServiceBookingsByUser(currentUserID);
if (serviceBookingsByCurrentUser.getSize() != 0)
{
std::cout << std::left
<< std::setw(12) << "Booking ID"
<< std::setw(20) << "Technician"
<< std::setw(15) << "Vehicle Brand"
<< std::setw(15) << "Vehicle Number"
<< std::setw(15) << "Vehicle Model"
<< std::setw(10) << "Discount %"
<< std::setw(12) << "Status"
<< std::endl;
for (int iterator = 0; iterator < serviceBookingsByCurrentUser.getSize(); iterator++)
{
const ServiceBooking* currentBooking = serviceBookingsByCurrentUser.getValueAt(iterator);
std::string technicianName = currentBooking->getAssignedTechnician() == nullptr
? "Not Assigned"
: currentBooking->getAssignedTechnician()->getName();
std::cout << std::left
<< std::setw(12) << currentBooking->getId()
<< std::setw(20) << technicianName
<< std::setw(15) << currentBooking->getVehicleBrand()
<< std::setw(15) << currentBooking->getVehicleNumber()
<< std::setw(15) << currentBooking->getVehicleModel()
<< std::setw(10) << currentBooking->getDiscountPercentage()
<< std::setw(12) << util::getServiceJobStatusString(currentBooking->getStatus())
<< std::endl;
hasServiceHistory = true;
}
}
if (!hasServiceHistory)
{
std::cout << "No history available." << std::endl;
}
}
static std::string selectInvoiceFromUserForPayment(const util::Map<std::string, const Invoice*>& currentInvoices)
{
int currentIndex = 1, choice;
util::Map<int, const Invoice*> pendingInvoicesForPayment;
std::cout << std::left
<< std::setw(6) << "Index"
<< std::setw(12) << "BookingID"
<< 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::Map<std::string, const Invoice*> currentInvoices = m_controller.getInvoicesByUser();
std::string selectedID = selectInvoiceFromUserForPayment(currentInvoices);
if (selectedID == "")
{
std::cout << "Payment failed.\n";
return;
}
util::PaymentMode paymentMode = selectPaymentMode();
m_controller.completePayment(selectedID, paymentMode);
std::cout << "Payment completed successfully.\n";
}
static void displayInvoices(util::Map<std::string, const Invoice*> currentUserInvoices)
{
if (currentUserInvoices.getSize() == 0)
{
std::cout << "No invoices found for this account." << std::endl;
util::pressEnter();
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::Map<std::string, const Invoice*> currentUserInvoices = m_controller.getInvoicesByUser();
displayInvoices(currentUserInvoices);
} }
/* /*
@@ -248,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
@@ -1,9 +1,8 @@
/* /*
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
*/ */
@@ -1,35 +1,31 @@
/* /*
File: MenuHelper.h File: MenuHelper.h
Description: Header file declaring the MenuHelper class, which provides Description: Provides inline utility functions to support menu operations in the Vehicle Service Management System.
utility functions for menu-driven operations such as Includes helper functions for selecting, displaying, and managing notifications, as well as
notification selection and display. integrating with the controller for user interactions.
Author: Trenser Author: Trenser
Date: 21-May-2026 Date: 21-May-2026
*/ */
#pragma once #pragma once
#include <iostream>
#include <iomanip>
#include <string> #include <string>
#include "Utility.h" #include <iomanip>
#include "Controller.h"
#include "InputHelper.h"
#include "Map.h"
#include "Notification.h"
#include "OutputHelper.h"
#include "Vector.h" #include "Vector.h"
#include "Validator.h" #include "Controller.h"
#include "Service.h" #include "Notification.h"
#include "ComboPackage.h" #include "Map.h"
#include "Utility.h" #include "InputHelper.h"
#include "OutputHelper.h"
/* /*
Function: selectNotification Function: selectNotification
Description: Displays a list of notifications with index, ID, title, and timestamp. Description: Displays a list of notifications with index, ID, title, and timestamp,
Allows the user to select a notification by index. Returns the selected then allows the user to select one by index.
notification or nullptr if the selection is invalid. Parameters:
Parameter: const util::Vector<const Notification*>& notifications - list of notifications - notifications: Vector of Notification pointers to be displayed.
Return type: const Notification* - pointer to the selected notification Returns:
- const Notification* representing the selected notification.
- nullptr if no notifications are available or if the selection is invalid.
*/ */
inline const Notification* selectNotification(const util::Vector<const Notification*>& notifications) inline const Notification* selectNotification(const util::Vector<const Notification*>& notifications)
{ {
@@ -118,412 +114,3 @@ inline void viewAndDeleteNotification(Controller& controller)
controller.deleteNotification(selectedNotification->getId()); controller.deleteNotification(selectedNotification->getId());
util::pressEnter(); util::pressEnter();
} }
/*
Function: changePassword
Description: Helper function to change password
Parameter: controller: Reference to the Controller object used to manage notifications.
Return type: void
*/
inline void changePasswordHelper(Controller& controller)
{
util::clear();
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;
}
controller.changePassword(newPassword);
std::cout << "Password changed successfully\n";
util::pressEnter();
break;
}
}
/*
Function: filterActiveUsers
Description: Filters out inactive users and returns a map of active users.
Parameter: const util::Map<std::string, const User*>& listOfUsers - all users
Return type: util::Map<std::string, const User*>
*/
inline util::Map<std::string, const User*> filterActiveUsers(const util::Map<std::string, const User*>& listOfUsers)
{
util::Map<std::string, const User*> activeUsers;
int inventorySize = listOfUsers.getSize();
for (int index = 0; index < inventorySize; index++)
{
const User* user = listOfUsers.getValueAt(index);
if (user != nullptr && user->getState() != util::State::INACTIVE)
{
activeUsers.insert(user->getId(), user);
}
}
return activeUsers;
}
/*
Function: displayAllActiveUsers
Description: Displays all active users in a tabular format with index, ID, username, and type.
Parameter: util::Map<std::string, const User*>& activeUsers - active users list
int activeUserCount - number of active users
Return type: void
*/
inline void displayAllActiveUsers(util::Map<std::string, const User*>& activeUsers, int activeUserCount)
{
std::cout << std::left << std::setw(10) << "Index"
<< std::setw(15) << "User ID"
<< std::setw(25) << "Username"
<< std::setw(25) << "User Type"
<< std::endl;
for (int iterator = 0; iterator < activeUserCount; iterator++)
{
const User* user = activeUsers.getValueAt(iterator);
if (user != nullptr)
{
std::cout << std::left << std::setw(10) << (iterator + 1)
<< std::setw(15) << user->getId()
<< std::setw(25) << user->getUserName()
<< std::setw(25) << util::getUserTypeString(user->getUserType())
<< std::endl;
}
else
{
std::cout << "No users found.\n";
util::pressEnter();
return;
}
}
}
/*
Function: selectServiceFromServices
Description: Displays active services and allows the customer to select one by index.
Parameter: const util::Map<std::string, const Service*>& services - list of services
Return type: const Service* - selected service
*/
inline const Service* selectServiceFromServices(const util::Map<std::string, const Service*>& services)
{
util::Map<int, const Service*> activeServicesMap;
int currentIndex = 1;
int userInputIndex;
std::cout << std::left
<< std::setw(10) << "Index"
<< std::setw(15) << "Service ID"
<< std::setw(25) << "Service Name"
<< std::setw(15) << "Estimated Cost"
<< std::endl;
for (int index = 0; index < services.getSize(); index++)
{
const Service* currentService = services.getValueAt(index);
if (currentService == nullptr)
{
throw std::runtime_error("Warning: Encountered a null service\n");
continue;
}
if (currentService->getState() != util::State::ACTIVE)
{
continue;
}
activeServicesMap.insert(currentIndex, currentService);
double partsCost = util::calculatePartsCost(currentService);
std::cout << std::left
<< std::setw(10) << currentIndex
<< std::setw(15) << currentService->getId()
<< std::setw(25) << currentService->getName()
<< std::setw(15) << (currentService->getLaborCost() + partsCost)
<< std::endl;
currentIndex++;
}
if (activeServicesMap.getSize() == 0)
{
std::cout << "No active services available." << std::endl;
return nullptr;
}
std::cout << "Enter service index: ";
util::read(userInputIndex);
if (activeServicesMap.find(userInputIndex) == -1)
{
std::cout << "Invalid service index." << std::endl;
return nullptr;
}
return activeServicesMap[userInputIndex];
}
/*
Function: selectComboPackageFromPackages
Description: Displays active combo packages and allows the customer to select one by index.
Parameter: const util::Map<std::string, const ComboPackage*>& comboPackages - list of combo packages
Return type: const ComboPackage* - selected combo package
*/
inline const ComboPackage* selectComboPackageFromPackages(const util::Map<std::string, const ComboPackage*>& comboPackages)
{
util::Map<int, const ComboPackage*> activeComboPackages;
int currentIndex = 1;
int userInputIndex;
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];
}
/*
Function: sendLowStockAlertsToAdmins (static helper)
Description: Sends low stock alert notifications to all admin users for a given inventory item.
Parameters:
- inventoryManagementService: InventoryManagementService&, service used to send notifications
- inventoryItem: const InventoryItem*, pointer to the low-stock inventory item
- adminUsers: const util::Vector<User*>&, list of admin users to notify
Returns:
- None
*/
/*
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.
*/
inline 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: filterActiveItems
Description: Filters out inactive inventory items and returns a map
containing only active items.
Parameter: const util::Map<std::string, const InventoryItem*>& inventoryItems -
map of all inventory items
Return type: util::Map<std::string, const InventoryItem*>
*/
inline util::Map<std::string, const InventoryItem*> filterActiveItems(const util::Map<std::string, const InventoryItem*>& inventoryItems)
{
util::Map<std::string, const InventoryItem*> activeItems;
int inventorySize = inventoryItems.getSize();
for (int index = 0; index < inventorySize; index++)
{
const InventoryItem* item = inventoryItems.getValueAt(index);
if (item != nullptr && item->getState() != util::State::INACTIVE)
{
activeItems.insert(item->getId(), item);
}
}
return activeItems;
}
/*
Function: displayInventoryWithItems
Description: Displays inventory items in a tabular format with index, ID,
part name, quantity, and price.
Parameter: util::Map<std::string, const InventoryItem*>& inventoryItems -
map of inventory items to display
Return type: void
*/
inline void displayInventoryWithItems(util::Map<std::string, const InventoryItem*>& inventoryItems)
{
int inventorySize = inventoryItems.getSize();
std::cout << std::left << std::setw(10) << "Index"
<< std::setw(15) << "Item ID"
<< std::setw(25) << "Part Name"
<< std::setw(10) << "Quantity"
<< std::setw(10) << "Price"
<< std::endl;
for (int iterator = 0; iterator < inventorySize; iterator++)
{
const InventoryItem* item = inventoryItems.getValueAt(iterator);
if (item != nullptr)
{
std::cout << std::left << std::setw(10) << (iterator + 1)
<< std::setw(15) << item->getId()
<< std::setw(25) << item->getPartName()
<< std::setw(10) << item->getQuantity()
<< std::setw(10) << item->getPrice()
<< std::endl;
}
}
}
/*
Function: addQuantityToItem
Description: Allows the admin to select an active inventory item and
increase its stock quantity.
Parameter: util::Map<std::string, const InventoryItem*>& inventoryItems -
map of inventory items
Controller& m_controller - controller instance to update stock
Return type: void
*/
inline void addQuantityToItem(util::Map<std::string, const InventoryItem*>& inventoryItems, Controller& m_controller)
{
int itemIndex;
int quantity;
auto activeItems = filterActiveItems(inventoryItems);
int activeSize = activeItems.getSize();
if (activeSize == 0)
{
std::cout << "No active items available in Inventory" << std::endl;
return;
}
displayInventoryWithItems(activeItems);
std::cout << "Enter the index of the item to update: ";
util::read(itemIndex);
if (itemIndex < 1 || itemIndex > activeSize)
{
std::cout << "Invalid index selected." << std::endl;
return;
}
std::cout << "Enter quantity to add: ";
util::read(quantity);
if (quantity < 0)
{
std::cout << "The quantity should be Greater than 0." << std::endl;
return;
}
const InventoryItem* selectedItem = activeItems.getValueAt(itemIndex - 1);
if (selectedItem != nullptr)
{
std::string selectedItemId = selectedItem->getId();
m_controller.addInventoryItemStock(selectedItemId, quantity);
std::cout << "Updated " << selectedItem->getPartName()
<< " stock. New quantity: " << selectedItem->getQuantity()
<< std::endl;
}
else
{
std::cout << "Error: Selected item could not be found." << std::endl;
}
}
/*
Function: displayComboPackagesWithIndex
Description: Displays combo packages with index, ID, name, and discount percentage.
Parameter: util::Map<int, const ComboPackage*>& currentComboPackageIndexMap - combo packages map
Return type: void
*/
inline void displayComboPackagesWithIndex(util::Map<int, const ComboPackage*>& currentComboPackageIndexMap)
{
for (int iterator = 0; iterator < currentComboPackageIndexMap.getSize(); iterator++)
{
const ComboPackage* currentComboPackage = currentComboPackageIndexMap.getValueAt(iterator);
if (currentComboPackage == nullptr)
{
throw std::runtime_error("Error accessing the combopackage.\n");
}
if (iterator == 0)
{
std::cout << std::left
<< std::setw(8) << "Index"
<< std::setw(10) << "ID"
<< std::setw(20) << "Package Name"
<< std::setw(15) << "Discount (%)"
<< "\n";
}
std::cout << std::left
<< std::setw(8) << currentComboPackageIndexMap.getKeyAt(iterator)
<< std::setw(10) << currentComboPackage->getId()
<< std::setw(20) << currentComboPackage->getPackageName()
<< std::setw(15) << currentComboPackage->getDiscountPercentage()
<< "\n";
}
}
/*
Function: selectComboPackage
Description: Allows the admin to select an active combo package by index.
Parameter: util::Map<std::string, const ComboPackage*>& currentComboPackages - combo packages list
Return type: std::string - ID of the selected combo package
*/
inline std::string selectComboPackage(util::Map<std::string, const ComboPackage*>& currentComboPackages)
{
util::Map<int, const ComboPackage*> currentComboPackageIndexMap;
if (currentComboPackages.getSize() == 0)
{
throw std::runtime_error("No combo packages are available.\n");
}
int currentIndex = 1, choice, selectedIndex;
for (int iterator = 0; iterator < currentComboPackages.getSize(); iterator++)
{
if (currentComboPackages.getValueAt(iterator)->getState() == util::State::INACTIVE)
{
continue;
}
currentComboPackageIndexMap.insert(currentIndex++, currentComboPackages.getValueAt(iterator));
}
if (currentComboPackageIndexMap.getSize() == 0)
{
throw std::runtime_error("No combo packages currently active.");
}
displayComboPackagesWithIndex(currentComboPackageIndexMap);
std::cout << "Enter your choice(Index): ";
util::read(choice);
selectedIndex = currentComboPackageIndexMap.find(choice);
if (selectedIndex != -1)
{
std::string selectedComboPackageID = currentComboPackageIndexMap.getValueAt(selectedIndex)->getId();
return selectedComboPackageID;
}
else
{
std::cout << "Enter a valid choice.\n";
return "";
}
}
@@ -6,12 +6,16 @@ Description: Implementation file containing the method definitions of the
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#include "TechnicianMenu.h"
#include <iomanip>
#include "Enums.h"
#include "InputHelper.h" #include "InputHelper.h"
#include "JobCard.h"
#include "MenuHelper.h"
#include "OutputHelper.h" #include "OutputHelper.h"
#include "Service.h"
#include "TechnicianMenu.h"
#include "Validator.h" #include "Validator.h"
#include "MenuHelper.h"
#include "MenuHelper.h"
/* /*
Function: showMenu Function: showMenu
@@ -79,9 +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)
{
int currentIndex = 1;
int choice;
bool hasIncompleteJobCard = false;
std::cout << std::left
<< std::setw(6) << "Index"
<< std::setw(12) << "BookingID"
<< std::setw(12) << "JobID"
<< std::setw(20) << "ServiceName"
<< std::setw(12) << "ServiceID"
<< std::endl;
for (int iterator = 0; iterator < assignedJobCards.getSize(); iterator++)
{
const JobCard* currentJobCard = assignedJobCards.getValueAt(iterator);
if (currentJobCard && (currentJobCard->getStatus() == util::ServiceJobStatus::STARTED))
{
std::cout << std::left << std::setw(6) << currentIndex
<< std::setw(12) << currentJobCard->getBookingId()
<< std::setw(12) << currentJobCard->getId()
<< std::setw(20) << currentJobCard->getService()->getName()
<< std::setw(12) << currentJobCard->getServiceId()
<< std::endl;
hasIncompleteJobCard = true;
incompleteJobCards.insert(currentIndex++, currentJobCard);
}
}
if (!hasIncompleteJobCard)
{
std::cout << "No pending jobs are present.\n";
return "";
}
std::cout << "Select the Job Card to complete (Index): ";
util::read(choice);
int selectedJobCardIndex = incompleteJobCards.find(choice);
if (selectedJobCardIndex != -1)
{
const JobCard* selectedJobCard = incompleteJobCards.getValueAt(selectedJobCardIndex);
return selectedJobCard->getId();
}
else
{
std::cout << "Invalid choice.\n";
return "";
}
}
void TechnicianMenu::completeJob() void TechnicianMenu::completeJob()
{ {
util::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 == "")
{
std::cout << "Failed to complete the job.\n";
}
else
{
m_controller.completeJob(selectedJobID);
std::cout << "Job marked as completed.\n";
}
} }
/* /*
@@ -114,8 +178,23 @@ Description: Allows the technician to change their password after validation.
Parameter: None Parameter: None
Return type: void Return type: void
*/ */
void TechnicianMenu::changePassword() void TechnicianMenu::changePassword()
{ {
changePasswordHelper(m_controller); std::string newPassword;
while (true)
{
util::clear();
std::cout << "Enter new password: ";
util::read(newPassword);
if (!util::isPasswordValid(newPassword))
{
std::cout << "Error: Password is not strong enough!\n";
util::pressEnter();
continue;
}
m_controller.changePassword(newPassword);
std::cout << "Password changed successfully\n";
util::pressEnter();
break;
}
} }
@@ -6,7 +6,6 @@ Description: Header file declaring the TechnicianMenu class, which provides
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#pragma once #pragma once
#include "Controller.h" #include "Controller.h"
@@ -6,12 +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 "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"
/* /*
@@ -119,11 +118,11 @@ void UserInterface::login()
/* /*
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()
{ {
@@ -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"