Compare commits

..

16 Commits

Author SHA1 Message Date
Avinash Rajesh 34cb64ab1b Add standardized documentation headers 2026-05-22 13:26:02 +05:30
joelthomastrenser 826919579c Merge branch 'feature-customer-management-menu' into feature-customer-management 2026-05-21 13:22:08 +05:30
joelthomastrenser 5e3b65fc5b Merge branch 'feature-customer-management-cus007' into feature-customer-management 2026-05-21 13:20:46 +05:30
joelthomastrenser ab2d41a942 Merge branch 'feature-customer-management-cus006' into feature-customer-management 2026-05-21 13:18:15 +05:30
joelthomastrenser de5311f9f9 Merge branch 'feature-customer-management-cus005' into feature-customer-management 2026-05-21 13:17:03 +05:30
joelthomastrenser 7ef7f02ee4 Merge branch 'feature-customer-management-cus004' into feature-customer-management 2026-05-21 13:12:47 +05:30
joelthomastrenser 5075b383d4 Merge branch 'feature-customer-management-cus003' into feature-customer-management 2026-05-21 13:07:58 +05:30
joelthomastrenser 448cb016a3 Merge branch 'feature-customer-management-cus002' into feature-customer-management 2026-05-21 13:04:35 +05:30
joelthomastrenser df39c0588b Implement Login functionality
<UserStory> CUS001:Login </UserStory>

<Changes>
    1. Added login implementation in AuthenticationManagementService to validate username and password from stored user records.
    2. Connected Controller::login() with AuthenticationManagementService login logic.
    3. Added getAuthenticatedUser() integration in Controller for retrieving the logged-in user.
    4. Implemented login flow in UserInterface to collect credentials and validate login.
    5. Added role-based menu navigation for Admin, Technician, and Customer after successful login.
    6. Added error handling to display "Invalid Username or Password" for failed login attempts.
    7. Added required includes and controller member dependency for authentication support.
    8. Added a check to create a default admin automatically if no admin exists in the system on startup
</Changes>

<Test>

Login functionality validation

Precondition:
1. System is running.
2. User records are available in the data store.
3. Valid username and password exist for a registered user.

Steps:
1. Launch the application.
2. Select the login option from the main menu.
3. Enter a valid username and password.
   - Verify that the entered credentials are validated.
   - Verify that access is granted and the correct menu is shown based on user type.
4. Enter an invalid username or password.
   - Verify that the message "Invalid Username or Password" is displayed.

</Test>

<Review>
Sreeja Reghukumar, please review
</Review>
2026-05-21 11:26:48 +05:30
joelthomastrenser be306781b1 Implement Customer Menu
* Added Customer Menu display with all customer options
* Added menu choice handling using switch case
* Connected menu options to corresponding customer functions
* Added invalid choice message
* Added logout option handling
2026-05-21 10:44:42 +05:30
joelthomastrenser 9533a74d87 Implement Create Customer functionality
<UserStory> CUS004: Register Customer Account </UserStory>

<Changes>
    1. Added customer registration flow in UserInterface to collect username, name, email, password, and phone inputs.
    2. Added validation for email, password, and phone number before proceeding with registration.
    3. Updated Controller::createCustomer() and UserManagementService::createUser() to support customer registration with full user details including name.
    4. Added duplicate username validation in UserManagementService using map predicate search.
    5. Added user creation and insertion logic in UserManagementService to store newly registered customer records in DataStore.
    6. Added observer attachment for newly registered users to inventory(only for admins), payment, and service notification services.
    7. Added registration confirmation message display after successful customer creation.
</Changes>

<Test>

  Precondition:
  1. Application is running and user is on the main login/register menu.
  2. DataStore is initialized and available for storing user records.
  3. Existing customer records may already be present in the system.

  Steps:
  1. Select the Register Customer option.
  2. Enter valid username, name, email, password, and phone number.
  3. Submit the registration request.
     - Verify that the system accepts valid inputs and creates the customer account.
  4. Attempt registration using an already existing username.
     - Verify that the duplicate registration is rejected.
  5. Register again with valid unique details.
     - Verify that the registration confirmation message is displayed.
  6. Re-access application data after registration.
     - Verify that the customer data is stored persistently.

</Test>

<Review>
Sreeja Reghukumar, please review
</Review>
2026-05-20 17:45:02 +05:30
joelthomastrenser 183a06cd2f Implement Purchase Combo functionality
<UserStory> CUS007: Purchase Combo Package </UserStory>

<Changes>
    1. Added combo package selection flow in CustomerMenu to list all active combo packages with estimated cost and allow customer selection.
    2. Implemented Controller::purchaseComboPackage to delegate combo package booking requests to ServiceManagementService.
    3. Added ServiceManagementService::purchaseComboPackage logic to validate authenticated user, fetch selected combo package, create a ServiceBooking, persist it in DataStore, and send booking confirmation notification.
    4. Added helper functions in CustomerMenu to calculate combo package estimated cost based on included services and required inventory items.
    5. Updated ServiceBooking model to use User* reference for assigned technician and simplified constructor to align booking model with object references.

</Changes>

<Test>

  Precondition:
  1. Customer account exists and is logged into the system.
  2. Active combo packages are available in the system.
  3. Combo package contains one or more active services.
  4. Service bookings and notifications can be created successfully.

  Steps:
  1. Navigate to Customer Menu and select the combo package booking option.
  2. View the list of available combo packages.
    - Verify that all active combo packages are displayed with their details.
  3. Select one combo package and enter vehicle number, vehicle brand, and vehicle model.
    - Verify that a booking request is generated successfully.
  4. Complete the booking flow.
    - Verify that a confirmation message is displayed to the customer.
  5. Check customer notifications.
    - Verify that a booking confirmation notification is received.

</Test>

<Review>
Sreeja Reghukumar, please review
</Review>
2026-05-20 13:56:42 +05:30
joelthomastrenser 76f13b526e Implement Purchase Individual Service functionality
<UserStory> CUS006 Purchase Individual Service </UserStory>

<Changes>
    1. Added service selection flow in CustomerMenu to display active services, allow customer to choose a service, and collect vehicle details for booking.
    2. Implemented Controller::purchaseService to delegate service booking requests to ServiceManagementService.
    3. Added ServiceManagementService::purchaseService logic to validate authenticated user, fetch selected services, create a ServiceBooking, and persist it in DataStore.
    4. Updated ServiceBooking constructor and assigned technician handling to use User* references instead of technician name strings.
    5. Integrated ServiceManagementService dependency into Controller
</Changes>

<Test>

 Validate customer service booking flow and service status tracking

  Precondition:
  1. Customer account exists and is logged into the system.
  2. Active services are available in the system.
  3. Service bookings can be created and stored in DataStore.
  4. Technician account exists to update service status.

  Steps:
  1. Navigate to Customer Menu and select the individual service booking option.
  2. View the list of active services and select a service.
  3. Enter vehicle number, vehicle brand, and vehicle model, then confirm booking.
    - Verify that the service booking is created successfully with an initial status.
  4. Technician updates the service booking status.
    - Verify that the latest status is reflected in the system.
  5. Customer refreshes or views service booking history.
    - Verify that the updated status is shown correctly in booking history.

</Test>

<Review>
Sreeja Reghukumar, please review
</Review>
2026-05-20 13:51:36 +05:30
joelthomastrenser 9c2663db74 Implement Update Customer Profile Details
<UserStory> CUS005: Update Customer Profile Details </UserStory>

<Changes>
    1. Added update profile flow in CustomerMenu to collect new email and phone number inputs.
    2. Added validation for updated email and phone number before saving changes.
    3. Updated Controller::updateUserDetails() to fetch the authenticated user and delegate profile update to UserManagementService.
    4. Added user existence validation in UserManagementService before updating profile details.
    5. Added logic in UserManagementService to update stored email and phone details for the selected user.
    6. Added profile update confirmation message after successful save.
</Changes>

<Test>

 Update Customer Profile Details

  Precondition:
  1. Application is running and a customer is logged into the system.
  2. Customer record exists in DataStore.
  3. Customer has existing profile details stored in the system.

  Steps:
  1. Select the Update Profile Details option.
  2. Verify that the current profile details are displayed.
     - Verify that the system shows the customer’s existing details.
  3. Enter a new valid email address and phone number.
  4. Save the updated details.
     - Verify that the system accepts the changes and displays a success message.
  5. Create or view a future booking using the same customer account.
     - Verify that the updated profile details are reflected in future bookings.

</Test>

<Review>
Sreeja Reghukumar, please review
</Review>
2026-05-19 20:51:34 +05:30
joelthomastrenser cc887b9bc0 Implement Change Password
<UserStory> CUS003: Implement change password functionality </UserStory>

<Changes>
    1. Connected Controller::changePassword() with AuthenticationManagementService password update logic.
    2. Added password validation before updating the user password.
    3. Added logged-in user check before allowing password changes.
    4. Implemented password update logic in AuthenticationManagementService.
    5. Added change password flow in CustomerMenu to collect new password input and trigger password update.
    6. Added success message display after password is changed successfully.
</Changes>

<Test>

Change password functionality validation

Precondition:
1. System is running.
2. A registered user exists in the data store.
3. User is logged in and customer menu is active.

Steps:
1. Launch the application and log in with valid credentials.
2. Select the Change Password option from the customer menu.
3. Enter a new password.
   - Verify that the entered password is validated.
4. If the password is valid, complete the password change.
   - Verify that the new password is saved successfully.
   - Verify that the message "Password changed successfully" is displayed.

</Test>

<Review>
Sreeja Reghukumar, please review
</Review>
2026-05-19 19:43:33 +05:30
joelthomastrenser 5c5a44876b Implement Logout functionality
<UserStory> CUS002: Logout</UserStory>

<Changes>
    1. Connected Controller::logout() with AuthenticationManagementService logout logic.
    2. Added logout implementation in AuthenticationManagementService to clear the authenticated user session.
    3. Added logout handling in CustomerMenu to invoke controller logout when the user selects the logout option.
    4. Added authentication service dependency in Controller for logout support.
</Changes>

<Test>

Logout functionality validation

Precondition:
1. System is running.
2. A registered user exists in the data store.
3. User is logged in and customer menu is active.

Steps:
1. Launch the application and log in with valid credentials.
   - Verify that access is granted and customer menu is displayed.
2. Select the Logout option from the customer menu.
   - Verify that the logout operation is triggered immediately.
3. Complete the logout operation.
   - Verify that the authenticated user session is cleared.
4. After logout completes.
   - Verify that the user is redirected to the login menu.

</Test>

<Review>
Sreeja Reghukumar, please review
</Review>
2026-05-19 19:42:43 +05:30
24 changed files with 829 additions and 1145 deletions
@@ -171,6 +171,7 @@
<ClInclude Include="services\PaymentManagementService.h" />
<ClInclude Include="services\ServiceManagementService.h" />
<ClInclude Include="services\UserManagementService.h" />
<ClInclude Include="utilities\Config.h" />
<ClInclude Include="utilities\Enums.h" />
<ClInclude Include="utilities\InputHelper.h" />
<ClInclude Include="utilities\Map.h" />
@@ -181,6 +182,7 @@
<ClInclude Include="utilities\Vector.h" />
<ClInclude Include="views\AdminMenu.h" />
<ClInclude Include="views\CustomerMenu.h" />
<ClInclude Include="views\MenuHelper.h" />
<ClInclude Include="views\TechnicianMenu.h" />
<ClInclude Include="views\UserInterface.h" />
</ItemGroup>
@@ -233,8 +233,5 @@
<ClInclude Include="models\ComboPackage.h">
<Filter>Header Files\Models</Filter>
</ClInclude>
<ClInclude Include="utilities\Utility.h">
<Filter>Header Files\Utilities</Filter>
</ClInclude>
</ItemGroup>
</Project>
@@ -1,24 +1,31 @@
/*
File: Controller.cpp
Description: Implementation file containing the method definitions of the
Controller class, which manages authentication, users, services,
combo packages, and inventory operations.
Controller class, including authentication, user creation,
service purchasing, and system checks.
Author: Trenser
Date:19-May-2026
*/
#include <stdexcept>
#include "Controller.h"
#include "ComboPackage.h"
#include "Enums.h"
#include "User.h"
/*
Function: login
Description: Authenticates a user by delegating to the authentication management service.
Parameter: const std::string& username - users username
const std::string& password - users password
Return type: bool - true if login successful, false otherwise
*/
bool Controller::login(const std::string& username, const std::string& password)
{
return false;
return m_authenticationManagementService.login(username, password);
}
/*
Function: logout
Description: Logs out the currently authenticated user by delegating
to the authentication management service.
Description: Logs out the currently authenticated user.
Parameter: None
Return type: void
*/
@@ -29,9 +36,8 @@ void Controller::logout()
/*
Function: changePassword
Description: Updates the password of the authenticated user by delegating
to the authentication management service.
Parameter: const std::string& newPassword - the new password to set
Description: Changes the password of the currently authenticated user.
Parameter: const std::string& newPassword - new password to set
Return type: void
*/
void Controller::changePassword(const std::string& newPassword)
@@ -39,32 +45,51 @@ void Controller::changePassword(const std::string& newPassword)
m_authenticationManagementService.changePassword(newPassword);
}
void Controller::createCustomer(const std::string& username, const std::string& password, const std::string& email, const std::string& phone)
/*
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)
{
}
const User* Controller::getAuthenticatedUser()
{
return nullptr;
m_userManagementService.createUser(username, name, password, email, phone, util::UserType::CUSTOMER);
}
/*
Function: createTechnician
Description: Creates a new technician account with provided details by
delegating to the user management service.
Parameter: const std::string& username - technician's username
const std::string& password - technician's password
const std::string& email - technician's email address
const std::string& phoneNumber - technician's phone number
Return type: void
Function: getAuthenticatedUser
Description: Retrieves the currently authenticated user.
Parameter: None
Return type: const User* - pointer to the authenticated user
*/
void Controller::createTechnician(const std::string& username, const std::string& name, const std::string& password, const std::string& email, const std::string& phoneNumber)
const User* Controller::getAuthenticatedUser()
{
m_userManagementService.createUser(username, name, password, email, phoneNumber, util::UserType::TECHNICIAN);
return m_authenticationManagementService.getAuthenticatedUser();
}
void Controller::createTechnician(const std::string& username, const std::string& password, const std::string& email, const std::string& phone)
{
}
/*
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)
{
User* authenticatedUser = m_authenticationManagementService.getAuthenticatedUser();
if (authenticatedUser == nullptr)
{
throw std::runtime_error("No user currently logged in!");
}
m_userManagementService.updateUserDetails(authenticatedUser->getId(), email, phone);
}
util::Map<std::string, const Service*> Controller::getServices()
@@ -72,34 +97,37 @@ util::Map<std::string, const Service*> Controller::getServices()
return util::Map<std::string, const Service*>();
}
/*
Function: getComboPackages
Description: Retrieves all available combo packages from the service
management service and constructs a read-only map.
Parameter: None
Return type: util::Map<std::string, const ComboPackage*>
*/
util::Map<std::string, const ComboPackage*> Controller::getComboPackages()
{
util::Map<std::string, ComboPackage*> currentAvailableComboPackages = m_serviceManagementService.getComboPackages();
util::Map<std::string, const ComboPackage*> readOnlyComboPackages;
for (int iterator = 0; iterator < currentAvailableComboPackages.getSize(); iterator++)
{
ComboPackage* currentComboPackage = currentAvailableComboPackages.getValueAt(iterator);
if (currentComboPackage)
{
readOnlyComboPackages.insert(currentComboPackage->getId(), currentComboPackage);
}
}
return readOnlyComboPackages;
return util::Map<std::string, const ComboPackage*>();
}
/*
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)
{
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)
{
m_serviceManagementService.purchaseComboPackage(comboPackageID, vehicleNumber, vehicleBrand, vehicleModel);
}
util::Map<std::string, const InventoryItem*> Controller::getInventoryItems()
@@ -130,22 +158,9 @@ util::Map<std::string, const ServiceBooking*> Controller::getServiceBookingsByUs
return util::Map<std::string, const ServiceBooking*>();
}
/*
Function: getUsers
Description: Retrieves all users from the user management service and
constructs a read-only map.
Parameter: None
Return type: util::Map<std::string, const User*>
*/
util::Map<std::string, const User*> Controller::getUsers()
{
auto listOfUsers = m_userManagementService.getUsers();
util::Map<std::string, const User*> readOnlyUserList;
for (int iterator = 0; iterator < listOfUsers.getSize(); iterator++)
{
readOnlyUserList.insert(listOfUsers.getKeyAt(iterator), listOfUsers.getValueAt(iterator));
}
return readOnlyUserList;
return util::Map<std::string, const User*>();
}
util::Map<std::string, const User*> Controller::getUsers(util::UserType userType)
@@ -174,49 +189,16 @@ void Controller::completeJob(const std::string& jobID)
{
}
/*
Function: removeUser
Description: Removes a user by ID. Cancels associated service bookings
and technician jobs before removing the user from the system.
Parameter: const std::string& userID - ID of the user to remove
Return type: void
*/
void Controller::removeUser(const std::string& userID)
{
User* user = m_userManagementService.getUser(userID);
if (!user)
{
throw std::runtime_error("Error User not Found.\n");
}
m_serviceManagementService.cancelCustomerServiceBookings(userID);
m_serviceManagementService.cancelTechnicianJobs(userID);
m_userManagementService.removeUser(userID);
}
/*
Function: createComboPackage
Description: Creates a new combo package with specified services and discount
percentage by delegating to the service management service.
Parameter: const std::string& name - name of the combo package
const util::Vector<std::string>& serviceIDs - list of service IDs
double discountPercentage - discount percentage for the package
Return type: void
*/
void Controller::createComboPackage(const std::string& name, const util::Vector<std::string>& serviceIDs, double discountPercentage)
{
m_serviceManagementService.createComboPackage(name, serviceIDs, discountPercentage);
}
/*
Function: removeComboPackage
Description: Removes a combo package by ID by delegating to the service
management service.
Parameter: const std::string& comboPackageID - ID of the combo package
Return type: void
*/
void Controller::removeComboPackage(const std::string& comboPackageID)
{
m_serviceManagementService.removeComboPackage(comboPackageID);
}
util::Map<std::string, const Invoice*> Controller::getInvoicesByUser()
@@ -241,7 +223,14 @@ void Controller::configureNotifications(const std::string& userID, bool paymentN
{
}
/*
Function: runSystemChecks
Description: Runs system checks to ensure critical configurations, such as verifying admin existence.
Parameter: None
Return type: void
*/
void Controller::runSystemChecks()
{
m_userManagementService.ensureAdminExists();
}
@@ -1,18 +1,18 @@
/*
File: Controller.h
Description: Header file declaring the Controller class, which manages
user authentication, inventory, services, bookings, job cards,
invoices, and notifications in the system.
Description: Header file declaring the Controller class, which coordinates
authentication, user management, service management, inventory,
and notifications across the Vehicle Service System.
Author: Trenser
Date:19-May-2026
*/
#pragma once
#include <string>
#include "Map.h"
#include <string>
#include "Enums.h"
#include "AuthenticationManagementService.h"
#include "UserManagementService.h"
#include "ServiceManagementService.h"
#include "AuthenticationManagementService.h"
class Service;
class ComboPackage;
@@ -33,9 +33,9 @@ public:
bool login(const std::string& username, const std::string& password);
void logout();
void changePassword(const std::string& newPassword);
void createCustomer(const std::string& username, 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();
void createTechnician(const std::string& username, const std::string& name, const std::string& password, const std::string& email, const std::string& phoneNumber);
void createTechnician(const std::string& username, const std::string& password, 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 ComboPackage*> getComboPackages();
@@ -1,44 +1,14 @@
/*
File: JobCard.cpp
Description: Implementation file containing the method definitions of the
JobCard class, including constructors, getters, and setters
for job card attributes.
Author: Trenser
Date:19-May-2026
*/
#include "JobCard.h"
int JobCard::m_uid = 0;
/*
Function: JobCard
Description: Default constructor that initializes a new job card with
a unique ID and default values.
Parameter: None
Return type: Constructor
*/
JobCard::JobCard()
: m_id("JC" + std::to_string(++m_uid)),
m_booking(nullptr),
m_service(nullptr),
m_technician(nullptr),
m_status(util::ServiceJobStatus()) {}
m_status(ServiceJobStatus()) {}
/*
Function: JobCard
Description: Parameterized constructor that initializes a job card with
booking, service, technician, and status details.
Parameter: const std::string& bookingId - ID of the booking
ServiceBooking* booking - pointer to the booking object
Service* service - pointer to the service object
const std::string& serviceId - ID of the service
const std::string& technicianId - ID of the technician
User* technician - pointer to the technician object
const util::Timestamp& assignedDate - date when job was assigned
util::ServiceJobStatus status - current status of the job
const util::Timestamp& completionDate - date when job was completed
Return type: Constructor
*/
JobCard::JobCard(const std::string& bookingId,
ServiceBooking* booking,
Service* service,
@@ -46,7 +16,7 @@ JobCard::JobCard(const std::string& bookingId,
const std::string& technicianId,
User* technician,
const util::Timestamp& assignedDate,
util::ServiceJobStatus status,
ServiceJobStatus status,
const util::Timestamp& completionDate
)
: m_id("JC" + std::to_string(++m_uid)),
@@ -60,221 +30,101 @@ JobCard::JobCard(const std::string& bookingId,
m_status(status),
m_completionDate(completionDate) {}
/*
Function: getId
Description: Retrieves the unique identifier of the job card.
Parameter: None
Return type: const std::string&
*/
const std::string& JobCard::getId() const
{
return m_id;
}
/*
Function: getBookingId
Description: Retrieves the booking ID associated with the job card.
Parameter: None
Return type: const std::string&
*/
const std::string& JobCard::getBookingId() const
{
return m_bookingId;
}
/*
Function: getBooking
Description: Retrieves the booking object associated with the job card.
Parameter: None
Return type: ServiceBooking*
*/
ServiceBooking* JobCard::getBooking() const
{
return m_booking;
}
/*
Function: getService
Description: Retrieves the service object associated with the job card.
Parameter: None
Return type: Service*
*/
Service* JobCard::getService() const
{
return m_service;
}
/*
Function: getServiceId
Description: Retrieves the service ID associated with the job card.
Parameter: None
Return type: const std::string&
*/
const std::string& JobCard::getServiceId() const
{
return m_serviceId;
}
/*
Function: getTechnicianId
Description: Retrieves the technician ID assigned to the job card.
Parameter: None
Return type: const std::string&
*/
const std::string& JobCard::getTechnicianId() const
{
return m_technicianId;
}
/*
Function: getTechnician
Description: Retrieves the technician object assigned to the job card.
Parameter: None
Return type: User*
*/
User* JobCard::getTechnician() const
{
return m_technician;
}
/*
Function: getAssignedDate
Description: Retrieves the date when the job was assigned.
Parameter: None
Return type: const util::Timestamp&
*/
const util::Timestamp& JobCard::getAssignedDate() const
{
return m_assignedDate;
}
/*
Function: getStatus
Description: Retrieves the current status of the job card.
Parameter: None
Return type: util::ServiceJobStatus
*/
util::ServiceJobStatus JobCard::getStatus() const
ServiceJobStatus JobCard::getStatus() const
{
return m_status;
}
/*
Function: getCompletionDate
Description: Retrieves the completion date of the job card.
Parameter: None
Return type: const util::Timestamp&
*/
const util::Timestamp& JobCard::getCompletionDate() const
{
return m_completionDate;
}
/*
Function: setId
Description: Sets the unique identifier of the job card.
Parameter: const std::string& id - new job card ID
Return type: void
*/
void JobCard::setId(const std::string& id)
{
m_id = id;
}
/*
Function: setBookingId
Description: Sets the booking ID for the job card.
Parameter: const std::string& bookingId - new booking ID
Return type: void
*/
void JobCard::setBookingId(const std::string& bookingId)
{
m_bookingId = bookingId;
}
/*
Function: setBooking
Description: Sets the booking object for the job card.
Parameter: ServiceBooking* booking - pointer to the booking object
Return type: void
*/
void JobCard::setBooking(ServiceBooking* booking)
{
m_booking = booking;
}
/*
Function: setService
Description: Sets the service object for the job card.
Parameter: Service* service - pointer to the service object
Return type: void
*/
void JobCard::setService(Service* service)
{
m_service = service;
}
/*
Function: setServiceId
Description: Sets the service ID for the job card.
Parameter: const std::string& serviceId - new service ID
Return type: void
*/
void JobCard::setServiceId(const std::string& serviceId)
{
m_serviceId = serviceId;
}
/*
Function: setTechnicianId
Description: Sets the technician ID for the job card.
Parameter: const std::string& technicianId - new technician ID
Return type: void
*/
void JobCard::setTechnicianId(const std::string& technicianId)
{
m_technicianId = technicianId;
}
/*
Function: setTechnician
Description: Sets the technician object for the job card.
Parameter: User* technician - pointer to the technician object
Return type: void
*/
void JobCard::setTechnician(User* technician)
{
m_technician = technician;
}
/*
Function: setAssignedDate
Description: Sets the assigned date for the job card.
Parameter: const util::Timestamp& assignedDate - new assigned date
Return type: void
*/
void JobCard::setAssignedDate(const util::Timestamp& assignedDate)
{
m_assignedDate = assignedDate;
}
/*
Function: setStatus
Description: Sets the status of the job card.
Parameter: util::ServiceJobStatus status - new job status
Return type: void
*/
void JobCard::setStatus(util::ServiceJobStatus status)
void JobCard::setStatus(ServiceJobStatus status)
{
m_status = status;
}
/*
Function: setCompletionDate
Description: Sets the completion date for the job card.
Parameter: const util::Timestamp& completionDate - new completion date
Return type: void
*/
void JobCard::setCompletionDate(const util::Timestamp& completionDate)
{
m_completionDate = completionDate;
@@ -1,20 +1,13 @@
/*
File: JobCard.h
Description: Header file declaring the JobCard class, which represents
a service job card containing booking, service, technician,
and status details.
Author: Trenser
Date:19-May-2026
*/
#pragma once
#include <string>
#include "Timestamp.h"
#include "Enums.h"
class ServiceBooking;
class Service;
class User;
enum class ServiceJobStatus : int;
class JobCard
{
private:
@@ -27,8 +20,9 @@ private:
std::string m_technicianId;
User* m_technician;
util::Timestamp m_assignedDate;
util::ServiceJobStatus m_status;
ServiceJobStatus m_status;
util::Timestamp m_completionDate;
public:
JobCard();
JobCard(const std::string& bookingId,
@@ -38,7 +32,7 @@ public:
const std::string& technicianId,
User* technician,
const util::Timestamp& assignedDate,
util::ServiceJobStatus status,
ServiceJobStatus status,
const util::Timestamp& completionDate
);
const std::string& getId() const;
@@ -49,7 +43,7 @@ public:
const std::string& getTechnicianId() const;
User* getTechnician() const;
const util::Timestamp& getAssignedDate() const;
util::ServiceJobStatus getStatus() const;
ServiceJobStatus getStatus() const;
const util::Timestamp& getCompletionDate() const;
void setId(const std::string& id);
void setBookingId(const std::string& bookingId);
@@ -59,6 +53,6 @@ public:
void setTechnicianId(const std::string& technicianId);
void setTechnician(User* technician);
void setAssignedDate(const util::Timestamp& assignedDate);
void setStatus(util::ServiceJobStatus status);
void setStatus(ServiceJobStatus status);
void setCompletionDate(const util::Timestamp& completionDate);
};
@@ -13,34 +13,31 @@ int ServiceBooking::m_uid = 0;
/*
Function: ServiceBooking
Description: Default constructor that initializes a new service booking
with a unique ID, no customer, and zero discount.
with a unique ID, no customer or technician, and zero discount.
Parameter: None
Return type: Constructor
*/
ServiceBooking::ServiceBooking()
: m_id("SRV" + std::to_string(++m_uid)),
m_customer(nullptr),
m_assignedTechnician(nullptr),
m_discountPercentage(0.0) {}
/*
Function: ServiceBooking
Description: Parameterized constructor that initializes a service booking
with customer, vehicle, technician, and discount details.
Parameter: const std::string& id - booking ID
util::ServiceJobStatus status - current booking status
with customer, vehicle, services, and discount details.
Parameter: util::ServiceJobStatus status - current booking status
const util::Map<std::string, Service*>& services - map of services
const std::string& customerId - ID of the customer
User* customer - pointer to the customer object
const std::string& vehicleNumber - vehicle registration number
const std::string& vehicleBrand - brand of the vehicle
const std::string& vehicleModel - model of the vehicle
const std::string& assignedTechnicianId - ID of the assigned technician
User* assignedTechnician - pointer to the technician object
double discountPercentage - discount applied to the booking
Return type: Constructor
*/
ServiceBooking::ServiceBooking(
const std::string& id,
util::ServiceJobStatus status,
const util::Map<std::string,
Service*>& services,
@@ -49,8 +46,6 @@ ServiceBooking::ServiceBooking(
const std::string& vehicleNumber,
const std::string& vehicleBrand,
const std::string& vehicleModel,
const std::string& assignedTechnicianId,
User* assignedTechnician,
double discountPercentage
)
: m_id("SRV" + std::to_string(++m_uid)),
@@ -61,8 +56,8 @@ ServiceBooking::ServiceBooking(
m_vehicleNumber(vehicleNumber),
m_vehicleBrand(vehicleBrand),
m_vehicleModel(vehicleModel),
m_assignedTechnicianId(assignedTechnicianId),
m_assignedTechnician(assignedTechnician),
m_assignedTechnicianId(""),
m_assignedTechnician(nullptr),
m_discountPercentage(discountPercentage)
{
}
@@ -176,7 +171,6 @@ User* ServiceBooking::getAssignedTechnician() const
{
return m_assignedTechnician;
}
/*
Function: getDiscountPercentage
Description: Retrieves the discount percentage applied to the booking.
@@ -32,7 +32,6 @@ private:
public:
ServiceBooking();
ServiceBooking(
const std::string& id,
util::ServiceJobStatus status,
const util::Map<std::string,
Service*>& services,
@@ -41,8 +40,6 @@ public:
const std::string& vehicleNumber,
const std::string& vehicleBrand,
const std::string& vehicleModel,
const std::string& assignedTechnicianId,
User* assignedTechnician,
double discountPercentage
);
const std::string& getId() const;
@@ -1,16 +1,57 @@
/*
File: AuthenticationManagementService.cpp
Description: Implementation file containing the method definitions of the
AuthenticationManagementService class, including logout and
password change logic.
AuthenticationManagementService class, including login, logout,
password change, and retrieval of the authenticated user.
Author: Trenser
Date:19-May-2026
*/
#include <stdexcept>
#include "AuthenticationManagementService.h"
#include "User.h"
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)
{
util::Map<std::string, User*> users = m_dataStore.getUsers();
int usersMapSize = users.getSize();
for (int index = 0; index < usersMapSize; index++)
{
User* user = users.getValueAt(index);
if (username == user->getUserName())
{
if (password == user->getPassword())
{
m_authenticatedUser = user;
return true;
}
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()
{
return m_authenticatedUser;
}
/*
Function: logout
Description: Logs out the currently authenticated user by clearing the
@@ -1,231 +1,98 @@
/*
File: ServiceManagementService.cpp
Description: Implementation file containing the method definitions of the
ServiceManagementService class, including service booking cancellation,
job card management, combo package creation, and removal logic.
ServiceManagementService class, including service and combo package
purchasing logic, booking creation, and notification handling.
Author: Trenser
Date:19-May-2026
*/
#include <stdexcept>
#include "ServiceManagementService.h"
#include "DataStore.h"
#include "ServiceBooking.h"
#include "JobCard.h"
#include "AuthenticationManagementService.h"
#include "Service.h"
#include "InventoryItem.h"
#include "Factory.h"
#include "ServiceBooking.h"
#include "ComboPackage.h"
#include "Factory.h"
/*
Function: cancelCustomerServiceBookings
Description: Cancels all service bookings associated with a given customer or technician.
Updates booking status, resets customer/technician assignments, sends notifications,
and restocks inventory items.
Parameter: const std::string& userID - ID of the customer or technician
Function: purchaseService
Description: Creates a new service booking for the authenticated user. Validates
service IDs, retrieves services from the DataStore, and generates a
booking. Sends a notification upon successful booking.
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 ServiceManagementService::cancelCustomerServiceBookings(const std::string& userID)
void ServiceManagementService::purchaseService(const util::Vector<std::string>& serviceIDs, const std::string& vehicleNumber, const std::string& vehicleBrand, const std::string& vehicleModel)
{
const int INCREMENT_VALUE = 1;
auto& users = m_dataStore.getUsers();
int userIndex = users.find(userID);
if (userIndex == -1)
AuthenticationManagementService m_authenticationManagementService;
auto authenticatedUser = m_authenticationManagementService.getAuthenticatedUser();
if (authenticatedUser == nullptr)
{
throw std::runtime_error("User not found: " + userID);
}
User* user = users.getValueAt(userIndex);
if (user == nullptr)
{
throw std::runtime_error("User not found: " + userID);
}
util::UserType type = user->getUserType();
auto& bookings = DataStore::getInstance().getServiceBookings();
for (int bookingIterator = 0; bookingIterator < bookings.getSize(); bookingIterator++)
{
ServiceBooking* booking = bookings.getValueAt(bookingIterator);
if (booking != nullptr &&
(booking->getCustomerId() == userID || booking->getAssignedTechnicianId() == userID))
{
if (booking->getStatus() == util::ServiceJobStatus::PENDING ||
booking->getStatus() == util::ServiceJobStatus::STARTED)
{
if (type == util::UserType::CUSTOMER)
{
booking->setStatus(util::ServiceJobStatus::CANCELLED);
booking->setCustomer(nullptr);
booking->setCustomerId("");
User* assignedTechnician = booking->getAssignedTechnician();
sendNotification(assignedTechnician, "Customer Service Cancelled", "Uh?Oh. The customer has cancelled their service booking. Your assigned job card has been cancelled and the inventory has been restocked.");
}
else if (type == util::UserType::TECHNICIAN)
{
booking->setStatus(util::ServiceJobStatus::PENDING);
sendNotification(booking->getCustomer(), "Technician Unavailable", "Your assigned technician is no longer available. Your booking has been reset to pending, and we will reassign a new technician shortly.");
}
booking->setAssignedTechnician(nullptr);
booking->setAssignedTechnicianId("");
const auto& ListOfServices = booking->getServices();
for (int serviceIterator = 0; serviceIterator < ListOfServices.getSize(); serviceIterator++)
{
Service* service = ListOfServices.getValueAt(serviceIterator);
if (service != nullptr)
{
const auto& items = service->getRequiredInventoryItems();
for (int itemIterator = 0; itemIterator < items.getSize(); itemIterator++)
{
InventoryItem* item = items.getValueAt(itemIterator);
if (item != nullptr)
{
item->setQuantity(item->getQuantity() + INCREMENT_VALUE);
}
}
}
}
}
}
}
}
/*
Function: cancelTechnicianJobs
Description: Cancels all jobs assigned to a technician. Updates job status, sends notifications,
and restocks inventory items used in the service.
Parameter: const std::string& technicianID - ID of the technician
Return type: void
*/
void ServiceManagementService::cancelTechnicianJobs(const std::string& technicianID)
{
const int INCREMENT_VALUE = 1;
auto& jobs = m_dataStore.getJobCards();
for (int jobIterator = 0; jobIterator < jobs.getSize(); jobIterator++)
{
JobCard* job = jobs.getValueAt(jobIterator);
if (job != nullptr && job->getTechnicianId() == technicianID)
{
if (job->getStatus() == util::ServiceJobStatus::PENDING || job->getStatus() == util::ServiceJobStatus::STARTED)
{
job->setStatus(util::ServiceJobStatus::CANCELLED);
sendNotification(job->getTechnician(), "Job Cancelled", "The Job has cancelled. Your job card has been cancelled and the inventory has been restocked.");
Service* service = job->getService();
if (service != nullptr)
{
const auto& items = service->getRequiredInventoryItems();
for (int itemIterator = 0; itemIterator < items.getSize(); itemIterator++)
{
InventoryItem* item = items.getValueAt(itemIterator);
if (item != nullptr)
{
item->setQuantity(item->getQuantity() + INCREMENT_VALUE);
}
}
}
}
}
}
}
/*
Function: createComboPackage
Description: Creates a new combo package with two services and a discount percentage.
Validates service IDs, ensures uniqueness, and inserts the new package into the DataStore.
Parameter: const std::string& packageName - name of the combo package
const util::Vector<std::string>& serviceIDsInNewCombo - list of service IDs
double discountPercentage - discount percentage for the package
Return type: void
*/
void ServiceManagementService::createComboPackage(const std::string& packageName, const util::Vector<std::string>& serviceIDsInNewCombo, double discountPercentage)
{
if (packageName.empty())
{
throw std::invalid_argument("The Combo Package Name cannot be empty.\n");
}
if (serviceIDsInNewCombo.getSize() < 2 || serviceIDsInNewCombo.getSize() > 2)
{
throw std::invalid_argument("Combo package must contain only two services.");
}
if (discountPercentage < 0.0 || discountPercentage > 100.0)
{
throw std::invalid_argument("Discount percentage must be between 0 and 100.");
throw std::runtime_error("No user is currently logged in!");
}
auto& servicesMap = m_dataStore.getServices();
for (int index = 0; index < serviceIDsInNewCombo.getSize(); index++)
{
const std::string serviceid = serviceIDsInNewCombo[index];
if (servicesMap.find(serviceid) == -1)
{
throw std::runtime_error("Service ID not found: " + serviceid);
}
}
auto& comboPackageMap = m_dataStore.getComboPackages();
for (int iterator = 0; iterator < comboPackageMap.getSize(); iterator++)
{
ComboPackage* existingCombos = comboPackageMap.getValueAt(iterator);
const util::Map<std::string, Service*>& servicesInsideExistingCombos = existingCombos->getServices();
if (servicesInsideExistingCombos.getSize() == serviceIDsInNewCombo.getSize())
{
bool isIdentical = true;
for (int serviceIterator = 0; serviceIterator < serviceIDsInNewCombo.getSize(); serviceIterator++)
{
const std::string& id = serviceIDsInNewCombo[serviceIterator];
if (servicesInsideExistingCombos.find(id) == -1)
{
isIdentical = false;
break;
}
}
if (isIdentical)
{
throw std::runtime_error("A combo package with the same services already exists.");
}
}
}
auto& serviceBookingMap = m_dataStore.getServiceBookings();
util::Map<std::string, Service*> selectedServices;
for (int iteratorOne = 0; iteratorOne < serviceIDsInNewCombo.getSize(); iteratorOne++)
int selectedServicesCount = serviceIDs.getSize();
for (int index = 0; index < selectedServicesCount; index++)
{
const std::string& serviceId = serviceIDsInNewCombo[iteratorOne];
int serviceIndex = servicesMap.find(serviceId);
int serviceIndex = servicesMap.find(serviceIDs[index]);
if (serviceIndex == -1)
{
throw std::runtime_error("Service ID not found: " + serviceId);
throw std::runtime_error("Service not found!");
}
selectedServices.insert(serviceId, servicesMap.getValueAt(serviceIndex));
Service* service = servicesMap.getValueAt(serviceIndex);
selectedServices[service->getId()] = service;
}
ComboPackage* newComboPackage = Factory::getObject<ComboPackage>(packageName, discountPercentage, selectedServices);
comboPackageMap.insert(newComboPackage->getId(), newComboPackage);
}
/*
Function: getComboPackages
Description: Retrieves all combo packages stored in the DataStore.
Parameter: None
Return type: util::Map<std::string, ComboPackage*>
*/
util::Map<std::string, ComboPackage*> ServiceManagementService::getComboPackages()
ServiceBooking* serviceBooking = Factory::getObject<ServiceBooking>(util::ServiceJobStatus::STARTED, selectedServices, authenticatedUser->getId(), authenticatedUser, vehicleNumber, vehicleBrand, vehicleModel, 0);
if (serviceBooking == nullptr)
{
return m_dataStore.getComboPackages();
throw std::runtime_error("Failed to create service booking");
}
serviceBookingMap[serviceBooking->getId()] = serviceBooking;
sendNotification(authenticatedUser,
"Service Booking succeeded",
"Your service booking has been successfully placed with ID " + serviceBooking->getId());
}
/*
Function: removeComboPackage
Description: Removes a combo package by marking it inactive. Throws an exception if the package ID is not found.
Function: purchaseComboPackage
Description: Creates a new service booking for a combo package. Validates the combo
package ID, retrieves services from the package, and generates a booking
with the applicable discount. Sends a notification upon successful booking.
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 ServiceManagementService::removeComboPackage(const std::string& comboPackageID)
void ServiceManagementService::purchaseComboPackage(const std::string& comboPackageID, const std::string& vehicleNumber, const std::string& vehicleBrand, const std::string& vehicleModel)
{
bool removed = false;
util::Map<std::string, ComboPackage*>& currentComboPackages = m_dataStore.getComboPackages();
for (int iterator = 0; iterator < currentComboPackages.getSize(); iterator++)
AuthenticationManagementService m_authenticationManagementService;
auto authenticatedUser = m_authenticationManagementService.getAuthenticatedUser();
if (authenticatedUser == nullptr)
{
ComboPackage* currentComboPackage = currentComboPackages.getValueAt(iterator);
if (currentComboPackage && currentComboPackage->getId() == comboPackageID)
throw std::runtime_error("No user is currently logged in!");
}
auto& comboPackagesMap = m_dataStore.getComboPackages();
auto& serviceBookingMap = m_dataStore.getServiceBookings();
int comboPackageIndex = comboPackagesMap.find(comboPackageID);
if (comboPackageIndex == -1)
{
currentComboPackage->setState(util::State::INACTIVE);
removed = true;
break;
throw std::runtime_error("Combo Package not found!");
}
}
if (!removed)
const ComboPackage* comboPackage = comboPackagesMap[comboPackageID];
util::Map<std::string, Service*> selectedServices = comboPackage->getServices();
ServiceBooking* serviceBooking = Factory::getObject<ServiceBooking>(util::ServiceJobStatus::STARTED, selectedServices, authenticatedUser->getId(), authenticatedUser, vehicleNumber, vehicleBrand, vehicleModel, comboPackage->getDiscountPercentage());
if (serviceBooking == nullptr)
{
throw std::runtime_error("Combo package with ID '" + comboPackageID + "' not found.");
throw std::runtime_error("Failed to create combo package service booking");
}
serviceBookingMap[serviceBooking->getId()] = serviceBooking;
sendNotification(authenticatedUser,
"Combo Package Service Booking succeeded",
"Your service booking for the combo package has been successfully placed with ID " + serviceBooking->getId());
}
@@ -37,7 +37,7 @@ public:
void completeJob(const std::string& jobID);
void cancelCustomerServiceBookings(const std::string& customerID);
void cancelTechnicianJobs(const std::string& technicianID);
void createComboPackage(const std::string& packageName, const util::Vector<std::string>& serviceIDs, double discountPercentage);
void createComboPackage(const std::string& name, const util::Vector<std::string>& serviceIDs, double discountPercentage);
void removeComboPackage(const std::string& comboPackageID);
void sendNotification(User* user, const std::string& title, const std::string& message) override;
void attach(User* user) override;
@@ -1,55 +1,112 @@
/*
File: UserManagementService.cpp
Description: Implementation file containing the method definitions of the
UserManagementService class, including user retrieval and removal logic.
UserManagementService class, including user creation, updates,
and ensuring an admin account exists.
Author: Trenser
Date:19-May-2026
*/
#include "UserManagementService.h"
#include <stdexcept>
#include "User.h"
#include "Enums.h"
#include "Config.h"
#include "UserManagementService.h"
#include "ServiceManagementService.h"
#include "PaymentManagementService.h"
#include "InventoryManagementService.h"
#include "Factory.h"
/*
Function: getUsers
Description: Retrieves all users stored in the DataStore.
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: 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)
void UserManagementService::ensureAdminExists()
{
int index = m_dataStore.getUsers().find(userID);
auto& usersMap = m_dataStore.getUsers();
int usersMapSize = usersMap.getSize();
bool isAdminFound = false;
for (int index = 0; index < usersMapSize; index++)
{
User* user = usersMap.getValueAt(index);
if (user && user->getUserType() == util::UserType::ADMIN)
{
isAdminFound = true;
break;
}
}
if (!isAdminFound)
{
createUser(
config::admin::DEFAULT_ADMIN_USERNAME,
config::admin::DEFAULT_ADMIN_NAME,
config::admin::DEFAULT_ADMIN_PASSWORD,
config::admin::DEFAULT_ADMIN_EMAIL,
config::admin::DEFAULT_ADMIN_PHONE,
util::UserType::ADMIN);
}
}
/*
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)
{
InventoryManagementService inventoryManagementService;
PaymentManagementService paymentManagementService;
ServiceManagementService serviceManagementService;
auto& usersMap = m_dataStore.getUsers();
int index = usersMap.findIf(
[&](const std::string&, User* user)
{
return user->getUserName() == username;
}
);
if (index != -1)
{
User* user = m_dataStore.getUsers().getValueAt(index);
if (user != nullptr)
throw std::runtime_error("Username already exists");
}
User* newUser = Factory::getObject<User>(username, password, name, phone, email, type);
usersMap.insert(newUser->getId(), newUser);
paymentManagementService.attach(newUser);
serviceManagementService.attach(newUser);
if (newUser->getUserType() == util::UserType::ADMIN)
{
user->setState(util::State::INACTIVE);
inventoryManagementService.attach(newUser);
}
}
/*
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)
{
auto& usersMap = m_dataStore.getUsers();
int index = usersMap.find(userID);
if (index == -1)
{
throw std::runtime_error("User does not exist!");
}
User* user = usersMap.getValueAt(index);
user->setEmail(email);
user->setPhone(phone);
}
@@ -1,7 +1,8 @@
/*
File: UserManagementService.h
Description: Header file declaring the UserManagementService class, which manages
user creation, updates, retrieval, removal, and notification handling.
user creation, updates, retrieval, removal, notifications, and ensures
the existence of an admin account.
Author: Trenser
Date:19-May-2026
*/
@@ -28,4 +29,5 @@ public:
void removeUser(const std::string& userID);
util::Vector<Notification*> getUserNotifications(const std::string& userID);
void deleteNotification(const std::string& notificationID, const std::string& userID);
void ensureAdminExists();
};
@@ -0,0 +1,21 @@
/*
File: Config.h
Description: Header file declaring configuration constants for the Vehicle Service System.
Includes default admin account details such as username, name, password,
email, and phone number.
Author: Trenser
Date:19-May-2026
*/
#pragma once
namespace config
{
namespace admin
{
constexpr const char* DEFAULT_ADMIN_USERNAME = "admin";
constexpr const char* DEFAULT_ADMIN_NAME = "admin";
constexpr const char* DEFAULT_ADMIN_PASSWORD = "";
constexpr const char* DEFAULT_ADMIN_EMAIL = "admin@vss";
constexpr const char* DEFAULT_ADMIN_PHONE = "0000000000";
}
}
@@ -24,10 +24,8 @@ namespace util
enum class ServiceJobStatus
{
PENDING,
STARTED,
COMPLETED,
CANCELLED
COMPLETED
};
enum class State
@@ -123,14 +121,10 @@ namespace util
{
switch (status)
{
case ServiceJobStatus::PENDING:
return "PENDING";
case ServiceJobStatus::STARTED:
return "STARTED";
case ServiceJobStatus::COMPLETED:
return "COMPLETED";
case ServiceJobStatus::CANCELLED:
return "CANCELLED";
}
throw std::invalid_argument("Invalid ServiceJobStatus");
}
@@ -145,14 +139,6 @@ namespace util
{
return ServiceJobStatus::COMPLETED;
}
if (value == "PENDING")
{
return ServiceJobStatus::PENDING;
}
if (value == "CANCELLED")
{
return ServiceJobStatus::CANCELLED;
}
throw std::invalid_argument("Invalid ServiceJobStatus string");
}
@@ -1,7 +1,7 @@
/*
File: Utility.h
Description: Header file declaring utility functions used across the system,
including cost calculation for services based on required inventory items.
including cost calculation for services and combo packages.
Author: Trenser
Date:19-May-2026
*/
@@ -27,3 +27,23 @@ inline double calculatePartsCost(const Service* service)
}
return cost;
}
/*
Function: calculateComboServiceEstimatedCost
Description: Calculates the estimated total cost of a combo package by summing
the labor and parts costs of all services included in the package.
Parameter: const ComboPackage* comboPackage - pointer to the combo package object
Return type: double - estimated total cost of the combo package
*/
inline double calculateComboServiceEstimatedCost(const ComboPackage* comboPackage)
{
double cost = 0;
auto& services = comboPackage->getServices();
int servicesSize = services.getSize();
for (int index = 0; index < servicesSize; index++)
{
const Service* service = services.getValueAt(index);
cost += calculatePartsCost(service) + service->getLaborCost();
}
return cost;
}
@@ -1,57 +1,21 @@
/*
File: AdminMenu.cpp
Description: Implementation file containing the method definitions of the
AdminMenu class, including menu handling, inventory operations,
user management, and combo package management functions.
Author: Trenser
Date:19-May-2026
*/
#include <iostream>
#include <iomanip>
#include "AdminMenu.h"
#include "InputHelper.h"
#include "OutputHelper.h"
#include "User.h"
#include "Validator.h"
#include "Service.h"
#include "Utility.h"
#include "ComboPackage.h"
#include "Enums.h"
/*
Function: showMenu
Description: Displays the admin menu and handles user input until logout is selected.
Parameter: None
Return type: void
*/
void AdminMenu::showMenu()
{
while (true)
bool isMenuActive = true;
while (isMenuActive)
{
try
{
int choice;
util::clear();
std::cout << "Admin Menu"
<< "\n1. View Stock Levels"
<< "\n2. Add Inventory Item"
<< "\n3. Remove Inventory Item"
<< "\n4. Check Stock Availability"
<< "\n5. Assign Job to Technician"
<< "\n6. Add Technician"
<< "\n7. Remove Customer/Technician"
<< "\n8. Create Service"
<< "\n9. Remove Service"
<< "\n10. Create Combo Package"
<< "\n11. Remove Combo Package"
<< "\n12. View Notifications"
<< "\n13. Change Password"
<< "\n14. Logout"
<< "\nEnter a choice: ";
std::cout << "" << std::endl;
util::read(choice);
if (!handleOperation(choice))
{
break;
isMenuActive = false;
}
}
catch (const std::exception& e)
@@ -62,100 +26,18 @@ void AdminMenu::showMenu()
}
}
/*
Function: handleOperation
Description: Executes the corresponding admin operation based on the selected menu choice.
Parameter: int choice - selected menu option
Return type: bool - true if menu continues, false if logout
*/
bool AdminMenu::handleOperation(int choice)
{
switch (choice)
{
case 1:
viewStockLevels();
break;
case 2:
addInventoryItem();
break;
case 3:
removeInventoryItem();
break;
case 4:
checkStockAvailability();
break;
case 5:
assignJob();
break;
case 6:
addTechnician();
break;
case 7:
removeUser();
break;
case 8:
createService();
break;
case 9:
removeService();
break;
case 10:
createComboPackages();
break;
case 11:
removeComboPackage();
break;
case 12:
viewNotifications();
break;
case 13:
changePassword();
break;
case 14:
logout();
return false;
default:
std::cout << "Enter a valid choice!" << std::endl;
util::pressEnter();
}
return true;
}
/*
Function: logout
Description: Logs out the currently authenticated admin user.
Parameter: None
Return type: void
*/
void AdminMenu::logout()
{
m_controller.logout();
}
/*
Function: changePassword
Description: Allows the admin to change their password after validation.
Parameter: None
Return type: void
*/
void AdminMenu::changePassword()
{
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;
}
}
void AdminMenu::viewStockLevels()
@@ -186,329 +68,20 @@ void AdminMenu::removeService()
{
}
/*
Function: addTechnician
Description: Adds a new technician after validating username, password, email, and phone number.
Parameter: None
Return type: void
*/
void AdminMenu::addTechnician()
{
util::clear();
std::string username, name, password, email, phoneNumber;
std::cout << std::left << std::setw(25) << "Enter Technician Username: ";
util::read(username);
std::cout << std::left << std::setw(25) << "Enter Technician Name: ";
util::read(name);
std::cout << std::setw(25) << "Enter Technician Password: ";
util::read(password);
if(!util::isPasswordValid(password))
{
std::cout << "Error: Password is invalid!";
util::pressEnter();
return;
}
std::cout << std::setw(25) << "Enter Technician Email: ";
util::read(email);
if(!util::isEmailValid(email))
{
std::cout << "Error: Email is invalid!";
util::pressEnter();
return;
}
std::cout << std::setw(25) << "Enter Technician Phone: ";
util::read(phoneNumber);
if(!util::isPhoneNumberValid(phoneNumber))
{
std::cout << "Error: Phone Number is invalid!";
util::pressEnter();
return;
}
m_controller.createTechnician(username, name, password, email, phoneNumber);
std::cout << "\nTechnician Added Successfully.\n";
util::pressEnter();
}
/*
Function: 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
Description: Removes a selected active user (customer or technician) from the system.
Parameter: None
Return type: void
*/
void AdminMenu::removeUser()
{
util::clear();
int indexChoice;
auto listOfUsers = m_controller.getUsers();
auto listOfActiveUsers = filterActiveUsers(listOfUsers);
int activeUserCount = listOfActiveUsers.getSize();
if (activeUserCount < 1)
{
std::cout << "No Active users." << std::endl;
util::pressEnter();
return;
}
displayAllActiveUsers(listOfActiveUsers, activeUserCount);
std::cout << "Enter the index of the user to delete : ";
util::read(indexChoice);
if (indexChoice < 1 || indexChoice > activeUserCount)
{
std::cout << "Error Invaild index.\n" << std::endl;
util::pressEnter();
return;
}
const User* userToRemove = listOfActiveUsers.getValueAt(indexChoice - 1);
if (userToRemove != nullptr)
{
std::string userIdToRemove = userToRemove->getId();
m_controller.removeUser(userIdToRemove);
std::cout << userToRemove->getUserName() << " removed Successfully.\n";
}
util::pressEnter();
}
/*
Function: 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 = 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
Description: Creates a new combo package by selecting two active services and applying a discount.
Parameter: None
Return type: void
*/
void AdminMenu::createComboPackages()
{
util::clear();
auto serviceList = m_controller.getServices();
const int numberOfServicesInPackage = 2;
util::Vector<std::string> selectedServiceID;
for (int iterator = 0; iterator < numberOfServicesInPackage; iterator++)
{
const Service* chosenService = selectServiceFromServices(serviceList);
if (chosenService == nullptr)
{
std::cout << "Failed to create combo package!";
util::pressEnter();
return;
}
selectedServiceID.push_back(chosenService->getId());
util::clear();
}
std::string packageName;
double discountPercentage;
std::cout << "Enter combo package name: ";
util::read(packageName);
std::cout << "Enter discount percentage: ";
util::read(discountPercentage);
if (discountPercentage < 0.0 || discountPercentage > 100.0)
{
std::cout << "Error: Discount percentage must be between 0 and 100." << std::endl;
util::pressEnter();
return;
}
m_controller.createComboPackage(packageName, selectedServiceID, discountPercentage);
std::cout << "Combo package '" << packageName << "' created successfully." << std::endl;
util::pressEnter();
}
/*
Function: 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
Description: Removes a selected combo package from the system.
Parameter: None
Return type: void
*/
void AdminMenu::removeComboPackage()
{
util::clear();
util::Map<std::string, const ComboPackage*> currentComboPackages = m_controller.getComboPackages();
std::string selectedComboPackageID = selectComboPackage(currentComboPackages);
if (selectedComboPackageID != "")
{
m_controller.removeComboPackage(selectedComboPackageID);
std::cout << "Combo Package removed successfully.\n";
}
else
{
std::cout << "Combo package removal failed.\n";
}
util::pressEnter();
}
void AdminMenu::viewNotifications()
@@ -1,11 +1,3 @@
/*
File: AdminMenu.h
Description: Header file declaring the AdminMenu class, which provides
administrative operations such as inventory management,
user management, service configuration, and notifications.
Author: Trenser
Date:19-May-2026
*/
#pragma once
#include "Controller.h"
@@ -1,21 +1,54 @@
/*
File: CustomerMenu.cpp
Description: Implementation file containing the method definitions of the
CustomerMenu class, including menu handling, service selection,
combo package booking, profile updates, and password management.
Author: Trenser
Date:19-May-2026
*/
#include <iomanip>
#include "CustomerMenu.h"
#include "Service.h"
#include "InventoryItem.h"
#include "ComboPackage.h"
#include "Service.h"
#include "InputHelper.h"
#include "OutputHelper.h"
#include "Validator.h"
#include "Vector.h"
#include "Utility.h"
#include "Map.h"
/*
Function: showMenu
Description: Displays the customer menu and handles user input until logout is selected.
Parameter: None
Return type: void
*/
void CustomerMenu::showMenu()
{
bool isMenuActive = true;
while (isMenuActive)
while (true)
{
try
{
int choice;
util::clear();
std::cout << "" << std::endl;
std::cout << "Customer Menu"
<< "\n1. Select a service"
<< "\n2. Select a combo package"
<< "\n3. Update Profile"
<< "\n4. Change Password"
<< "\n5. View Service History"
<< "\n6. Complete Payments"
<< "\n7. View Invoices"
<< "\n8. View Notifications"
<< "\n9. Configure Notifications"
<< "\n10. Logout"
<< "\nEnter a choice: ";
util::read(choice);
if (!handleOperation(choice))
{
isMenuActive = false;
break;
}
}
catch (const std::exception& e)
@@ -26,29 +59,277 @@ 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)
{
switch (choice)
{
case 1:
selectService();
break;
case 2:
selectComboPackage();
break;
case 3:
updateDetails();
break;
case 4:
changePassword();
break;
case 5:
viewServiceHistory();
break;
case 6:
completePayments();
break;
case 7:
viewInvoices();
break;
case 8:
viewNotifications();
break;
case 9:
configureNotifications();
break;
case 10:
logout();
return false;
default:
std::cout << "Enter a valid choice!" << std::endl;
util::pressEnter();
}
return true;
}
/*
Function: logout
Description: Logs out the currently authenticated customer user.
Parameter: None
Return type: void
*/
void CustomerMenu::logout()
{
m_controller.logout();
}
/*
Function: changePassword
Description: Allows the customer to change their password after validation.
Parameter: None
Return type: void
*/
void CustomerMenu::changePassword()
{
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()
{
std::string email, phone;
util::clear();
std::cout << "Enter new email: ";
util::read(email);
if (!util::isEmailValid(email))
{
std::cout << "Error: Email is invalid!";
util::pressEnter();
return;
}
std::cout << "Enter new phone: ";
util::read(phone);
if (!util::isPhoneNumberValid(phone))
{
std::cout << "Error: Phone number is invalid!";
util::pressEnter();
return;
}
m_controller.updateUserDetails(email, phone);
std::cout << "Profile details updated successfully";
util::pressEnter();
}
/*
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
*/
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 = 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: selectService
Description: Allows the customer to select a service, provide vehicle details,
and book the service through the controller.
Parameter: None
Return type: void
*/
void CustomerMenu::selectService()
{
std::string vehicleNumber, vehicleBrand, vehicleModel;
auto services = m_controller.getServices();
util::Vector<std::string> selectedServices;
util::clear();
const Service* selectedService = selectServiceFromServices(services);
if (selectedService == nullptr)
{
std::cout << "Failed to book service!";
util::pressEnter();
return;
}
selectedServices.push_back(selectedService->getId());
util::clear();
std::cout << "Enter vehicle number: ";
util::read(vehicleNumber);
std::cout << "Enter vehicle brand: ";
util::read(vehicleBrand);
std::cout << "Enter vehicle model: ";
util::read(vehicleModel);
m_controller.purchaseService(selectedServices, vehicleNumber, vehicleBrand, vehicleModel);
std::cout << "Service has been booked successfully";
util::pressEnter();
}
/*
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
*/
static 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) << 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: selectComboPackage
Description: Allows the customer to select a combo package, provide vehicle details,
and book the package through the controller.
Parameter: None
Return type: void
*/
void CustomerMenu::selectComboPackage()
{
std::string vehicleNumber, vehicleBrand, vehicleModel;
auto comboPackages = m_controller.getComboPackages();
util::clear();
const ComboPackage* selectedComboPackage = selectComboPackageFromPackages(comboPackages);
if (selectedComboPackage == nullptr)
{
std::cout << "Failed to book combo package!";
util::pressEnter();
return;
}
util::clear();
std::cout << "Enter vehicle number: ";
util::read(vehicleNumber);
std::cout << "Enter vehicle brand: ";
util::read(vehicleBrand);
std::cout << "Enter vehicle model: ";
util::read(vehicleModel);
m_controller.purchaseComboPackage(selectedComboPackage->getId(), vehicleNumber, vehicleBrand, vehicleModel);
std::cout << "Combo Package has been booked successfully";
util::pressEnter();
}
void CustomerMenu::viewServiceHistory()
@@ -1,3 +1,12 @@
/*
File: CustomerMenu.h
Description: Header file declaring the CustomerMenu class, which provides
customer operations such as selecting services, booking combo
packages, updating profile details, managing payments, viewing
invoices, and configuring notifications.
Author: Trenser
Date:19-May-2026
*/
#pragma once
#include "Controller.h"
@@ -0,0 +1,62 @@
/*
File: MenuHelper.h
Description: Header file declaring the MenuHelper class, which provides
utility functions for menu-driven operations such as
notification selection and display.
Author: Trenser
Date:19-May-2026
*/
#pragma once
#include <string>
#include <iomanip>
#include "Notification.h"
#include "Map.h"
#include "InputHelper.h"
#include "OutputHelper.h"
/*
Function: selectNotification
Description: Displays a list of notifications with index, ID, title, and timestamp.
Allows the user to select a notification by index. Returns the selected
notification or nullptr if the selection is invalid.
Parameter: const util::Vector<const Notification*>& notifications - list of notifications
Return type: const Notification* - pointer to the selected notification
*/
inline const Notification* selectNotification(const util::Vector<const Notification*>& notifications)
{
if (notifications.getSize() == 0)
{
std::cout << "No notifications available." << std::endl;
return nullptr;
}
std::cout << std::left
<< std::setw(6) << "Index"
<< std::setw(15) << "ID"
<< std::setw(30) << "Title"
<< std::setw(25) << "Timestamp"
<< std::endl;
int currentIndex = 1;
for (int iterator = 0; iterator < notifications.getSize(); iterator++)
{
const Notification* currentNotification = notifications[iterator];
if (currentNotification)
{
std::cout << std::left
<< std::setw(6) << currentIndex
<< std::setw(15) << currentNotification->getId()
<< std::setw(30) << currentNotification->getTitle()
<< std::setw(25) << currentNotification->getCreatedAt().toString()
<< std::endl;
currentIndex++;
}
}
int selectedIndex;
std::cout << "Select notification: ";
util::read(selectedIndex);
if (selectedIndex < 1 || selectedIndex > notifications.getSize())
{
std::cout << "Invalid selection." << std::endl;
return nullptr;
}
return notifications[selectedIndex - 1];
}
@@ -1,40 +1,21 @@
/*
File: TechnicianMenu.cpp
Description: Implementation file containing the method definitions of the
TechnicianMenu class, including menu handling, job completion,
notification viewing, password management, and logout logic.
Author: Trenser
Date:19-May-2026
*/
#include "TechnicianMenu.h"
#include "InputHelper.h"
#include "OutputHelper.h"
#include "Validator.h"
/*
Function: showMenu
Description: Displays the technician menu and handles user input until logout is selected.
Parameter: None
Return type: void
*/
void TechnicianMenu::showMenu()
{
while (true)
bool isMenuActive = true;
while (isMenuActive)
{
try
{
int choice;
util::clear();
std::cout << "Technician Menu"
<< "\n1. Mark Job as Completed"
<< "\n2. View Notifications"
<< "\n3. Change Password"
<< "\n4. Logout"
<< "\nEnter a choice: ";
std::cout << "" << std::endl;
util::read(choice);
if (!handleOperation(choice))
{
break;
isMenuActive = false;
}
}
catch (const std::exception& e)
@@ -45,35 +26,10 @@ void TechnicianMenu::showMenu()
}
}
/*
Function: handleOperation
Description: Executes the corresponding technician operation based on the selected menu choice.
Parameter: int choice - selected menu option
Return type: bool - true if menu continues, false if logout
*/
bool TechnicianMenu::handleOperation(int choice)
{
switch (choice)
{
case 1:
completeJob();
break;
case 2:
viewNotifications();
break;
case 3:
changePassword();
break;
case 4:
logout();
return false;
default:
std::cout << "Enter a valid choice!" << std::endl;
util::pressEnter();
}
return true;
}
void TechnicianMenu::completeJob()
{
@@ -82,41 +38,3 @@ void TechnicianMenu::completeJob()
void TechnicianMenu::viewNotifications()
{
}
/*
Function: logout
Description: Logs out the currently authenticated technician user.
Parameter: None
Return type: void
*/
void TechnicianMenu::logout()
{
m_controller.logout();
}
/*
Function: changePassword
Description: Allows the technician to change their password after validation.
Parameter: None
Return type: void
*/
void TechnicianMenu::changePassword()
{
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;
}
}
@@ -1,11 +1,3 @@
/*
File: TechnicianMenu.h
Description: Header file declaring the TechnicianMenu class, which provides
technician operations such as job completion, notification viewing,
password management, and logout functionality.
Author: Trenser
Date:19-May-2026
*/
#pragma once
#include "Controller.h"
@@ -18,6 +10,4 @@ public:
void showMenu();
void completeJob();
void viewNotifications();
void logout();
void changePassword();
};
@@ -9,7 +9,9 @@ Date:19-May-2026
#include "UserInterface.h"
#include "InputHelper.h"
#include "OutputHelper.h"
#include "Enums.h"
#include "User.h"
#include "Validator.h"
/*
Function: run
@@ -111,7 +113,47 @@ void UserInterface::login()
}
}
/*
Function: registerCustomer
Description: Registers a new customer by collecting and validating details such as
username, name, email, password, and phone number. Delegates creation
to the controller.
Parameter: None
Return type: void
*/
void UserInterface::registerCustomer()
{
std::string username, name, email, phone, password;
util::clear();
std::cout << "Enter username: ";
util::read(username);
std::cout << "Enter name: ";
util::read(name);
std::cout << "Enter email: ";
util::read(email);
if (!util::isEmailValid(email))
{
std::cout << "Error: Email is invalid!";
util::pressEnter();
return;
}
std::cout << "Enter password: ";
util::read(password);
if (!util::isPasswordValid(password))
{
std::cout << "Error: Password is invalid!";
util::pressEnter();
return;
}
std::cout << "Enter phone: ";
util::read(phone);
if (!util::isPhoneNumberValid(phone))
{
std::cout << "Error: Phone number is invalid!";
util::pressEnter();
return;
}
m_controller.createCustomer(username, name, password, email, phone);
std::cout << "Registration is successful";
util::pressEnter();
}