Compare commits

..

10 Commits

Author SHA1 Message Date
Jissin Mathew 0519690043 Add documentation headers across system modules 2026-05-22 13:11:11 +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 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 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
23 changed files with 988 additions and 1448 deletions
@@ -176,7 +176,6 @@
<ClInclude Include="utilities\Map.h" /> <ClInclude Include="utilities\Map.h" />
<ClInclude Include="utilities\OutputHelper.h" /> <ClInclude Include="utilities\OutputHelper.h" />
<ClInclude Include="utilities\Timestamp.h" /> <ClInclude Include="utilities\Timestamp.h" />
<ClInclude Include="utilities\Utility.h" />
<ClInclude Include="utilities\Validator.h" /> <ClInclude Include="utilities\Validator.h" />
<ClInclude Include="utilities\Vector.h" /> <ClInclude Include="utilities\Vector.h" />
<ClInclude Include="views\AdminMenu.h" /> <ClInclude Include="views\AdminMenu.h" />
@@ -233,8 +233,5 @@
<ClInclude Include="models\ComboPackage.h"> <ClInclude Include="models\ComboPackage.h">
<Filter>Header Files\Models</Filter> <Filter>Header Files\Models</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="utilities\Utility.h">
<Filter>Header Files\Utilities</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>
@@ -1,42 +1,20 @@
/*
File: Controller.cpp
Description: Implementation file containing the method definitions of the
Controller class, which manages authentication, users, services,
combo packages, and inventory operations.
Author: Trenser
Date:19-May-2026
*/
#include "Controller.h" #include "Controller.h"
#include "ComboPackage.h" #include "InventoryItem.h"
#include "User.h" #include "Service.h"
#include "ServiceBooking.h"
#include "JobCard.h"
bool Controller::login(const std::string& username, const std::string& password) bool Controller::login(const std::string& username, const std::string& password)
{ {
return false; return false;
} }
/*
Function: logout
Description: Logs out the currently authenticated user by delegating
to the authentication management service.
Parameter: None
Return type: void
*/
void Controller::logout() void Controller::logout()
{ {
m_authenticationManagementService.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
Return type: void
*/
void Controller::changePassword(const std::string& newPassword) 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) void Controller::createCustomer(const std::string& username, const std::string& password, const std::string& email, const std::string& phone)
@@ -48,50 +26,36 @@ const User* Controller::getAuthenticatedUser()
return nullptr; return nullptr;
} }
/* void Controller::createTechnician(const std::string& username, const std::string& password, const std::string& email, const std::string& phone)
Function: createTechnician
Description: Creates a new technician account with provided details by
delegating to the user management service.
Parameter: const std::string& username - technician's username
const std::string& password - technician's password
const std::string& email - technician's email address
const std::string& phoneNumber - technician's phone number
Return type: void
*/
void Controller::createTechnician(const std::string& username, const std::string& name, const std::string& password, const std::string& email, const std::string& phoneNumber)
{ {
m_userManagementService.createUser(username, name, password, email, phoneNumber, util::UserType::TECHNICIAN);
} }
void Controller::updateUserDetails(const std::string& email, const std::string& phone) void Controller::updateUserDetails(const std::string& email, const std::string& phone)
{ {
} }
/*
Function: getServices
Description: Retrieves all available services in read-only form.
Parameters:
- None
Returns:
- util::Map<std::string, const Service*> containing all services
*/
util::Map<std::string, const Service*> Controller::getServices() util::Map<std::string, const Service*> Controller::getServices()
{ {
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;
} }
/*
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, const ComboPackage*> Controller::getComboPackages()
{ {
util::Map<std::string, ComboPackage*> currentAvailableComboPackages = m_serviceManagementService.getComboPackages(); return util::Map<std::string, const ComboPackage*>();
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;
} }
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)
@@ -104,7 +68,8 @@ void Controller::purchaseComboPackage(const std::string& comboPackageID, const s
util::Map<std::string, const InventoryItem*> Controller::getInventoryItems() util::Map<std::string, const InventoryItem*> Controller::getInventoryItems()
{ {
return util::Map<std::string, const InventoryItem*>(); util::Map<std::string, const InventoryItem*> dummyMap;
return dummyMap;
} }
const InventoryItem* Controller::getInventoryItem(const std::string& inventoryItemID) const InventoryItem* Controller::getInventoryItem(const std::string& inventoryItemID)
@@ -120,103 +85,155 @@ void Controller::removeInventoryItem(const std::string& inventoryItemID)
{ {
} }
/*
Function: getServiceBookings
Description: Retrieves all service bookings in read-only form.
Parameters:
- None
Returns:
- util::Map<std::string, const ServiceBooking*> containing service bookings
*/
util::Map<std::string, const ServiceBooking*> Controller::getServiceBookings() util::Map<std::string, const ServiceBooking*> Controller::getServiceBookings()
{ {
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++)
util::Map<std::string, const ServiceBooking*> Controller::getServiceBookingsByUser(const std::string userID) {
{ readOnlyServiceBookings.insert(serviceBookings.getKeyAt(iterator), serviceBookings.getValueAt(iterator));
return util::Map<std::string, const ServiceBooking*>(); }
return readOnlyServiceBookings;
} }
/* /*
Function: getUsers Function: getServiceBookingsByUser
Description: Retrieves all users from the user management service and Description: Retrieves all service bookings for a specific user.
constructs a read-only map. Parameters:
Parameter: None - userID: std::string, the user ID
Return type: util::Map<std::string, const User*> Returns:
- util::Map<std::string, const ServiceBooking*> containing bookings for the user
*/ */
util::Map<std::string, const User*> Controller::getUsers() util::Map<std::string, const ServiceBooking*> Controller::getServiceBookingsByUser(const std::string userID)
{ {
auto listOfUsers = m_userManagementService.getUsers(); util::Map<std::string, const ServiceBooking*> readOnlyServiceBookingsByUserMap;
util::Map<std::string, const User*> readOnlyUserList; util::Map<std::string, ServiceBooking*> currentServiceBookingsByUser = m_serviceManagementService.getServiceBookings(userID);
for (int iterator = 0; iterator < listOfUsers.getSize(); iterator++) for (int iterator = 0; iterator < currentServiceBookingsByUser.getSize(); iterator++)
{ {
readOnlyUserList.insert(listOfUsers.getKeyAt(iterator), listOfUsers.getValueAt(iterator)); readOnlyServiceBookingsByUserMap.insert(currentServiceBookingsByUser.getValueAt(iterator)->getId(), currentServiceBookingsByUser.getValueAt(iterator));
} }
return readOnlyUserList; return readOnlyServiceBookingsByUserMap;
} }
util::Map<std::string, const User*> Controller::getUsers(util::UserType userType) util::Map<std::string, const User*> Controller::getUsers()
{ {
return util::Map<std::string, const User*>(); return util::Map<std::string, const User*>();
} }
/*
Function: getUsers
Description: Retrieves users filtered by user type.
Parameters:
- userType: util::UserType, type of user (CUSTOMER, TECHNICIAN, ADMIN)
Returns:
- util::Map<std::string, const User*> containing users of the specified type
*/
util::Map<std::string, const User*> Controller::getUsers(util::UserType userType)
{
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;
}
/*
Function: createJobCard
Description: Creates a job card for a service booking assigned to a technician.
Parameters:
- bookingID: std::string, ID of the service booking
- technicianID: std::string, ID of the technician
- serviceID: std::string, ID of the service
Returns:
- void
*/
void Controller::createJobCard(const std::string& bookingID, const std::string& technicianID, const std::string& serviceID) void Controller::createJobCard(const std::string& bookingID, const std::string& technicianID, const std::string& serviceID)
{ {
m_serviceManagementService.createJobCard(bookingID, technicianID, serviceID);
} }
/*
Function: createService
Description: Creates a new service with associated inventory items and labor cost.
Parameters:
- name: std::string, name of the service
- inventoryItemIDs: Vector of inventory item IDs
- laborCost: double, labor cost
Returns:
- void
*/
void Controller::createService(const std::string& name, const util::Vector<std::string>& inventoryItemIDs, double laborCost) void Controller::createService(const std::string& name, const util::Vector<std::string>& inventoryItemIDs, double laborCost)
{ {
m_serviceManagementService.createService(name, inventoryItemIDs, laborCost);
} }
/*
Function: removeService
Description: Removes a service from the system by ID.
Parameters:
- serviceID: std::string, ID of the service
Returns:
- void
*/
void Controller::removeService(const std::string& serviceID) void Controller::removeService(const std::string& serviceID)
{ {
m_serviceManagementService.removeService(serviceID);
} }
/*
Function: getJobCardsByUser
Description: Retrieves job cards assigned to the authenticated technician.
Parameters:
- None
Returns:
- util::Map<std::string, const JobCard*> containing job cards
*/
util::Map<std::string, const JobCard*> Controller::getJobCardsByUser() util::Map<std::string, const JobCard*> Controller::getJobCardsByUser()
{ {
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;
} }
/*
Function: completeJob
Description: Marks a job card as completed.
Parameters:
- jobID: std::string, ID of the job card
Returns:
- void
*/
void Controller::completeJob(const std::string& jobID) void Controller::completeJob(const std::string& jobID)
{ {
m_serviceManagementService.completeJob(jobID);
} }
/*
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) 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) 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) void Controller::removeComboPackage(const std::string& comboPackageID)
{ {
m_serviceManagementService.removeComboPackage(comboPackageID);
} }
util::Map<std::string, const Invoice*> Controller::getInvoicesByUser() util::Map<std::string, const Invoice*> Controller::getInvoicesByUser()
@@ -1,18 +1,10 @@
/*
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.
Author: Trenser
Date:19-May-2026
*/
#pragma once #pragma once
#include <string>
#include "Map.h" #include "Map.h"
#include <string>
#include "Enums.h" #include "Enums.h"
#include "UserManagementService.h"
#include "ServiceManagementService.h" #include "ServiceManagementService.h"
#include "AuthenticationManagementService.h" #include "UserManagementService.h"
#include "InventoryManagementService.h"
class Service; class Service;
class ComboPackage; class ComboPackage;
@@ -26,16 +18,15 @@ class Notification;
class Controller class Controller
{ {
private: private:
AuthenticationManagementService m_authenticationManagementService;
UserManagementService m_userManagementService;
ServiceManagementService m_serviceManagementService; ServiceManagementService m_serviceManagementService;
UserManagementService m_userManagementService;
public: public:
bool login(const std::string& username, const std::string& password); bool login(const std::string& username, const std::string& password);
void logout(); void logout();
void changePassword(const std::string& newPassword); 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& 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& 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); 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();
@@ -1,22 +1,7 @@
/*
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" #include "JobCard.h"
int JobCard::m_uid = 0; 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() JobCard::JobCard()
: m_id("JC" + std::to_string(++m_uid)), : m_id("JC" + std::to_string(++m_uid)),
m_booking(nullptr), m_booking(nullptr),
@@ -24,21 +9,6 @@ JobCard::JobCard()
m_technician(nullptr), m_technician(nullptr),
m_status(util::ServiceJobStatus()) {} m_status(util::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, JobCard::JobCard(const std::string& bookingId,
ServiceBooking* booking, ServiceBooking* booking,
Service* service, Service* service,
@@ -60,221 +30,101 @@ JobCard::JobCard(const std::string& bookingId,
m_status(status), m_status(status),
m_completionDate(completionDate) {} 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 const std::string& JobCard::getId() const
{ {
return m_id; 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 const std::string& JobCard::getBookingId() const
{ {
return m_bookingId; return m_bookingId;
} }
/*
Function: getBooking
Description: Retrieves the booking object associated with the job card.
Parameter: None
Return type: ServiceBooking*
*/
ServiceBooking* JobCard::getBooking() const ServiceBooking* JobCard::getBooking() const
{ {
return m_booking; return m_booking;
} }
/*
Function: getService
Description: Retrieves the service object associated with the job card.
Parameter: None
Return type: Service*
*/
Service* JobCard::getService() const Service* JobCard::getService() const
{ {
return m_service; 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 const std::string& JobCard::getServiceId() const
{ {
return m_serviceId; 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 const std::string& JobCard::getTechnicianId() const
{ {
return m_technicianId; return m_technicianId;
} }
/*
Function: getTechnician
Description: Retrieves the technician object assigned to the job card.
Parameter: None
Return type: User*
*/
User* JobCard::getTechnician() const User* JobCard::getTechnician() const
{ {
return m_technician; 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 const util::Timestamp& JobCard::getAssignedDate() const
{ {
return m_assignedDate; 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 util::ServiceJobStatus JobCard::getStatus() const
{ {
return m_status; 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 const util::Timestamp& JobCard::getCompletionDate() const
{ {
return m_completionDate; 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) void JobCard::setId(const std::string& id)
{ {
m_id = 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) void JobCard::setBookingId(const std::string& bookingId)
{ {
m_bookingId = 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) void JobCard::setBooking(ServiceBooking* booking)
{ {
m_booking = 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) void JobCard::setService(Service* service)
{ {
m_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) void JobCard::setServiceId(const std::string& serviceId)
{ {
m_serviceId = 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) void JobCard::setTechnicianId(const std::string& technicianId)
{ {
m_technicianId = 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) void JobCard::setTechnician(User* technician)
{ {
m_technician = 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) void JobCard::setAssignedDate(const util::Timestamp& assignedDate)
{ {
m_assignedDate = 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(util::ServiceJobStatus status)
{ {
m_status = 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) void JobCard::setCompletionDate(const util::Timestamp& completionDate)
{ {
m_completionDate = completionDate; m_completionDate = completionDate;
@@ -1,11 +1,3 @@
/*
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 #pragma once
#include <string> #include <string>
#include "Timestamp.h" #include "Timestamp.h"
@@ -29,6 +21,7 @@ private:
util::Timestamp m_assignedDate; util::Timestamp m_assignedDate;
util::ServiceJobStatus m_status; util::ServiceJobStatus m_status;
util::Timestamp m_completionDate; util::Timestamp m_completionDate;
public: public:
JobCard(); JobCard();
JobCard(const std::string& bookingId, JobCard(const std::string& bookingId,
@@ -1,44 +1,12 @@
/*
File: ServiceBooking.cpp
Description: Implementation file containing the method definitions of the
ServiceBooking class, including constructors, getters, and setters
for booking attributes.
Author: Trenser
Date:19-May-2026
*/
#include "ServiceBooking.h" #include "ServiceBooking.h"
int ServiceBooking::m_uid = 0; 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.
Parameter: None
Return type: Constructor
*/
ServiceBooking::ServiceBooking() ServiceBooking::ServiceBooking()
: m_id("SRV" + std::to_string(++m_uid)), : m_id("SRV" + std::to_string(++m_uid)),
m_customer(nullptr), m_customer(nullptr),
m_discountPercentage(0.0) {} 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
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( ServiceBooking::ServiceBooking(
const std::string& id, const std::string& id,
util::ServiceJobStatus status, util::ServiceJobStatus status,
@@ -50,7 +18,7 @@ ServiceBooking::ServiceBooking(
const std::string& vehicleBrand, const std::string& vehicleBrand,
const std::string& vehicleModel, const std::string& vehicleModel,
const std::string& assignedTechnicianId, const std::string& assignedTechnicianId,
User* assignedTechnician, const User* assignedTechnician,
double discountPercentage double discountPercentage
) )
: m_id("SRV" + std::to_string(++m_uid)), : m_id("SRV" + std::to_string(++m_uid)),
@@ -67,243 +35,111 @@ 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;
} }
/*
Function: getStatus
Description: Retrieves the current status of the service booking.
Parameter: None
Return type: util::ServiceJobStatus
*/
util::ServiceJobStatus ServiceBooking::getStatus() const util::ServiceJobStatus ServiceBooking::getStatus() const
{ {
return m_status; return m_status;
} }
/*
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
{ {
return m_services; return m_services;
} }
/*
Function: getCustomerId
Description: Retrieves the customer ID associated with the booking.
Parameter: None
Return type: const std::string&
*/
const std::string& ServiceBooking::getCustomerId() const const std::string& ServiceBooking::getCustomerId() const
{ {
return m_customerId; return m_customerId;
} }
/*
Function: getCustomer
Description: Retrieves the customer object associated with the booking.
Parameter: None
Return type: User*
*/
User* ServiceBooking::getCustomer() const User* ServiceBooking::getCustomer() const
{ {
return m_customer; return m_customer;
} }
/*
Function: getVehicleNumber
Description: Retrieves the vehicle registration number for the booking.
Parameter: None
Return type: const std::string&
*/
const std::string& ServiceBooking::getVehicleNumber() const const std::string& ServiceBooking::getVehicleNumber() const
{ {
return m_vehicleNumber; return m_vehicleNumber;
} }
/*
Function: getVehicleBrand
Description: Retrieves the brand of the vehicle for the booking.
Parameter: None
Return type: const std::string&
*/
const std::string& ServiceBooking::getVehicleBrand() const const std::string& ServiceBooking::getVehicleBrand() const
{ {
return m_vehicleBrand; return m_vehicleBrand;
} }
/*
Function: getVehicleModel
Description: Retrieves the model of the vehicle for the booking.
Parameter: None
Return type: const std::string&
*/
const std::string& ServiceBooking::getVehicleModel() const const std::string& ServiceBooking::getVehicleModel() const
{ {
return m_vehicleModel; return m_vehicleModel;
} }
/*
Function: getAssignedTechnicianId
Description: Retrieves the ID of the technician assigned to the booking.
Parameter: None
Return type: const std::string&
*/
const std::string& ServiceBooking::getAssignedTechnicianId() const const std::string& ServiceBooking::getAssignedTechnicianId() const
{ {
return m_assignedTechnicianId; return m_assignedTechnicianId;
} }
/* const User* ServiceBooking::getAssignedTechnician() const
Function: getAssignedTechnician
Description: Retrieves the technician object assigned to the booking.
Parameter: None
Return type: User*
*/
User* ServiceBooking::getAssignedTechnician() const
{ {
return m_assignedTechnician; return m_assignedTechnician;
} }
/*
Function: getDiscountPercentage
Description: Retrieves the discount percentage applied to the booking.
Parameter: None
Return type: double
*/
double ServiceBooking::getDiscountPercentage() const double ServiceBooking::getDiscountPercentage() const
{ {
return m_discountPercentage; return m_discountPercentage;
} }
/*
Function: setId
Description: Sets the unique identifier of the service booking.
Parameter: const std::string& id - new booking ID
Return type: void
*/
void ServiceBooking::setId(const std::string& id) void ServiceBooking::setId(const std::string& id)
{ {
m_id = id; m_id = id;
} }
/*
Function: setStatus
Description: Sets the current status of the service booking.
Parameter: const util::ServiceJobStatus& status - new booking status
Return type: void
*/
void ServiceBooking::setStatus(const util::ServiceJobStatus& status) void ServiceBooking::setStatus(const util::ServiceJobStatus& status)
{ {
m_status = status; m_status = status;
} }
/*
Function: setServices
Description: Sets the services associated with the booking.
Parameter: const util::Map<std::string, Service*>& services - new services map
Return type: void
*/
void ServiceBooking::setServices(const util::Map<std::string, Service*>& services) void ServiceBooking::setServices(const util::Map<std::string, Service*>& services)
{ {
m_services = services; m_services = services;
} }
/*
Function: setCustomerId
Description: Sets the customer ID for the booking.
Parameter: const std::string& customerId - new customer ID
Return type: void
*/
void ServiceBooking::setCustomerId(const std::string& customerId) void ServiceBooking::setCustomerId(const std::string& customerId)
{ {
m_customerId = customerId; m_customerId = customerId;
} }
/*
Function: setCustomer
Description: Sets the customer object for the booking.
Parameter: User* customer - pointer to the customer object
Return type: void
*/
void ServiceBooking::setCustomer(User* customer) void ServiceBooking::setCustomer(User* customer)
{ {
m_customer = customer; m_customer = customer;
} }
/*
Function: setVehicleNumber
Description: Sets the vehicle registration number for the booking.
Parameter: const std::string& vehicleNumber - new vehicle number
Return type: void
*/
void ServiceBooking::setVehicleNumber(const std::string& vehicleNumber) void ServiceBooking::setVehicleNumber(const std::string& vehicleNumber)
{ {
m_vehicleNumber = vehicleNumber; m_vehicleNumber = vehicleNumber;
} }
/*
Function: setVehicleBrand
Description: Sets the brand of the vehicle for the booking.
Parameter: const std::string& vehicleBrand - new vehicle brand
Return type: void
*/
void ServiceBooking::setVehicleBrand(const std::string& vehicleBrand) void ServiceBooking::setVehicleBrand(const std::string& vehicleBrand)
{ {
m_vehicleBrand = vehicleBrand; m_vehicleBrand = vehicleBrand;
} }
/*
Function: setVehicleModel
Description: Sets the model of the vehicle for the booking.
Parameter: const std::string& vehicleModel - new vehicle model
Return type: void
*/
void ServiceBooking::setVehicleModel(const std::string& vehicleModel) void ServiceBooking::setVehicleModel(const std::string& vehicleModel)
{ {
m_vehicleModel = vehicleModel; m_vehicleModel = vehicleModel;
} }
/*
Function: setAssignedTechnicianId
Description: Sets the ID of the technician assigned to the booking.
Parameter: const std::string& assignedTechnicianId - new technician ID
Return type: void
*/
void ServiceBooking::setAssignedTechnicianId(const std::string& assignedTechnicianId) void ServiceBooking::setAssignedTechnicianId(const std::string& assignedTechnicianId)
{ {
m_assignedTechnicianId = assignedTechnicianId; m_assignedTechnicianId = assignedTechnicianId;
} }
/* void ServiceBooking::setAssignedTechnician(const User* assignedTechnician)
Function: setAssignedTechnician
Description: Sets the technician object assigned to the booking.
Parameter: User* assignedTechnician - pointer to the technician object
Return type: void
*/
void ServiceBooking::setAssignedTechnician(User* assignedTechnician)
{ {
m_assignedTechnician = assignedTechnician; m_assignedTechnician = assignedTechnician;
} }
/*
Function: setDiscountPercentage
Description: Sets the discount percentage for the booking.
Parameter: double discountPercentage - new discount percentage
Return type: void
*/
void ServiceBooking::setDiscountPercentage(double discountPercentage) void ServiceBooking::setDiscountPercentage(double discountPercentage)
{ {
m_discountPercentage = discountPercentage; m_discountPercentage = discountPercentage;
@@ -1,11 +1,3 @@
/*
File: ServiceBooking.h
Description: Header file declaring the ServiceBooking class, which represents
a booking of services by a customer, including vehicle details,
assigned technician, and discount information.
Author: Trenser
Date:19-May-2026
*/
#pragma once #pragma once
#include <string> #include <string>
#include "Map.h" #include "Map.h"
@@ -27,7 +19,7 @@ private:
std::string m_vehicleBrand; std::string m_vehicleBrand;
std::string m_vehicleModel; std::string m_vehicleModel;
std::string m_assignedTechnicianId; std::string m_assignedTechnicianId;
User* m_assignedTechnician; const User* m_assignedTechnician;
double m_discountPercentage; double m_discountPercentage;
public: public:
ServiceBooking(); ServiceBooking();
@@ -42,7 +34,7 @@ public:
const std::string& vehicleBrand, const std::string& vehicleBrand,
const std::string& vehicleModel, const std::string& vehicleModel,
const std::string& assignedTechnicianId, const std::string& assignedTechnicianId,
User* assignedTechnician, const User* assignedTechnician,
double discountPercentage double discountPercentage
); );
const std::string& getId() const; const std::string& getId() const;
@@ -54,7 +46,7 @@ public:
const std::string& getVehicleBrand() const; const std::string& getVehicleBrand() const;
const std::string& getVehicleModel() const; const std::string& getVehicleModel() const;
const std::string& getAssignedTechnicianId() const; const std::string& getAssignedTechnicianId() const;
User* getAssignedTechnician() const; const User* getAssignedTechnician() const;
double getDiscountPercentage() const; double getDiscountPercentage() const;
void setId(const std::string& id); void setId(const std::string& id);
void setStatus(const util::ServiceJobStatus& status); void setStatus(const util::ServiceJobStatus& status);
@@ -65,6 +57,6 @@ public:
void setVehicleBrand(const std::string& vehicleBrand); void setVehicleBrand(const std::string& vehicleBrand);
void setVehicleModel(const std::string& vehicleModel); void setVehicleModel(const std::string& vehicleModel);
void setAssignedTechnicianId(const std::string& assignedTechnicianId); void setAssignedTechnicianId(const std::string& assignedTechnicianId);
void setAssignedTechnician(User* assignedTechnician); void setAssignedTechnician(const User* assignedTechnician);
void setDiscountPercentage(double discountPercentage); void setDiscountPercentage(double discountPercentage);
}; };
@@ -1,40 +1,3 @@
/*
File: AuthenticationManagementService.cpp
Description: Implementation file containing the method definitions of the
AuthenticationManagementService class, including logout and
password change logic.
Author: Trenser
Date:19-May-2026
*/
#include "AuthenticationManagementService.h" #include "AuthenticationManagementService.h"
#include "User.h"
User* AuthenticationManagementService::m_authenticatedUser = nullptr; User* AuthenticationManagementService::m_authenticatedUser = nullptr;
/*
Function: logout
Description: Logs out the currently authenticated user by clearing the
static authenticated user pointer.
Parameter: None
Return type: void
*/
void AuthenticationManagementService::logout()
{
m_authenticatedUser = nullptr;
}
/*
Function: changePassword
Description: Changes the password of the currently authenticated user.
Throws an exception if no user is logged in.
Parameter: const std::string& newPassword - new password to set
Return type: void
*/
void AuthenticationManagementService::changePassword(const std::string& newPassword)
{
if (m_authenticatedUser == nullptr)
{
throw std::runtime_error("There is no user currently logged in!");
}
m_authenticatedUser->setPassword(newPassword);
}
@@ -1,11 +1,3 @@
/*
File: AuthenticationManagementService.h
Description: Header file declaring the AuthenticationManagementService class, which manages
user authentication, login, logout, password changes, and retrieval of the
authenticated user.
Author: Trenser
Date:19-May-2026
*/
#pragma once #pragma once
#include <string> #include <string>
#include "DataStore.h" #include "DataStore.h"
@@ -1,231 +1,324 @@
/*
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.
Author: Trenser
Date:19-May-2026
*/
#include "ServiceManagementService.h" #include "ServiceManagementService.h"
#include "DataStore.h" #include "UserManagementService.h"
#include "ServiceBooking.h" #include "ServiceBooking.h"
#include "JobCard.h"
#include "Service.h"
#include "InventoryItem.h"
#include "Factory.h" #include "Factory.h"
#include "ComboPackage.h" #include "JobCard.h"
#include "Timestamp.h"
#include "Service.h"
#include "Enums.h"
#include "InventoryItem.h"
#include "AuthenticationManagementService.h"
#include "PaymentManagementService.h"
#include "NotificationManagementService.h"
#include "User.h"
/* /*
Function: cancelCustomerServiceBookings Function: getServiceBookings
Description: Cancels all service bookings associated with a given customer or technician. Description: Retrieves all service bookings from the datastore.
Updates booking status, resets customer/technician assignments, sends notifications, Parameters:
and restocks inventory items. - None
Parameter: const std::string& userID - ID of the customer or technician Returns:
Return type: void - util::Map<std::string, ServiceBooking*> containing all service bookings
*/ */
void ServiceManagementService::cancelCustomerServiceBookings(const std::string& userID) util::Map<std::string, ServiceBooking*> ServiceManagementService::getServiceBookings()
{ {
const int INCREMENT_VALUE = 1; return m_dataStore.getServiceBookings();
auto& users = m_dataStore.getUsers();
int userIndex = users.find(userID);
if (userIndex == -1)
{
throw std::runtime_error("User not found: " + userID);
}
User* user = users.getValueAt(userIndex);
if (user == nullptr)
{
throw std::runtime_error("User not found: " + userID);
}
util::UserType type = user->getUserType();
auto& bookings = DataStore::getInstance().getServiceBookings();
for (int bookingIterator = 0; bookingIterator < bookings.getSize(); bookingIterator++)
{
ServiceBooking* booking = bookings.getValueAt(bookingIterator);
if (booking != nullptr &&
(booking->getCustomerId() == userID || booking->getAssignedTechnicianId() == userID))
{
if (booking->getStatus() == util::ServiceJobStatus::PENDING ||
booking->getStatus() == util::ServiceJobStatus::STARTED)
{
if (type == util::UserType::CUSTOMER)
{
booking->setStatus(util::ServiceJobStatus::CANCELLED);
booking->setCustomer(nullptr);
booking->setCustomerId("");
User* assignedTechnician = booking->getAssignedTechnician();
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 Function: getServiceBooking
Description: Cancels all jobs assigned to a technician. Updates job status, sends notifications, Description: Retrieves a specific service booking by its ID.
and restocks inventory items used in the service. Parameters:
Parameter: const std::string& technicianID - ID of the technician - serviceID: std::string, ID of the service booking
Return type: void Returns:
- ServiceBooking*: Pointer to the service booking, or nullptr if not found
*/ */
void ServiceManagementService::cancelTechnicianJobs(const std::string& technicianID) ServiceBooking* ServiceManagementService::getServiceBooking(const std::string& serviceID)
{ {
const int INCREMENT_VALUE = 1; auto currentServiceBookings = getServiceBookings();
auto& jobs = m_dataStore.getJobCards(); for (int iterator = 0; iterator < currentServiceBookings.getSize(); iterator++)
for (int jobIterator = 0; jobIterator < jobs.getSize(); jobIterator++) {
{ if (currentServiceBookings.getValueAt(iterator)->getId() == serviceID)
JobCard* job = jobs.getValueAt(jobIterator); {
if (job != nullptr && job->getTechnicianId() == technicianID) return currentServiceBookings.getValueAt(iterator);
{ }
if (job->getStatus() == util::ServiceJobStatus::PENDING || job->getStatus() == util::ServiceJobStatus::STARTED) }
{ return nullptr;
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 Function: createJobCard
Description: Creates a new combo package with two services and a discount percentage. Description: Creates a job card for a given service booking, service, and technician.
Validates service IDs, ensures uniqueness, and inserts the new package into the DataStore. Validates booking, service, technician, and inventory availability before creation.
Parameter: const std::string& packageName - name of the combo package Parameters:
const util::Vector<std::string>& serviceIDsInNewCombo - list of service IDs - bookingID: std::string, ID of the service booking
double discountPercentage - discount percentage for the package - technicianID: std::string, ID of the technician
Return type: void - serviceID: std::string, ID of the service
Returns:
- void
Throws:
- std::runtime_error if booking, service, technician, or inventory validation fails
*/ */
void ServiceManagementService::createComboPackage(const std::string& packageName, const util::Vector<std::string>& serviceIDsInNewCombo, double discountPercentage) void ServiceManagementService::createJobCard(const std::string& bookingID, const std::string& technicianID, const std::string& serviceID)
{ {
if (packageName.empty()) UserManagementService m_userManagementService;
{ ServiceBooking* currentBooking = getServiceBooking(bookingID);
throw std::invalid_argument("The Combo Package Name cannot be empty.\n"); auto& currentJobCards = m_dataStore.getJobCards();
} if (currentBooking == nullptr)
if (serviceIDsInNewCombo.getSize() < 2 || serviceIDsInNewCombo.getSize() > 2) {
{ throw std::runtime_error("Service Booking not available");
throw std::invalid_argument("Combo package must contain only two services."); }
} auto& currentServices = currentBooking->getServices();
if (discountPercentage < 0.0 || discountPercentage > 100.0) if (currentServices.find(serviceID) == -1)
{ {
throw std::invalid_argument("Discount percentage must be between 0 and 100."); throw std::runtime_error("Invalid service Id");
} }
auto& servicesMap = m_dataStore.getServices(); Service* currentService = currentServices.getValueAt(currentServices.find(serviceID));
for (int index = 0; index < serviceIDsInNewCombo.getSize(); index++) User* selectedTechnician = m_userManagementService.getUser(technicianID);
{ if (selectedTechnician == nullptr)
const std::string serviceid = serviceIDsInNewCombo[index]; {
if (servicesMap.find(serviceid) == -1) throw std::runtime_error("Technician not available");
{ }
throw std::runtime_error("Service ID not found: " + serviceid); auto& inventoryItems = currentService->getRequiredInventoryItems();
} for (int iterator = 0; iterator < inventoryItems.getSize(); iterator++)
} {
auto& comboPackageMap = m_dataStore.getComboPackages(); InventoryItem* currentInventoryItem = inventoryItems.getValueAt(iterator);
for (int iterator = 0; iterator < comboPackageMap.getSize(); iterator++) if (currentInventoryItem->getQuantity() == 0)
{ {
ComboPackage* existingCombos = comboPackageMap.getValueAt(iterator); std::string errorMessage = "Failed to create job card, " + currentInventoryItem->getPartName() + " is out of stock.";
const util::Map<std::string, Service*>& servicesInsideExistingCombos = existingCombos->getServices(); throw std::runtime_error(errorMessage);
if (servicesInsideExistingCombos.getSize() == serviceIDsInNewCombo.getSize()) }
{ else
bool isIdentical = true; {
for (int serviceIterator = 0; serviceIterator < serviceIDsInNewCombo.getSize(); serviceIterator++) int currentStockQuantity = currentInventoryItem->getQuantity();
{ currentInventoryItem->setQuantity(currentStockQuantity - 1);
const std::string& id = serviceIDsInNewCombo[serviceIterator]; }
if (servicesInsideExistingCombos.find(id) == -1) }
{ currentBooking->setAssignedTechnician(selectedTechnician);
isIdentical = false; currentBooking->setAssignedTechnicianId(selectedTechnician->getId());
break; std::string title = "Job card created";
} std::string message = "Job card created for the service and you are assigned for that.";
} JobCard* jobCard = Factory::getObject<JobCard>(bookingID, currentBooking, currentService, serviceID, technicianID, selectedTechnician, util::Timestamp(), util::ServiceJobStatus::STARTED, util::Timestamp());
if (isIdentical) currentJobCards.insert(jobCard->getId(), jobCard);
{ sendNotification(selectedTechnician,title, message);
throw std::runtime_error("A combo package with the same services already exists.");
}
}
}
util::Map<std::string, Service*> selectedServices;
for (int iteratorOne = 0; iteratorOne < serviceIDsInNewCombo.getSize(); iteratorOne++)
{
const std::string& serviceId = serviceIDsInNewCombo[iteratorOne];
int serviceIndex = servicesMap.find(serviceId);
if (serviceIndex == -1)
{
throw std::runtime_error("Service ID not found: " + serviceId);
}
selectedServices.insert(serviceId, servicesMap.getValueAt(serviceIndex));
}
ComboPackage* newComboPackage = Factory::getObject<ComboPackage>(packageName, discountPercentage, selectedServices);
comboPackageMap.insert(newComboPackage->getId(), newComboPackage);
} }
/* /*
Function: getComboPackages Function: createService
Description: Retrieves all combo packages stored in the DataStore. Description: Creates a new service with associated inventory items and labor cost.
Parameter: None Validates inventory items before creation.
Return type: util::Map<std::string, ComboPackage*> Parameters:
- name: std::string, name of the service
- inventoryItemIDs: util::Vector<std::string>, IDs of required inventory items
- laborCost: double, labor cost for the service
Returns:
- void
Throws:
- std::runtime_error if inventory items are not found or service creation fails
*/ */
util::Map<std::string, ComboPackage*> ServiceManagementService::getComboPackages() void ServiceManagementService::createService(const std::string& name, const util::Vector<std::string>& inventoryItemIDs, double laborCost)
{ {
return m_dataStore.getComboPackages(); util::Map<std::string, InventoryItem*> currentServiceInventoryItems;
auto inventoryItems = m_dataStore.getInventoryItems();
for (int iteratorOne =0; iteratorOne < inventoryItemIDs.getSize(); iteratorOne++)
{
std::string currentItemID = inventoryItemIDs[iteratorOne];
bool itemFound = false;
for (int iteratorTwo = 0; iteratorTwo < inventoryItems.getSize(); iteratorTwo++)
{
InventoryItem* currentInventoryItem = inventoryItems.getValueAt(iteratorTwo);
if (currentInventoryItem && currentInventoryItem->getId() == currentItemID)
{
itemFound = true;
currentServiceInventoryItems.insert(currentInventoryItem->getId(), currentInventoryItem);
break;
}
}
if (!itemFound)
{
throw std::runtime_error("Inventory item with ID '" + currentItemID + "' not found.");
}
}
Service* newService = Factory::getObject<Service>(name, currentServiceInventoryItems, laborCost);
if (newService == nullptr)
{
throw std::runtime_error("Unable to create new service.");
}
util::Map<std::string, Service*>& currentServices = m_dataStore.getServices();
if (currentServices.find(newService->getId()) != -1)
{
throw std::runtime_error("Service with this ID Already exists.");
}
currentServices.insert(newService->getId(), newService);
} }
/* /*
Function: removeComboPackage Function: getServices
Description: Removes a combo package by marking it inactive. Throws an exception if the package ID is not found. Description: Retrieves all services from the datastore.
Parameter: const std::string& comboPackageID - ID of the combo package Parameters:
Return type: void - None
Returns:
- util::Map<std::string, Service*> containing all services
*/ */
void ServiceManagementService::removeComboPackage(const std::string& comboPackageID) util::Map<std::string, Service*> ServiceManagementService::getServices()
{ {
bool removed = false; return m_dataStore.getServices();
util::Map<std::string, ComboPackage*>& currentComboPackages = m_dataStore.getComboPackages(); }
for (int iterator = 0; iterator < currentComboPackages.getSize(); iterator++)
{ /*
ComboPackage* currentComboPackage = currentComboPackages.getValueAt(iterator); Function: removeService
if (currentComboPackage && currentComboPackage->getId() == comboPackageID) Description: Marks a service as inactive by its ID.
{ Parameters:
currentComboPackage->setState(util::State::INACTIVE); - serviceID: std::string, ID of the service
removed = true; Returns:
break; - void
} Throws:
} - std::runtime_error if the service is not found
if (!removed) */
{ void ServiceManagementService::removeService(const std::string& serviceID)
throw std::runtime_error("Combo package with ID '" + comboPackageID + "' not found."); {
} util::Map<std::string, Service*> currentServices = getServices();
if (currentServices.find(serviceID) != -1)
{
currentServices.getValueAt(currentServices.find(serviceID))->setState(util::State::INACTIVE);
}
else
{
throw std::runtime_error("Service not found.");
}
}
/*
Function: getServiceBookings (overloaded)
Description: Retrieves all service bookings for a specific customer.
Parameters:
- customerID: std::string, ID of the customer
Returns:
- util::Map<std::string, ServiceBooking*> containing bookings for the customer
*/
util::Map<std::string, ServiceBooking*> ServiceManagementService::getServiceBookings(const std::string& customerID)
{
util::Map<std::string, ServiceBooking*> currentServiceBookings = getServiceBookings();
util::Map<std::string, ServiceBooking*> currentUserServiceBookings;
if (currentServiceBookings.getSize() != 0)
{
for (int iterator = 0; iterator < currentServiceBookings.getSize(); iterator++)
{
auto currentServiceBooking = currentServiceBookings.getValueAt(iterator);
if (currentServiceBooking->getCustomerId() == customerID)
{
currentUserServiceBookings.insert(currentServiceBooking->getId(), currentServiceBooking);
}
}
}
return currentUserServiceBookings;
}
/*
Function: getJobCards
Description: Retrieves all job cards assigned to a specific technician.
Parameters:
- technicianID: std::string, ID of the technician
Returns:
- util::Map<std::string, JobCard*> containing job cards assigned to the technician
*/
util::Map<std::string, JobCard*> ServiceManagementService::getJobCards(const std::string& technicianID)
{
util::Map<std::string, JobCard*> jobCards = m_dataStore.getJobCards();
util::Map<std::string, JobCard*> technicianJobCards;
for (int iterator = 0; iterator < jobCards.getSize(); iterator++)
{
JobCard* currentJobCard = jobCards.getValueAt(iterator);
if (currentJobCard->getTechnicianId() == technicianID)
{
technicianJobCards.insert(currentJobCard->getId(), currentJobCard);
}
}
return technicianJobCards;
}
/*
Function: hasAllJobCardsinServiceBookingCompleted (static helper)
Description: Checks if all job cards for a given service booking are completed.
Parameters:
- bookingId: std::string, ID of the service booking
- currentAssignedJobs: util::Map<std::string, JobCard*>&, map of assigned job cards
Returns:
- bool: True if all job cards are completed, False otherwise
*/
static bool hasAllJobCardsinServiceBookingCompleted(std::string bookingId, util::Map<std::string, JobCard*>& currentAssignedJobs)
{
for (int iterator = 0; iterator < currentAssignedJobs.getSize(); iterator++)
{
JobCard* currentJob = currentAssignedJobs.getValueAt(iterator);
if (currentJob->getBookingId() == bookingId)
{
if (currentJob->getStatus() == util::ServiceJobStatus::STARTED)
{
return false;
}
}
}
return true;
}
/*
Function: completeJob
Description: Marks a job card as completed for the authenticated technician.
If all job cards in the booking are completed, marks the booking as completed
and generates an invoice.
Parameters:
- jobID: std::string, ID of the job card
Returns:
- void
Throws:
- std::runtime_error if technician is not authenticated, job card not found, or job already completed
*/
void ServiceManagementService::completeJob(const std::string& jobID)
{
AuthenticationManagementService authenticationManagementService;
PaymentManagementService paymentManagementService;
bool jobStatusUpdated = false, serviceBookingCompleted;
JobCard* currentJob;
User* currentTechnician = authenticationManagementService.getAuthenticatedUser();
if (currentTechnician == nullptr)
{
throw std::runtime_error("Unable to fetch current technician.");
}
util::Map<std::string, JobCard*> currentAssignedJobs = getJobCards(currentTechnician->getId());
if (currentAssignedJobs.getSize() == 0)
{
throw std::runtime_error("No job cards assigned to the technician.");
}
if (currentAssignedJobs.find(jobID) != -1)
{
currentJob = currentAssignedJobs.getValueAt(currentAssignedJobs.find(jobID));
if (currentJob == nullptr)
{
throw std::runtime_error("Unable to fetch current job.");
}
if (currentJob->getStatus() == util::ServiceJobStatus::STARTED)
{
currentJob->setStatus(util::ServiceJobStatus::COMPLETED);
jobStatusUpdated = true;
}
}
else
{
throw std::runtime_error("Failed to complete the job, some error occured or job already completed.");
}
if (!jobStatusUpdated)
{
throw std::runtime_error("Failed to complete the job, some error occured or job already completed.");
}
serviceBookingCompleted = hasAllJobCardsinServiceBookingCompleted(currentJob->getBookingId(), currentAssignedJobs);
if (serviceBookingCompleted)
{
currentJob->getBooking()->setStatus(util::ServiceJobStatus::COMPLETED);
paymentManagementService.generateInvoice(currentJob->getBooking());
std::string title = "Service Booking completed,Invoice Generated.\n";
std::string message = "Services completed for the booking and invoice generated.\n";
sendNotification(currentJob->getBooking()->getCustomer(), title, message);
}
} }
@@ -1,11 +1,3 @@
/*
File: ServiceManagementService.h
Description: Header file declaring the ServiceManagementService class, which manages
services, combo packages, job cards, and service bookings. Inherits from
NotificationManagementService to handle notifications.
Author: Trenser
Date:19-May-2026
*/
#pragma once #pragma once
#include <string> #include <string>
#include "Map.h" #include "Map.h"
@@ -30,6 +22,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);
@@ -37,7 +30,7 @@ public:
void completeJob(const std::string& jobID); void completeJob(const std::string& jobID);
void cancelCustomerServiceBookings(const std::string& customerID); void cancelCustomerServiceBookings(const std::string& customerID);
void cancelTechnicianJobs(const std::string& technicianID); void cancelTechnicianJobs(const std::string& technicianID);
void createComboPackage(const std::string& packageName, const util::Vector<std::string>& serviceIDs, double discountPercentage); void createComboPackage(const std::string& name, const util::Vector<std::string>& serviceIDs, double discountPercentage);
void removeComboPackage(const std::string& comboPackageID); void removeComboPackage(const std::string& comboPackageID);
void sendNotification(User* user, const std::string& title, const std::string& message) override; void sendNotification(User* user, const std::string& title, const std::string& message) override;
void attach(User* user) override; void attach(User* user) override;
@@ -1,55 +1,31 @@
/*
File: UserManagementService.cpp
Description: Implementation file containing the method definitions of the
UserManagementService class, including user retrieval and removal logic.
Author: Trenser
Date:19-May-2026
*/
#include "UserManagementService.h" #include "UserManagementService.h"
#include "User.h" #include "User.h"
/* util::Map<std::string, User*> UserManagementService::getUsers(util::UserType type)
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*>& 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) User* UserManagementService::getUser(const std::string& userID)
{ {
int index = m_dataStore.getUsers().find(userID); util::Map<std::string, User*>& currentUsers = m_dataStore.getUsers();
if (index != -1) for (int iterator = 0; iterator < currentUsers.getSize(); iterator++)
{ {
return m_dataStore.getUsers().getValueAt(index); User* currentUser = currentUsers.getValueAt(iterator);
if (currentUser->getId() == userID)
{
return currentUser;
}
} }
return nullptr; 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,10 +1,3 @@
/*
File: UserManagementService.h
Description: Header file declaring the UserManagementService class, which manages
user creation, updates, retrieval, removal, and notification handling.
Author: Trenser
Date:19-May-2026
*/
#pragma once #pragma once
#include <string> #include <string>
#include "Map.h" #include "Map.h"
@@ -20,7 +13,7 @@ private:
DataStore& m_dataStore; DataStore& m_dataStore;
public: public:
UserManagementService() : m_dataStore(DataStore::getInstance()) {} UserManagementService() : m_dataStore(DataStore::getInstance()) {}
void 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 createUser(const std::string& username, const std::string& password, const std::string& email, const std::string& phone, util::UserType type);
void updateUserDetails(const std::string& userID, const std::string& email, const std::string& phone); void updateUserDetails(const std::string& userID, const std::string& email, const std::string& phone);
util::Map<std::string, User*> getUsers(); util::Map<std::string, User*> getUsers();
util::Map<std::string, User*> getUsers(util::UserType type); util::Map<std::string, User*> getUsers(util::UserType type);
@@ -26,8 +26,7 @@ namespace util
{ {
PENDING, PENDING,
STARTED, STARTED,
COMPLETED, COMPLETED
CANCELLED
}; };
enum class State enum class State
@@ -123,14 +122,12 @@ namespace util
{ {
switch (status) switch (status)
{ {
case ServiceJobStatus::PENDING:
return "PENDING";
case ServiceJobStatus::STARTED: case ServiceJobStatus::STARTED:
return "STARTED"; return "STARTED";
case ServiceJobStatus::COMPLETED: case ServiceJobStatus::COMPLETED:
return "COMPLETED"; return "COMPLETED";
case ServiceJobStatus::CANCELLED: case ServiceJobStatus::PENDING:
return "CANCELLED"; return "STARTED";
} }
throw std::invalid_argument("Invalid ServiceJobStatus"); throw std::invalid_argument("Invalid ServiceJobStatus");
} }
@@ -145,14 +142,6 @@ namespace util
{ {
return ServiceJobStatus::COMPLETED; return ServiceJobStatus::COMPLETED;
} }
if (value == "PENDING")
{
return ServiceJobStatus::PENDING;
}
if (value == "CANCELLED")
{
return ServiceJobStatus::CANCELLED;
}
throw std::invalid_argument("Invalid ServiceJobStatus string"); throw std::invalid_argument("Invalid ServiceJobStatus string");
} }
@@ -1,29 +0,0 @@
/*
File: Utility.h
Description: Header file declaring utility functions used across the system,
including cost calculation for services based on required inventory items.
Author: Trenser
Date:19-May-2026
*/
#pragma once
#include "Service.h"
#include "InventoryItem.h"
/*
Function: calculatePartsCost
Description: Calculates the total cost of parts required for a given service
by summing the prices of all associated inventory items.
Parameter: const Service* service - pointer to the service object
Return type: double - total cost of required parts
*/
inline double calculatePartsCost(const Service* service)
{
double cost = 0;
auto& requiredInventoryItems = service->getRequiredInventoryItems();
int requiredInventoryItemsSize = requiredInventoryItems.getSize();
for (int index = 0; index < requiredInventoryItemsSize; index++)
{
cost += requiredInventoryItems.getValueAt(index)->getPrice();
}
return cost;
}
@@ -1,161 +1,49 @@
/*
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 <iomanip>
#include "AdminMenu.h" #include "AdminMenu.h"
#include "Service.h"
#include "InputHelper.h" #include "InputHelper.h"
#include "OutputHelper.h" #include "OutputHelper.h"
#include "User.h" #include "ServiceBooking.h"
#include "Validator.h"
#include "Service.h"
#include "Utility.h"
#include "ComboPackage.h"
#include "Enums.h" #include "Enums.h"
#include "Service.h"
#include "InventoryItem.h"
/*
Function: showMenu
Description: Displays the admin menu and handles user input until logout is selected.
Parameter: None
Return type: void
*/
void AdminMenu::showMenu() void AdminMenu::showMenu()
{ {
while (true) bool isMenuActive = true;
{ while (isMenuActive)
try {
{ try
int choice; {
util::clear(); int choice;
std::cout << "Admin Menu" util::clear();
<< "\n1. View Stock Levels" std::cout << "" << std::endl;
<< "\n2. Add Inventory Item" util::read(choice);
<< "\n3. Remove Inventory Item" if (!handleOperation(choice))
<< "\n4. Check Stock Availability" {
<< "\n5. Assign Job to Technician" isMenuActive = false;
<< "\n6. Add Technician" }
<< "\n7. Remove Customer/Technician" }
<< "\n8. Create Service" catch (const std::exception& e)
<< "\n9. Remove Service" {
<< "\n10. Create Combo Package" std::cout << "Exception: " << e.what() << std::endl;
<< "\n11. Remove Combo Package" util::pressEnter();
<< "\n12. View Notifications" }
<< "\n13. Change Password" }
<< "\n14. Logout"
<< "\nEnter a choice: ";
util::read(choice);
if (!handleOperation(choice))
{
break;
}
}
catch (const std::exception& e)
{
std::cout << "Exception: " << e.what() << std::endl;
util::pressEnter();
}
}
} }
/*
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) bool AdminMenu::handleOperation(int choice)
{ {
switch (choice) return false;
{
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() 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() 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() void AdminMenu::viewStockLevels()
@@ -174,341 +62,384 @@ void AdminMenu::checkStockAvailability()
{ {
} }
void AdminMenu::assignJob()
{
}
void AdminMenu::createService()
{
}
void AdminMenu::removeService()
{
}
/* /*
Function: addTechnician Function: listServiceBookings (static helper)
Description: Adds a new technician after validating username, password, email, and phone number. Description: Lists all pending service bookings and maps them to indices for selection.
Parameter: None Parameters:
Return type: void - currentBookings: util::Map<std::string, const ServiceBooking*>&, current bookings
- bookingsSize: int&, number of bookings
- serviceBookingsMap: util::Map<int, const ServiceBooking*>&, map of indexed bookings
Returns:
- bool: True if pending services exist, False otherwise
*/ */
void AdminMenu::addTechnician() static bool listServiceBookings(util::Map<std::string, const ServiceBooking*>& currentBookings, int& bookingsSize, util::Map<int, const ServiceBooking*>& serviceBookingsMap)
{ {
util::clear(); int currentIndex = 1;
std::string username, name, password, email, phoneNumber; bool hasPendingService = false;
std::cout << std::left << std::setw(25) << "Enter Technician Username: "; std::cout << std::left
util::read(username); << std::setw(10) << "Index"
std::cout << std::left << std::setw(25) << "Enter Technician Name: "; << std::setw(10) << "ID"
util::read(name); << std::setw(12) << "Status"
std::cout << std::setw(25) << "Enter Technician Password: "; << std::setw(12) << "CustID"
util::read(password); << std::setw(20) << "Customer"
if(!util::isPasswordValid(password)) << std::setw(15) << "VehicleNo"
{ << std::setw(15) << "Brand"
std::cout << "Error: Password is invalid!"; << std::setw(15) << "Model"
util::pressEnter(); << std::setw(20) << "Technician"
return; << std::setw(15) << "TechID"
}
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; << std::endl;
for (int iterator = 0; iterator < activeUserCount; iterator++) for (int iterator = 0; iterator < bookingsSize; iterator++)
{ {
const User* user = activeUsers.getValueAt(iterator); const ServiceBooking* currentBooking = currentBookings.getValueAt(iterator);
if (user != nullptr) if (currentBooking && currentBooking->getStatus() == util::ServiceJobStatus::PENDING)
{
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)
{ {
hasPendingService = true;
std::cout << std::left std::cout << std::left
<< std::setw(8) << "Index" << std::setw(10) << currentIndex
<< std::setw(10) << "ID" << std::setw(10) << currentBooking->getId()
<< std::setw(20) << "Package Name" << std::setw(12) << util::getServiceJobStatusString(currentBooking->getStatus())
<< std::setw(15) << "Discount (%)" << std::setw(12) << currentBooking->getCustomerId()
<< "\n"; << 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);
} }
std::cout << std::left }
<< std::setw(8) << currentComboPackageIndexMap.getKeyAt(iterator) if (!hasPendingService)
<< std::setw(10) << currentComboPackage->getId() {
<< std::setw(20) << currentComboPackage->getPackageName() std::cout << "No pending service available." << std::endl;
<< std::setw(15) << currentComboPackage->getDiscountPercentage() return false;
<< "\n"; }
return true;
}
/*
Function: selectPendingServiceBookings (static helper)
Description: Allows selection of a pending service booking by index.
Parameters:
- serviceBookingsMap: util::Map<int, const ServiceBooking*>&, map of indexed bookings
Returns:
- const ServiceBooking*: Pointer to the selected booking, or nullptr if invalid
*/
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;
} }
} }
/* /*
Function: selectComboPackage Function: listAvailableTechnicians (static helper)
Description: Allows the admin to select an active combo package by index. Description: Lists all available technicians and maps them to indices for selection.
Parameter: util::Map<std::string, const ComboPackage*>& currentComboPackages - combo packages list Parameters:
Return type: std::string - ID of the selected combo package - currentAvailableTechnicians: util::Map<std::string, const User*>, available technicians
- numberOfTechnicians: int, number of technicians
- currentAvailableTechniciansMap: util::Map<int, const User*>&, map of indexed technicians
Returns:
- void
*/ */
static std::string selectComboPackage(util::Map<std::string, const ComboPackage*>& currentComboPackages) static void listAvailableTechnicians( util::Map<std::string, const User*> currentAvailableTechnicians, int numberOfTechnicians, util::Map<int, const User*>& currentAvailableTechniciansMap)
{ {
util::Map<int, const ComboPackage*> currentComboPackageIndexMap; bool hasTechnicians = false;
if (currentComboPackages.getSize() == 0) 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++)
{ {
throw std::runtime_error("No combo packages are available.\n"); const User* currentTechnician = currentAvailableTechnicians.getValueAt(iterator);
} if (currentTechnician->getState() == util::State::INACTIVE)
int currentIndex = 1, choice, selectedIndex;
for (int iterator = 0; iterator < currentComboPackages.getSize(); iterator++)
{
if (currentComboPackages.getValueAt(iterator)->getState() == util::State::INACTIVE)
{ {
continue; continue;
} }
currentComboPackageIndexMap.insert(currentIndex++, currentComboPackages.getValueAt(iterator)); 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 (currentComboPackageIndexMap.getSize() == 0) if (!hasTechnicians)
{ {
throw std::runtime_error("No combo packages currently active."); std::cout << "No technicians currently available.";
}
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: selectTechnician (static helper)
Description: Removes a selected combo package from the system. Description: Allows selection of a technician by index.
Parameter: None Parameters:
Return type: void - currentAvailableTechniciansMap: util::Map<int, const User*>&, map of indexed technicians
Returns:
- const User*: Pointer to the selected technician, or nullptr if invalid
*/ */
void AdminMenu::removeComboPackage() static const User* selectTechnician(util::Map<int, const User*>& currentAvailableTechniciansMap)
{ {
util::clear(); int userInputIndex;
util::Map<std::string, const ComboPackage*> currentComboPackages = m_controller.getComboPackages(); util::read(userInputIndex);
std::string selectedComboPackageID = selectComboPackage(currentComboPackages); if (currentAvailableTechniciansMap.find(userInputIndex) != -1)
if (selectedComboPackageID != "")
{ {
m_controller.removeComboPackage(selectedComboPackageID); return currentAvailableTechniciansMap.getValueAt(userInputIndex);
std::cout << "Combo Package removed successfully.\n";
} }
else else
{ {
std::cout << "Combo package removal failed.\n"; std::cout << "Enter a valid index.";
return nullptr;
} }
util::pressEnter(); }
/*
Function: assignJob
Description: Allows the admin to assign pending service bookings to available technicians.
Creates job cards for selected services.
Parameters:
- None
Returns:
- void
*/
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.";
}
}
}
}
/*
Function: selectInventoryItems (static helper)
Description: Allows selection of inventory items by index for creating a service.
Parameters:
- currentInventoryItems: util::Map<std::string, const InventoryItem*>&, available inventory items
- selectedInventoryItems: util::Vector<std::string>&, vector to store selected item IDs
Returns:
- void
*/
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;
}
}
}
/*
Function: createService
Description: Allows the admin to create a new service by selecting inventory items and specifying labor cost.
Parameters:
- None
Returns:
- void
*/
void AdminMenu::createService()
{
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";
}
/*
Function: selectServicesToRemove (static helper)
Description: Allows selection of a service to remove by index.
Parameters:
- currentServices: util::Map<std::string, const Service*>, available services
Returns:
- std::string: ID of the selected service, or empty string if invalid
*/
static std::string selectServicesToRemove(util::Map<std::string, const Service*> currentServices)
{
util::Map<int, const Service*> currentServicesMap;
bool hasServices = false;
int currentIndex = 1, choice;
std::cout << std::left
<< std::setw(6) << "Index"
<< std::setw(12) << "Service ID"
<< std::setw(20) << "Name"
<< std::setw(10) << "Labor Cost"
<< std::endl;
for (int iterator = 0; iterator < currentServices.getSize(); iterator++)
{
const Service* currentService = currentServices.getValueAt(iterator);
if (currentService->getState() == util::State::INACTIVE)
{
continue;
}
std::cout << std::left
<< std::setw(6) << currentIndex
<< std::setw(12) << currentService->getId()
<< std::setw(20) << currentService->getName()
<< std::setw(10) << currentService->getLaborCost()
<< std::endl;
hasServices = true;
currentServicesMap.insert(currentIndex++, currentService);
}
if (!hasServices)
{
std::cout << "No services currently available." << std::endl;
return "";
}
std::cout << "Enter your choice: ";
util::read(choice);
if (currentServicesMap.find(choice) != -1)
{
return currentServicesMap.getValueAt(currentServicesMap.find(choice))->getId();
}
else
{
std::cout << "Invalid choice." << std::endl;
return "";
}
}
/*
Function: removeService
Description: Allows the admin to remove an existing service by selecting from available services.
Parameters:
- None
Returns:
- void
*/
void AdminMenu::removeService()
{
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.";
}
}
void AdminMenu::addTechnician()
{
}
void AdminMenu::removeUser()
{
}
void AdminMenu::createComboPackages()
{
}
void AdminMenu::removeComboPackage()
{
} }
void AdminMenu::viewNotifications() 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 #pragma once
#include "Controller.h" #include "Controller.h"
@@ -1,6 +1,10 @@
#include <iomanip>
#include "CustomerMenu.h" #include "CustomerMenu.h"
#include "InputHelper.h" #include "InputHelper.h"
#include "OutputHelper.h" #include "OutputHelper.h"
#include "User.h"
#include "ServiceBooking.h"
#include "Enums.h"
void CustomerMenu::showMenu() void CustomerMenu::showMenu()
{ {
@@ -51,8 +55,55 @@ void CustomerMenu::selectComboPackage()
{ {
} }
/*
Function: viewServiceHistory
Description: Displays the customers past service bookings in tabular format,
including booking ID, technician, vehicle details, discount percentage, and status.
Parameters:
- None
Returns:
- void
*/
void CustomerMenu::viewServiceHistory() void CustomerMenu::viewServiceHistory()
{ {
util::clear();
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;
}
} }
void CustomerMenu::completePayments() void CustomerMenu::completePayments()
@@ -1,122 +1,122 @@
/* #include <iomanip>
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 "TechnicianMenu.h"
#include "InputHelper.h" #include "InputHelper.h"
#include "OutputHelper.h" #include "OutputHelper.h"
#include "Validator.h" #include "JobCard.h"
#include "Enums.h"
#include "Service.h"
/*
Function: showMenu
Description: Displays the technician menu and handles user input until logout is selected.
Parameter: None
Return type: void
*/
void TechnicianMenu::showMenu() void TechnicianMenu::showMenu()
{ {
while (true) bool isMenuActive = true;
while (isMenuActive)
{
try
{
int choice;
util::clear();
std::cout << "" << std::endl;
util::read(choice);
if (!handleOperation(choice))
{
isMenuActive = false;
}
}
catch (const std::exception& e)
{
std::cout << "Exception: " << e.what() << std::endl;
util::pressEnter();
}
}
}
bool TechnicianMenu::handleOperation(int choice)
{
return false;
}
/*
Function: selectJobCardToComplete (static helper)
Description: Lists all incomplete job cards assigned to the technician and allows selection by index.
Parameters:
- assignedJobCards: util::Map<std::string, const JobCard*>&, job cards assigned to the technician
- incompleteJobCards: util::Map<int, const JobCard*>&, map of incomplete job cards indexed for selection
Returns:
- std::string: ID of the selected job card, or empty string if none selected
*/
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++)
{ {
try const JobCard* currentJobCard = assignedJobCards.getValueAt(iterator);
if (currentJobCard && (currentJobCard->getStatus() == util::ServiceJobStatus::STARTED))
{ {
int choice; std::cout << std::left << std::setw(6) << currentIndex
util::clear(); << std::setw(12) << currentJobCard->getBookingId()
std::cout << "Technician Menu" << std::setw(12) << currentJobCard->getId()
<< "\n1. Mark Job as Completed" << std::setw(20) << currentJobCard->getService()->getName()
<< "\n2. View Notifications" << std::setw(12) << currentJobCard->getServiceId()
<< "\n3. Change Password" << std::endl;
<< "\n4. Logout" hasIncompleteJobCard = true;
<< "\nEnter a choice: "; incompleteJobCards.insert(currentIndex++, currentJobCard);
util::read(choice);
if (!handleOperation(choice))
{
break;
}
}
catch (const std::exception& e)
{
std::cout << "Exception: " << e.what() << std::endl;
util::pressEnter();
} }
} }
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 "";
}
} }
/* /*
Function: handleOperation Function: completeJob
Description: Executes the corresponding technician operation based on the selected menu choice. Description: Allows the technician to mark a selected job card as completed.
Parameter: int choice - selected menu option Validates selection and updates job status through the controller.
Return type: bool - true if menu continues, false if logout Parameters:
- None
Returns:
- void
*/ */
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() 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";
}
} }
void TechnicianMenu::viewNotifications() 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 #pragma once
#include "Controller.h" #include "Controller.h"
@@ -18,6 +10,4 @@ public:
void showMenu(); void showMenu();
void completeJob(); void completeJob();
void viewNotifications(); void viewNotifications();
void logout();
void changePassword();
}; };
@@ -1,23 +1,7 @@
/*
File: UserInterface.cpp
Description: Implementation file containing the method definitions of the
UserInterface class, including system run loop, login handling,
and customer registration logic.
Author: Trenser
Date:19-May-2026
*/
#include "UserInterface.h" #include "UserInterface.h"
#include "InputHelper.h" #include "InputHelper.h"
#include "OutputHelper.h" #include "OutputHelper.h"
#include "User.h"
/*
Function: run
Description: Runs the main system loop, displaying the initial menu for login,
customer registration, or exit. Handles exceptions gracefully.
Parameter: None
Return type: void
*/
void UserInterface::run() void UserInterface::run()
{ {
bool isMenuActive = true; bool isMenuActive = true;
@@ -42,12 +26,6 @@ void UserInterface::run()
} }
} }
/*
Function: handleOperation
Description: Executes the corresponding system operation based on the selected menu choice.
Parameter: int choice - selected menu option
Return type: bool - true if menu continues, false if exit
*/
bool UserInterface::handleOperation(int choice) bool UserInterface::handleOperation(int choice)
{ {
switch (choice) switch (choice)
@@ -68,47 +46,9 @@ bool UserInterface::handleOperation(int choice)
return true; return true;
} }
/*
Function: login
Description: Handles user login by validating credentials. Based on the authenticated
user type, navigates to the appropriate menu (Admin, Technician, Customer).
Parameter: None
Return type: void
*/
void UserInterface::login() void UserInterface::login()
{ {
std::string username, password;
util::clear();
std::cout << "Enter username: ";
util::read(username);
std::cout << "Enter password: ";
util::read(password);
if (m_controller.login(username, password))
{
const User* authenticatedUser = m_controller.getAuthenticatedUser();
if (authenticatedUser != nullptr)
{
switch (authenticatedUser->getUserType())
{
case util::UserType::ADMIN:
m_adminMenu.showMenu();
break;
case util::UserType::TECHNICIAN:
m_technicianMenu.showMenu();
break;
case util::UserType::CUSTOMER:
m_customerMenu.showMenu();
break;
default:
std::cout << "\nError: Unknown user type";
break;
}
}
}
else
{
std::cout << "\nError: Invalid Username or Password";
}
} }
void UserInterface::registerCustomer() void UserInterface::registerCustomer()
@@ -1,12 +1,3 @@
/*
File: UserInterface.h
Description: Header file declaring the UserInterface class, which provides
the main entry point for the Vehicle Service System. Handles
login, customer registration, and menu navigation for different
user roles (Admin, Technician, Customer).
Author: Trenser
Date:19-May-2026
*/
#pragma once #pragma once
#include "Controller.h" #include "Controller.h"
#include "AdminMenu.h" #include "AdminMenu.h"