Compare commits

..

16 Commits

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

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

<Test>

Login functionality validation

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

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

</Test>

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

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

<Test>

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

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

</Test>

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

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

</Changes>

<Test>

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

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

</Test>

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

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

<Test>

 Validate customer service booking flow and service status tracking

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

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

</Test>

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

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

<Test>

 Update Customer Profile Details

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

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

</Test>

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

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

<Test>

Change password functionality validation

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

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

</Test>

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

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

<Test>

Logout functionality validation

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

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

</Test>

<Review>
Sreeja Reghukumar, please review
</Review>
2026-05-19 19:42:43 +05:30
45 changed files with 1127 additions and 2327 deletions
@@ -173,18 +173,16 @@
<ClInclude Include="services\UserManagementService.h" />
<ClInclude Include="utilities\Config.h" />
<ClInclude Include="utilities\Enums.h" />
<ClInclude Include="utilities\FileHelper.h" />
<ClInclude Include="utilities\FileManager.h" />
<ClInclude Include="utilities\InputHelper.h" />
<ClInclude Include="utilities\Map.h" />
<ClInclude Include="utilities\OutputHelper.h" />
<ClInclude Include="utilities\StringHelper.h" />
<ClInclude Include="utilities\Timestamp.h" />
<ClInclude Include="utilities\Utility.h" />
<ClInclude Include="utilities\Validator.h" />
<ClInclude Include="utilities\Vector.h" />
<ClInclude Include="views\AdminMenu.h" />
<ClInclude Include="views\CustomerMenu.h" />
<ClInclude Include="views\MenuHelper.h" />
<ClInclude Include="views\TechnicianMenu.h" />
<ClInclude Include="views\UserInterface.h" />
</ItemGroup>
@@ -233,20 +233,5 @@
<ClInclude Include="models\ComboPackage.h">
<Filter>Header Files\Models</Filter>
</ClInclude>
<ClInclude Include="utilities\Config.h">
<Filter>Header Files\Utilities</Filter>
</ClInclude>
<ClInclude Include="utilities\FileManager.h">
<Filter>Header Files\Utilities</Filter>
</ClInclude>
<ClInclude Include="utilities\StringHelper.h">
<Filter>Header Files\Utilities</Filter>
</ClInclude>
<ClInclude Include="utilities\FileHelper.h">
<Filter>Header Files\Utilities</Filter>
</ClInclude>
<ClInclude Include="utilities\Utility.h">
<Filter>Header Files\Utilities</Filter>
</ClInclude>
</ItemGroup>
</Project>
@@ -1,33 +1,95 @@
/*
File: Controller.cpp
Description: Implementation file containing the method definitions of the
Controller class, including authentication, user creation,
service purchasing, and system checks.
Author: Trenser
Date:19-May-2026
*/
#include <stdexcept>
#include "Controller.h"
#include "Enums.h"
#include "User.h"
/*
Function: login
Description: Authenticates a user by delegating to the authentication management service.
Parameter: const std::string& username - users username
const std::string& password - users password
Return type: bool - true if login successful, false otherwise
*/
bool Controller::login(const std::string& username, const std::string& password)
{
return false;
return m_authenticationManagementService.login(username, password);
}
/*
Function: logout
Description: Logs out the currently authenticated user.
Parameter: None
Return type: void
*/
void Controller::logout()
{
m_authenticationManagementService.logout();
}
/*
Function: changePassword
Description: Changes the password of the currently authenticated user.
Parameter: const std::string& newPassword - new password to set
Return type: void
*/
void Controller::changePassword(const std::string& newPassword)
{
m_authenticationManagementService.changePassword(newPassword);
}
void Controller::createCustomer(const std::string& username, const std::string& password, const std::string& email, const std::string& phone)
/*
Function: createCustomer
Description: Creates a new customer account with the provided details.
Parameter: const std::string& username - customers username
const std::string& name - customers name
const std::string& password - customers password
const std::string& email - customers email
const std::string& phone - customers phone number
Return type: void
*/
void Controller::createCustomer(const std::string& username, const std::string& name, const std::string& password, const std::string& email, const std::string& phone)
{
m_userManagementService.createUser(username, name, password, email, phone, util::UserType::CUSTOMER);
}
/*
Function: getAuthenticatedUser
Description: Retrieves the currently authenticated user.
Parameter: None
Return type: const User* - pointer to the authenticated user
*/
const User* Controller::getAuthenticatedUser()
{
return nullptr;
return m_authenticationManagementService.getAuthenticatedUser();
}
void Controller::createTechnician(const std::string& username, const std::string& password, const std::string& email, const std::string& phone)
{
}
/*
Function: updateUserDetails
Description: Updates the email and phone details of the currently authenticated user.
Parameter: const std::string& email - new email address
const std::string& phone - new phone number
Return type: void
*/
void Controller::updateUserDetails(const std::string& email, const std::string& phone)
{
User* authenticatedUser = m_authenticationManagementService.getAuthenticatedUser();
if (authenticatedUser == nullptr)
{
throw std::runtime_error("No user currently logged in!");
}
m_userManagementService.updateUserDetails(authenticatedUser->getId(), email, phone);
}
util::Map<std::string, const Service*> Controller::getServices()
@@ -40,12 +102,32 @@ util::Map<std::string, const ComboPackage*> Controller::getComboPackages()
return util::Map<std::string, const ComboPackage*>();
}
/*
Function: purchaseService
Description: Purchases one or more services for a vehicle by delegating to the service management service.
Parameter: const util::Vector<std::string>& serviceIDs - IDs of services to purchase
const std::string& vehicleNumber - vehicle registration number
const std::string& vehicleBrand - brand of the vehicle
const std::string& vehicleModel - model of the vehicle
Return type: void
*/
void Controller::purchaseService(const util::Vector<std::string>& serviceIDs, const std::string& vehicleNumber, const std::string& vehicleBrand, const std::string& vehicleModel)
{
m_serviceManagementService.purchaseService(serviceIDs, vehicleNumber, vehicleBrand, vehicleModel);
}
/*
Function: purchaseComboPackage
Description: Purchases a combo package for a vehicle by delegating to the service management service.
Parameter: const std::string& comboPackageID - ID of the combo package
const std::string& vehicleNumber - vehicle registration number
const std::string& vehicleBrand - brand of the vehicle
const std::string& vehicleModel - model of the vehicle
Return type: void
*/
void Controller::purchaseComboPackage(const std::string& comboPackageID, const std::string& vehicleNumber, const std::string& vehicleBrand, const std::string& vehicleModel)
{
m_serviceManagementService.purchaseComboPackage(comboPackageID, vehicleNumber, vehicleBrand, vehicleModel);
}
util::Map<std::string, const InventoryItem*> Controller::getInventoryItems()
@@ -142,54 +224,13 @@ void Controller::configureNotifications(const std::string& userID, bool paymentN
}
/*
Function: loadSystemData
Description: Loads all system data from persistent storage into memory.
Invokes the respective management services to load users, inventory items, services,
combo packages, service bookings, job cards, invoices, and observers.
Parameters:
- None
Returns:
- void
Function: runSystemChecks
Description: Runs system checks to ensure critical configurations, such as verifying admin existence.
Parameter: None
Return type: void
*/
void Controller::loadSystemData()
{
m_userManagementService.loadUsers();
m_inventoryManagementService.loadInventoryItems();
m_serviceManagementService.loadServices();
m_serviceManagementService.loadComboPackages();
m_serviceManagementService.loadServiceBookings();
m_serviceManagementService.loadJobCards();
m_paymentManagementService.loadInvoices();
m_serviceManagementService.loadObservers();
m_paymentManagementService.loadObservers();
m_inventoryManagementService.loadObservers();
}
/*
Function: saveSystemData
Description: Saves all system data from memory back to persistent storage.
Invokes the respective management services to save users, inventory items, services,
combo packages, service bookings, job cards, invoices, and observers.
Parameters:
- None
Returns:
- void
*/
void Controller::saveSystemData()
{
m_userManagementService.saveUsers();
m_inventoryManagementService.saveInventoryItems();
m_serviceManagementService.saveServices();
m_serviceManagementService.saveComboPackages();
m_serviceManagementService.saveServiceBookings();
m_serviceManagementService.saveJobCards();
m_paymentManagementService.saveInvoices();
m_serviceManagementService.saveObservers();
m_paymentManagementService.saveObservers();
m_inventoryManagementService.saveObservers();
}
void Controller::runSystemChecks()
{
m_userManagementService.ensureAdminExists();
}
@@ -1,11 +1,18 @@
/*
File: Controller.h
Description: Header file declaring the Controller class, which coordinates
authentication, user management, service management, inventory,
and notifications across the Vehicle Service System.
Author: Trenser
Date:19-May-2026
*/
#pragma once
#include "Map.h"
#include <string>
#include "Enums.h"
#include "InventoryManagementService.h"
#include "AuthenticationManagementService.h"
#include "UserManagementService.h"
#include "ServiceManagementService.h"
#include "PaymentManagementService.h"
class Service;
class ComboPackage;
@@ -19,15 +26,14 @@ class Notification;
class Controller
{
private:
AuthenticationManagementService m_authenticationManagementService;
UserManagementService m_userManagementService;
InventoryManagementService m_inventoryManagementService;
ServiceManagementService m_serviceManagementService;
PaymentManagementService m_paymentManagementService;
public:
bool login(const std::string& username, const std::string& password);
void logout();
void changePassword(const std::string& newPassword);
void createCustomer(const std::string& username, const std::string& password, const std::string& email, const std::string& phone);
void createCustomer(const std::string& username, const std::string& name, const std::string& password, const std::string& email, const std::string& phone);
const User* getAuthenticatedUser();
void createTechnician(const std::string& username, const std::string& password, const std::string& email, const std::string& phone);
void updateUserDetails(const std::string& email, const std::string& phone);
@@ -56,7 +62,5 @@ public:
util::Vector<const Notification*> getNotifications();
void deleteNotification(const std::string& notificationID);
void configureNotifications(const std::string& userID, bool paymentNotifications, bool serviceNotifications);
void loadSystemData();
void saveSystemData();
void runSystemChecks();
};
@@ -1,7 +1,6 @@
#pragma once
#include <string>
#include "Map.h"
#include "Vector.h"
class User;
class Notification;
@@ -1 +0,0 @@
Place files here.
@@ -1,9 +1,4 @@
#include <sstream>
#include <stdexcept>
#include "ComboPackage.h"
#include "Service.h"
#include "Factory.h"
#include "StringHelper.h"
int ComboPackage::m_uid = 0;
@@ -17,42 +12,7 @@ ComboPackage::ComboPackage(const std::string& packageName, double discountPercen
m_packageName(packageName),
m_discountPercentage(discountPercentage),
m_status(util::State::ACTIVE),
m_services(services)
{
int numberOfServices = m_services.getSize();
auto servicePointers = m_services.getValues();
for (int index = 0; index < numberOfServices; index++)
{
m_serviceIDs.push_back(servicePointers[index]->getId());
}
}
/*
Function: ComboPackage (parameterized constructor with ID)
Description: Initializes a combo package with an existing ID, name, discount percentage,
service IDs, and state. Updates UID tracking based on ID.
Parameters:
- id: const std::string&, unique ID of the package
- packageName: const std::string&, name of the package
- discountPercentage: double, discount percentage applied
- serviceIDs: const util::Vector<std::string>&, IDs of services included
- status: util::State, state of the package (ACTIVE/INACTIVE)
Returns:
- A new ComboPackage object
*/
ComboPackage::ComboPackage(const std::string& id, const std::string& packageName, double discountPercentage, const util::Vector<std::string>& serviceIDs, util::State status)
: m_id(id),
m_packageName(packageName),
m_discountPercentage(discountPercentage),
m_serviceIDs(serviceIDs),
m_status(status)
{
int idNumber = util::extractNumber(m_id);
if (idNumber > m_uid)
{
m_uid = idNumber;
}
}
m_services(services) {}
const std::string& ComboPackage::getId() const
{
@@ -74,11 +34,6 @@ util::State ComboPackage::getState() const
return m_status;
}
const util::Vector<std::string>& ComboPackage::getServiceIDs() const
{
return m_serviceIDs;
}
const util::Map<std::string, Service*>& ComboPackage::getServices() const
{
return m_services;
@@ -102,131 +57,9 @@ void ComboPackage::setDiscountPercentage(double discountPercentage)
void ComboPackage::setServices(const util::Map<std::string, Service*>& services)
{
m_services = services;
m_serviceIDs.clear();
int numberOfServices = m_services.getSize();
auto servicePointers = m_services.getValues();
for (int index = 0; index < numberOfServices; index++)
{
m_serviceIDs.push_back(servicePointers[index]->getId());
}
}
void ComboPackage::setState(util::State status)
{
m_status = status;
}
/*
Function: getServiceIDsAsString (static helper)
Description: Converts a vector of service IDs into a single string separated by '|'.
Parameters:
- serviceIDs: const util::Vector<std::string>&, vector of service IDs
Returns:
- std::string: Concatenated service IDs string
*/
static std::string getServiceIDsAsString(const util::Vector<std::string>& serviceIDs)
{
int numberOfServices = serviceIDs.getSize();
std::string serviceIDsString;
for (int index = 0; index < numberOfServices; index++)
{
serviceIDsString += serviceIDs[index];
if (index < numberOfServices - 1)
{
serviceIDsString += '|';
}
}
return serviceIDsString;
}
/*
Function: getServiceIDsAsVector (static helper)
Description: Converts a string of service IDs separated by '|' into a vector.
Parameters:
- serviceIDsString: const std::string&, concatenated service IDs string
Returns:
- util::Vector<std::string>: Vector of service IDs
*/
static util::Vector<std::string> getServiceIDsAsVector(const std::string& serviceIDsString)
{
util::Vector<std::string> serviceIDs;
std::string serviceID;
std::istringstream serializedServiceIDs(serviceIDsString);
while (getline(serializedServiceIDs, serviceID, '|'))
{
serviceIDs.push_back(serviceID);
}
return serviceIDs;
}
/*
Function: serialize
Description: Serializes the combo package into a CSV-formatted string.
Parameters:
- None
Returns:
- std::string: Serialized combo package record
*/
std::string ComboPackage::serialize() const
{
std::ostringstream serializedComboPackage;
serializedComboPackage << m_id << ','
<< m_packageName << ','
<< m_discountPercentage << ','
<< getServiceIDsAsString(m_serviceIDs) << ','
<< util::getStateString(m_status);
return serializedComboPackage.str();
}
/*
Function: deserialize
Description: Deserializes a CSV-formatted string into a ComboPackage object.
Parameters:
- record: const std::string&, serialized combo package record
Returns:
- ComboPackage*: Pointer to the deserialized ComboPackage object
Throws:
- std::runtime_error if data is invalid
*/
ComboPackage* ComboPackage::deserialize(const std::string& record)
{
std::string id, packageName;
std::string discountPercentageString, serviceIDsString, statusString;
double discountPercentage;
std::istringstream serializedComboPackage(record);
getline(serializedComboPackage, id, ',');
getline(serializedComboPackage, packageName, ',');
getline(serializedComboPackage, discountPercentageString, ',');
getline(serializedComboPackage, serviceIDsString, ',');
getline(serializedComboPackage, statusString, ',');
try
{
discountPercentage = std::stod(discountPercentageString);
}
catch (...)
{
throw std::runtime_error("Invalid combo package data");
}
util::Vector<std::string> serviceIDs = getServiceIDsAsVector(serviceIDsString);
util::State status = util::getState(statusString);
return Factory::getObject<ComboPackage>(
id,
packageName,
discountPercentage,
serviceIDs,
status
);
}
/*
Function: getHeaders
Description: Retrieves the CSV headers for combo package serialization.
Parameters:
- None
Returns:
- std::string: Header string ("ID,PackageName,DiscountPercentage,ServiceIDs,Status")
*/
std::string ComboPackage::getHeaders()
{
return "ID,PackageName,DiscountPercentage,ServiceIDs,Status";
}
@@ -1,7 +1,6 @@
#pragma once
#include <string>
#include "Map.h"
#include "Vector.h"
#include "Enums.h"
class Service;
@@ -13,17 +12,14 @@ private:
std::string m_id;
std::string m_packageName;
double m_discountPercentage;
util::Vector<std::string> m_serviceIDs;
util::Map<std::string, Service*> m_services;
util::State m_status;
public:
ComboPackage();
ComboPackage(const std::string& packageName, double discountPercentage, const util::Map<std::string, Service*>& services);
ComboPackage(const std::string& id, const std::string& packageName, double discountPercentage, const util::Vector<std::string>& serviceIDs, util::State status);
const std::string& getId() const;
const std::string& getPackageName() const;
double getDiscountPercentage() const;
const util::Vector<std::string>& getServiceIDs() const;
const util::Map<std::string, Service*>& getServices() const;
util::State getState() const;
void setId(const std::string& id);
@@ -31,7 +27,4 @@ public:
void setDiscountPercentage(double discountPercentage);
void setServices(const util::Map<std::string, Service*>& services);
void setState(util::State status);
std::string serialize() const;
static ComboPackage* deserialize(const std::string&);
static std::string getHeaders();
};
@@ -1,7 +1,3 @@
#include <sstream>
#include <stdexcept>
#include "Factory.h"
#include "StringHelper.h"
#include "InventoryItem.h"
int InventoryItem::m_uid = 0;
@@ -19,33 +15,6 @@ InventoryItem::InventoryItem(const std::string& partName, int quantity, double p
m_status(util::State::ACTIVE),
m_price(price) {}
/*
Function: InventoryItem (parameterized constructor with ID)
Description: Initializes an inventory item with an existing ID, part name, quantity,
price, and state. Updates UID tracking based on ID.
Parameters:
- id: const std::string&, unique ID of the item
- partName: const std::string&, name of the part
- quantity: int, quantity of the part
- price: double, price of the part
- status: util::State, state of the item (ACTIVE/INACTIVE)
Returns:
- A new InventoryItem object
*/
InventoryItem::InventoryItem(const std::string& id, const std::string& partName, int quantity, double price, util::State status)
: m_id(id),
m_partName(partName),
m_quantity(quantity),
m_status(status),
m_price(price)
{
int idNumber = util::extractNumber(m_id);
if (idNumber > m_uid)
{
m_uid = idNumber;
}
}
const std::string& InventoryItem::getId() const
{
return m_id;
@@ -95,76 +64,3 @@ void InventoryItem::setState(util::State status)
{
m_status = status;
}
/*
Function: serialize
Description: Serializes the inventory item into a CSV-formatted string.
Parameters:
- None
Returns:
- std::string: Serialized inventory item record
*/
std::string InventoryItem::serialize() const
{
std::ostringstream serializedInventoryItem;
serializedInventoryItem << m_id << ','
<< m_partName << ','
<< m_quantity << ','
<< m_price << ','
<< util::getStateString(m_status);
return serializedInventoryItem.str();
}
/*
Function: deserialize
Description: Deserializes a CSV-formatted string into an InventoryItem object.
Parameters:
- record: const std::string&, serialized inventory item record
Returns:
- InventoryItem*: Pointer to the deserialized InventoryItem object
Throws:
- std::runtime_error if data is invalid
*/
InventoryItem* InventoryItem::deserialize(const std::string& record)
{
std::string id, partName;
std::string quantityString, priceString, statusString;
int quantity;
double price;
std::istringstream serializedInventoryItem(record);
getline(serializedInventoryItem, id, ',');
getline(serializedInventoryItem, partName, ',');
getline(serializedInventoryItem, quantityString, ',');
getline(serializedInventoryItem, priceString, ',');
getline(serializedInventoryItem, statusString, ',');
try
{
quantity = std::stoi(quantityString);
price = std::stod(priceString);
}
catch (...)
{
throw std::runtime_error("Invalid inventory item data");
}
util::State status = util::getState(statusString);
return Factory::getObject<InventoryItem>(
id,
partName,
quantity,
price,
status
);
}
/*
Function: getHeaders
Description: Retrieves the CSV headers for inventory item serialization.
Parameters:
- None
Returns:
- std::string: Header string ("ID,PartName,Quantity,Price,Status")
*/
std::string InventoryItem::getHeaders()
{
return "ID,PartName,Quantity,Price,Status";
}
@@ -14,7 +14,6 @@ private:
public:
InventoryItem();
InventoryItem(const std::string& partName, int quantity, double price);
InventoryItem(const std::string& id, const std::string& partName, int quantity, double price, util::State status);
const std::string& getId() const;
const std::string& getPartName() const;
int getQuantity() const;
@@ -25,7 +24,4 @@ public:
void setQuantity(int quantity);
void setPrice(double price);
void setState(util::State status);
std::string serialize() const;
static InventoryItem* deserialize(const std::string&);
static std::string getHeaders();
};
@@ -1,9 +1,4 @@
#include <sstream>
#include <stdexcept>
#include "Invoice.h"
#include "Factory.h"
#include "InventoryItem.h"
#include "StringHelper.h"
int Invoice::m_uid = 0;
@@ -21,7 +16,7 @@ Invoice::Invoice(
const std::string& bookingId,
ServiceBooking* booking,
const util::Timestamp& invoiceDate,
double laborCost, const util::Map<std::string,
double laborCost, const util::Map<int,
InventoryItem*>& parts,
double partsCost,
double discountPercentage,
@@ -41,48 +36,7 @@ Invoice::Invoice(
m_totalAmount(totalAmount),
m_paymentDate(paymentDate),
m_paymentMethod(paymentMethod),
m_status(status)
{
int numberOfParts = m_parts.getSize();
auto partPointers = m_parts.getValues();
for (int index = 0; index < numberOfParts; index++)
{
m_partIDs.push_back(partPointers[index]->getId());
}
}
Invoice::Invoice(
const std::string& id,
const std::string& bookingId,
const util::Timestamp& invoiceDate,
const util::Vector<std::string>& partIDs,
double laborCost,
double partsCost,
double discountPercentage,
double totalAmount,
const util::Timestamp& paymentDate,
util::PaymentMode paymentMethod,
util::PaymentStatus status
)
: m_id(id),
m_bookingId(bookingId),
m_booking(nullptr),
m_invoiceDate(invoiceDate),
m_partIDs(partIDs),
m_laborCost(laborCost),
m_partsCost(partsCost),
m_discountPercentage(discountPercentage),
m_totalAmount(totalAmount),
m_paymentDate(paymentDate),
m_paymentMethod(paymentMethod),
m_status(status)
{
int idNumber = util::extractNumber(m_id);
if (idNumber > m_uid)
{
m_uid = idNumber;
}
}
m_status(status) {}
const std::string& Invoice::getId() const
{
@@ -109,20 +63,7 @@ double Invoice::getLaborCost() const
return m_laborCost;
}
/*
Function: getPartIDs
Description: Retrieves the IDs of parts used in the invoice.
Parameters:
- None
Returns:
- const util::Vector<std::string>&: Part IDs
*/
const util::Vector<std::string>& Invoice::getPartIDs() const
{
return m_partIDs;
}
const util::Map<std::string, InventoryItem*>& Invoice::getParts() const
const util::Map<int, InventoryItem*>& Invoice::getParts() const
{
return m_parts;
}
@@ -182,16 +123,9 @@ void Invoice::setLaborCost(double laborCost)
m_laborCost = laborCost;
}
void Invoice::setParts(const util::Map<std::string, InventoryItem*>& parts)
void Invoice::setParts(const util::Map<int, InventoryItem*>& parts)
{
m_parts = parts;
m_partIDs.clear();
int numberOfParts = m_parts.getSize();
auto partPointers = m_parts.getValues();
for (int index = 0; index < numberOfParts; index++)
{
m_partIDs.push_back(partPointers[index]->getId());
}
}
void Invoice::setPartsCost(double partsCost)
@@ -223,146 +157,3 @@ void Invoice::setStatus(util::PaymentStatus status)
{
m_status = status;
}
/*
Function: getPartIDsAsString (static helper)
Description: Converts a vector of part IDs into a single string separated by '|'.
Parameters:
- partIDs: const util::Vector<std::string>&, vector of part IDs
Returns:
- std::string: Concatenated part IDs string
*/
static std::string getPartIDsAsString(const util::Vector<std::string>& partIDs)
{
int numberOfParts = partIDs.getSize();
std::string partIDsString;
for (int index = 0; index < numberOfParts; index++)
{
partIDsString += partIDs[index];
if (index < numberOfParts - 1)
{
partIDsString += '|';
}
}
return partIDsString;
}
/*
Function: getPartIDsAsVector (static helper)
Description: Converts a string of part IDs separated by '|' into a vector.
Parameters:
- partIDsString: const std::string&, concatenated part IDs string
Returns:
- util::Vector<std::string>: Vector of part IDs
*/
static util::Vector<std::string> getPartIDsAsVector(const std::string& partIDsString)
{
util::Vector<std::string> partIDs;
std::string partID;
std::istringstream serializedPartIDs(partIDsString);
while (getline(serializedPartIDs, partID, '|'))
{
partIDs.push_back(partID);
}
return partIDs;
}
/*
Function: serialize
Description: Serializes the invoice into a CSV-formatted string.
Parameters:
- None
Returns:
- std::string: Serialized invoice record
*/
std::string Invoice::serialize() const
{
std::ostringstream serializedInvoice;
serializedInvoice << m_id << ','
<< m_bookingId << ','
<< m_invoiceDate.toString() << ','
<< m_laborCost << ','
<< getPartIDsAsString(m_partIDs) << ','
<< m_partsCost << ','
<< m_discountPercentage << ','
<< m_totalAmount << ','
<< m_paymentDate.toString() << ','
<< util::getPaymentModeString(m_paymentMethod) << ','
<< util::getPaymentStatusString(m_status);
return serializedInvoice.str();
}
/*
Function: deserialize
Description: Deserializes a CSV-formatted string into an Invoice object.
Parameters:
- record: const std::string&, serialized invoice record
Returns:
- Invoice*: Pointer to the deserialized Invoice object
Throws:
- std::runtime_error if data is invalid
*/
Invoice* Invoice::deserialize(const std::string& record)
{
std::string id, bookingId;
std::string invoiceDateString, laborCostString, partIDsString;
std::string partsCostString, discountPercentageString, totalAmountString;
std::string paymentDateString, paymentMethodString, statusString;
double laborCost, partsCost, discountPercentage, totalAmount;
std::istringstream serializedInvoice(record);
getline(serializedInvoice, id, ',');
getline(serializedInvoice, bookingId, ',');
getline(serializedInvoice, invoiceDateString, ',');
getline(serializedInvoice, laborCostString, ',');
getline(serializedInvoice, partIDsString, ',');
getline(serializedInvoice, partsCostString, ',');
getline(serializedInvoice, discountPercentageString, ',');
getline(serializedInvoice, totalAmountString, ',');
getline(serializedInvoice, paymentDateString, ',');
getline(serializedInvoice, paymentMethodString, ',');
getline(serializedInvoice, statusString, ',');
util::Timestamp invoiceDate;
util::Timestamp paymentDate;
try
{
invoiceDate = util::Timestamp::fromString(invoiceDateString);
paymentDate = util::Timestamp::fromString(paymentDateString);
laborCost = std::stod(laborCostString);
partsCost = std::stod(partsCostString);
discountPercentage = std::stod(discountPercentageString);
totalAmount = std::stod(totalAmountString);
}
catch (...)
{
throw std::runtime_error("Invalid invoice data");
}
util::Vector<std::string> partIDs = getPartIDsAsVector(partIDsString);
util::PaymentMode paymentMethod = util::getPaymentMode(paymentMethodString);
util::PaymentStatus status = util::getPaymentStatus(statusString);
return Factory::getObject<Invoice>(
id,
bookingId,
invoiceDate,
partIDs,
laborCost,
partsCost,
discountPercentage,
totalAmount,
paymentDate,
paymentMethod,
status
);
}
/*
Function: getHeaders
Description: Retrieves the CSV headers for invoice serialization.
Parameters:
- None
Returns:
- std::string: Header string ("ID,BookingID,InvoiceDate,LaborCost,PartIDs,PartsCost,DiscountPercentage,TotalAmount,PaymentDate,PaymentMethod,Status")
*/
std::string Invoice::getHeaders()
{
return "ID,BookingID,InvoiceDate,LaborCost,PartIDs,PartsCost,DiscountPercentage,TotalAmount,PaymentDate,PaymentMethod,Status";
}
@@ -1,7 +1,6 @@
#pragma once
#include <string>
#include "Map.h"
#include "Vector.h"
#include "Timestamp.h"
#include "Enums.h"
@@ -17,21 +16,21 @@ private:
ServiceBooking* m_booking;
util::Timestamp m_invoiceDate;
double m_laborCost;
util::Vector<std::string> m_partIDs;
util::Map<std::string, InventoryItem*> m_parts;
util::Map<int, InventoryItem*> m_parts;
double m_partsCost;
double m_discountPercentage;
double m_totalAmount;
util::Timestamp m_paymentDate;
util::PaymentMode m_paymentMethod;
util::PaymentStatus m_status;
public:
Invoice();
Invoice(
const std::string& bookingId,
ServiceBooking* booking,
const util::Timestamp& invoiceDate,
double laborCost, const util::Map<std::string,
double laborCost, const util::Map<int,
InventoryItem*>& parts,
double partsCost,
double discountPercentage,
@@ -40,26 +39,12 @@ public:
util::PaymentMode paymentMethod,
util::PaymentStatus status
);
Invoice(
const std::string& id,
const std::string& bookingId,
const util::Timestamp& invoiceDate,
const util::Vector<std::string>& partIDs,
double laborCost,
double partsCost,
double discountPercentage,
double totalAmount,
const util::Timestamp& paymentDate,
util::PaymentMode paymentMethod,
util::PaymentStatus status
);
const std::string& getId() const;
const std::string& getBookingId() const;
ServiceBooking* getBooking() const;
const util::Timestamp& getInvoiceDate() const;
double getLaborCost() const;
const util::Vector<std::string>& getPartIDs() const;
const util::Map<std::string, InventoryItem*>& getParts() const;
const util::Map<int, InventoryItem*>& getParts() const;
double getPartsCost() const;
double getDiscountPercentage() const;
double getTotalAmount() const;
@@ -71,14 +56,11 @@ public:
void setBooking(ServiceBooking* booking);
void setInvoiceDate(const util::Timestamp& invoiceDate);
void setLaborCost(double laborCost);
void setParts(const util::Map<std::string, InventoryItem*>& parts);
void setParts(const util::Map<int, InventoryItem*>& parts);
void setPartsCost(double partsCost);
void setDiscountPercentage(double discountPercentage);
void setTotalAmount(double totalAmount);
void setPaymentDate(const util::Timestamp& paymentDate);
void setPaymentMethod(util::PaymentMode paymentMethod);
void setStatus(util::PaymentStatus status);
std::string serialize() const;
static Invoice* deserialize(const std::string&);
static std::string getHeaders();
};
@@ -1,9 +1,4 @@
#include <sstream>
#include <stdexcept>
#include "JobCard.h"
#include "Factory.h"
#include "StringHelper.h"
#include "Enums.h"
int JobCard::m_uid = 0;
@@ -12,7 +7,7 @@ JobCard::JobCard()
m_booking(nullptr),
m_service(nullptr),
m_technician(nullptr),
m_status(util::ServiceJobStatus()) {}
m_status(ServiceJobStatus()) {}
JobCard::JobCard(const std::string& bookingId,
ServiceBooking* booking,
@@ -21,7 +16,7 @@ JobCard::JobCard(const std::string& bookingId,
const std::string& technicianId,
User* technician,
const util::Timestamp& assignedDate,
util::ServiceJobStatus status,
ServiceJobStatus status,
const util::Timestamp& completionDate
)
: m_id("JC" + std::to_string(++m_uid)),
@@ -35,48 +30,6 @@ JobCard::JobCard(const std::string& bookingId,
m_status(status),
m_completionDate(completionDate) {}
/*
Function: JobCard (parameterized constructor with ID)
Description: Initializes a job card with an existing ID, booking ID, service ID,
technician ID, assignment date, completion date, and status.
Updates UID tracking based on ID.
Parameters:
- id: const std::string&, unique job card ID
- bookingId: const std::string&, ID of the booking
- serviceId: const std::string&, ID of the service
- technicianId: const std::string&, ID of the technician
- assignedDate: const util::Timestamp&, date of assignment
- status: util::ServiceJobStatus, job status
- completionDate: const util::Timestamp&, date of completion
Returns:
- A new JobCard object
*/
JobCard::JobCard(const std::string& id,
const std::string& bookingId,
const std::string& serviceId,
const std::string& technicianId,
const util::Timestamp& assignedDate,
util::ServiceJobStatus status,
const util::Timestamp& completionDate
)
: m_id(id),
m_bookingId(bookingId),
m_booking(nullptr),
m_service(nullptr),
m_serviceId(serviceId),
m_technicianId(technicianId),
m_technician(nullptr),
m_assignedDate(assignedDate),
m_status(status),
m_completionDate(completionDate)
{
int idNumber = util::extractNumber(m_id);
if (idNumber > m_uid)
{
m_uid = idNumber;
}
}
const std::string& JobCard::getId() const
{
return m_id;
@@ -117,7 +70,7 @@ const util::Timestamp& JobCard::getAssignedDate() const
return m_assignedDate;
}
util::ServiceJobStatus JobCard::getStatus() const
ServiceJobStatus JobCard::getStatus() const
{
return m_status;
}
@@ -167,7 +120,7 @@ void JobCard::setAssignedDate(const util::Timestamp& assignedDate)
m_assignedDate = assignedDate;
}
void JobCard::setStatus(util::ServiceJobStatus status)
void JobCard::setStatus(ServiceJobStatus status)
{
m_status = status;
}
@@ -176,82 +129,3 @@ void JobCard::setCompletionDate(const util::Timestamp& completionDate)
{
m_completionDate = completionDate;
}
/*
Function: serialize
Description: Serializes the job card into a CSV-formatted string.
Parameters:
- None
Returns:
- std::string: Serialized job card record
*/
std::string JobCard::serialize() const
{
std::ostringstream serializedJobCard;
serializedJobCard << m_id << ','
<< m_bookingId << ','
<< m_serviceId << ','
<< m_technicianId << ','
<< m_assignedDate.toString() << ','
<< util::getServiceJobStatusString(m_status) << ','
<< m_completionDate.toString();
return serializedJobCard.str();
}
/*
Function: deserialize
Description: Deserializes a CSV-formatted string into a JobCard object.
Parameters:
- record: const std::string&, serialized job card record
Returns:
- JobCard*: Pointer to the deserialized JobCard object
Throws:
- std::runtime_error if timestamp parsing fails
*/
JobCard* JobCard::deserialize(const std::string& record)
{
std::string id, bookingId, serviceId, technicianId;
std::string assignedDateString, statusString, completionDateString;
std::istringstream serializedJobCard(record);
getline(serializedJobCard, id, ',');
getline(serializedJobCard, bookingId, ',');
getline(serializedJobCard, serviceId, ',');
getline(serializedJobCard, technicianId, ',');
getline(serializedJobCard, assignedDateString, ',');
getline(serializedJobCard, statusString, ',');
getline(serializedJobCard, completionDateString, ',');
util::Timestamp assignedDate;
util::Timestamp completionDate;
try
{
assignedDate = util::Timestamp::fromString(assignedDateString);
completionDate = util::Timestamp::fromString(completionDateString);
}
catch (...)
{
throw std::runtime_error("Invalid timestamp");
}
util::ServiceJobStatus status = util::getServiceJobStatus(statusString);
return Factory::getObject<JobCard>(
id,
bookingId,
serviceId,
technicianId,
assignedDate,
status,
completionDate
);
}
/*
Function: getHeaders
Description: Retrieves the CSV headers for job card serialization.
Parameters:
- None
Returns:
- std::string: Header string ("ID,BookingID,ServiceID,TechnicianID,AssignedDate,Status,CompletionDate")
*/
std::string JobCard::getHeaders()
{
return "ID,BookingID,ServiceID,TechnicianID,AssignedDate,Status,CompletionDate";
}
@@ -1,12 +1,13 @@
#pragma once
#include <string>
#include "Timestamp.h"
#include "Enums.h"
class ServiceBooking;
class Service;
class User;
enum class ServiceJobStatus : int;
class JobCard
{
private:
@@ -19,7 +20,7 @@ private:
std::string m_technicianId;
User* m_technician;
util::Timestamp m_assignedDate;
util::ServiceJobStatus m_status;
ServiceJobStatus m_status;
util::Timestamp m_completionDate;
public:
@@ -31,15 +32,7 @@ public:
const std::string& technicianId,
User* technician,
const util::Timestamp& assignedDate,
util::ServiceJobStatus status,
const util::Timestamp& completionDate
);
JobCard(const std::string& id,
const std::string& bookingId,
const std::string& serviceId,
const std::string& technicianId,
const util::Timestamp& assignedDate,
util::ServiceJobStatus status,
ServiceJobStatus status,
const util::Timestamp& completionDate
);
const std::string& getId() const;
@@ -50,7 +43,7 @@ public:
const std::string& getTechnicianId() const;
User* getTechnician() const;
const util::Timestamp& getAssignedDate() const;
util::ServiceJobStatus getStatus() const;
ServiceJobStatus getStatus() const;
const util::Timestamp& getCompletionDate() const;
void setId(const std::string& id);
void setBookingId(const std::string& bookingId);
@@ -60,9 +53,6 @@ public:
void setTechnicianId(const std::string& technicianId);
void setTechnician(User* technician);
void setAssignedDate(const util::Timestamp& assignedDate);
void setStatus(util::ServiceJobStatus status);
void setStatus(ServiceJobStatus status);
void setCompletionDate(const util::Timestamp& completionDate);
std::string serialize() const;
static JobCard* deserialize(const std::string&);
static std::string getHeaders();
};
@@ -1,7 +1,4 @@
#include <sstream>
#include "Notification.h"
#include "StringHelper.h"
#include "Factory.h"
int Notification::m_uid = 0;
@@ -17,34 +14,6 @@ Notification::Notification(const std::string& recipientUserId, User* recipient,
m_message(message),
m_createdAt(createdAt) {}
/*
Function: Notification (parameterized constructor with ID)
Description: Initializes a notification with an existing ID, recipient details,
title, message, and creation timestamp. Updates UID tracking based on ID.
Parameters:
- id: const std::string&, unique notification ID
- recipientUserId: const std::string&, ID of the recipient user
- title: const std::string&, notification title
- message: const std::string&, notification message
- createdAt: const util::Timestamp&, timestamp of creation
Returns:
- A new Notification object
*/
Notification::Notification(const std::string& id, const std::string& recipientUserId, const std::string& title, const std::string& message, const util::Timestamp& createdAt)
: m_id(id),
m_recipientUserId(recipientUserId),
m_recipient(nullptr),
m_title(title),
m_message(message),
m_createdAt(createdAt)
{
int idNumber = util::extractNumber(m_id);
if (idNumber > m_uid)
{
m_uid = idNumber;
}
}
const std::string& Notification::getId() const
{
return m_id;
@@ -104,72 +73,3 @@ void Notification::setCreatedAt(const util::Timestamp& createdAt)
{
m_createdAt = createdAt;
}
/*
Function: serialize
Description: Serializes the notification into a CSV-formatted string.
Parameters:
- None
Returns:
- std::string: Serialized notification record
*/
std::string Notification::serialize() const
{
std::ostringstream serializedNotification;
serializedNotification << m_id << ','
<< m_recipientUserId << ','
<< m_title << ','
<< m_message << ','
<< m_createdAt.toString();
return serializedNotification.str();
}
/*
Function: deserialize
Description: Deserializes a CSV-formatted string into a Notification object.
Parameters:
- record: const std::string&, serialized notification record
Returns:
- Notification*: Pointer to the deserialized Notification object
Throws:
- std::runtime_error if timestamp parsing fails
*/
Notification* Notification::deserialize(const std::string& record)
{
std::string id, recipientUserId, title, message, createdAtTimestampString;
std::istringstream serializedNotification(record);
getline(serializedNotification, id, ',');
getline(serializedNotification, recipientUserId, ',');
getline(serializedNotification, title, ',');
getline(serializedNotification, message, ',');
getline(serializedNotification, createdAtTimestampString, ',');
util::Timestamp createdAtTimestamp;
try
{
createdAtTimestamp = util::Timestamp::fromString(createdAtTimestampString);
}
catch (...)
{
throw std::runtime_error("Invalid createdAt timestamp");
}
return Factory::getObject<Notification>(
id,
recipientUserId,
title,
message,
createdAtTimestamp
);
}
/*
Function: getHeaders
Description: Retrieves the CSV headers for notification serialization.
Parameters:
- None
Returns:
- std::string: Header string ("ID,RecipientID,Title,Message,Timestamp")
*/
std::string Notification::getHeaders()
{
return "ID,RecipientID,Title,Message,Timestamp";
}
@@ -17,7 +17,6 @@ private:
public:
Notification();
Notification(const std::string& recipientUserId, User* recipient, const std::string& title, const std::string& message, const util::Timestamp& createdAt);
Notification(const std::string& id, const std::string& recipientUserId, const std::string& title, const std::string& message, const util::Timestamp& createdAt);
const std::string& getId() const;
const std::string& getRecipientUserId() const;
User* getRecipient() const;
@@ -30,7 +29,4 @@ public:
void setTitle(const std::string& title);
void setMessage(const std::string& message);
void setCreatedAt(const util::Timestamp& createdAt);
std::string serialize() const;
static Notification* deserialize(const std::string&);
static std::string getHeaders();
};
@@ -1,8 +1,4 @@
#include <sstream>
#include "Service.h"
#include "InventoryItem.h"
#include "StringHelper.h"
#include "Factory.h"
int Service::m_uid = 0;
@@ -16,42 +12,7 @@ Service::Service(const std::string& name, const util::Map<std::string, Inventory
m_name(name),
m_requiredInventoryItems(requiredInventoryItems),
m_status(util::State::ACTIVE),
m_laborCost(laborCost)
{
int numberOfInventoryItems = m_requiredInventoryItems.getSize();
auto inventoryItemPointers = m_requiredInventoryItems.getValues();
for (int index = 0; index < numberOfInventoryItems; index++)
{
m_requiredInventoryItemIDs.push_back(inventoryItemPointers[index]->getId());
}
}
/*
Function: Service (parameterized constructor with ID)
Description: Initializes a service with an existing ID, name, inventory item IDs,
labor cost, and state. Updates UID tracking based on ID.
Parameters:
- id: const std::string&, unique service ID
- name: const std::string&, name of the service
- requiredInventoryItemIDs: const util::Vector<std::string>&, IDs of required inventory items
- laborCost: double, labor cost of the service
- status: util::State, state of the service (ACTIVE/INACTIVE)
Returns:
- A new Service object
*/
Service::Service(const std::string& id, const std::string& name, const util::Vector<std::string>& requiredInventoryItemIDs, double laborCost, util::State status)
: m_id(id),
m_name(name),
m_requiredInventoryItemIDs(requiredInventoryItemIDs),
m_status(status),
m_laborCost(laborCost)
{
int idNumber = util::extractNumber(m_id);
if (idNumber > m_uid)
{
m_uid = idNumber;
}
}
m_laborCost(laborCost) {}
const std::string& Service::getId() const
{
@@ -63,19 +24,6 @@ const std::string& Service::getName() const
return m_name;
}
/*
Function: getRequiredInventoryItemIDs
Description: Retrieves the IDs of required inventory items for the service.
Parameters:
- None
Returns:
- const util::Vector<std::string>&: Inventory item IDs
*/
const util::Vector<std::string>& Service::getRequiredInventoryItemIDs() const
{
return m_requiredInventoryItemIDs;
}
const util::Map<std::string, InventoryItem*>& Service::getRequiredInventoryItems() const
{
return m_requiredInventoryItems;
@@ -104,13 +52,6 @@ void Service::setName(const std::string& name)
void Service::setRequiredInventoryItems(const util::Map<std::string, InventoryItem*>& requiredInventoryItems)
{
m_requiredInventoryItems = requiredInventoryItems;
m_requiredInventoryItemIDs.clear();
int numberOfRequiredInventoryItems = m_requiredInventoryItems.getSize();
auto inventoryItemPointers = m_requiredInventoryItems.getValues();
for (int index = 0; index < numberOfRequiredInventoryItems; index++)
{
m_requiredInventoryItemIDs.push_back(inventoryItemPointers[index]->getId());
}
}
void Service::setLaborCost(double laborCost)
@@ -122,118 +63,3 @@ void Service::setState(util::State status)
{
m_status = status;
}
/*
Function: getInventoryItemIDsAsString (static helper)
Description: Converts a vector of inventory item IDs into a single string separated by '|'.
Parameters:
- inventoryItemIds: const util::Vector<std::string>&, vector of inventory item IDs
Returns:
- std::string: Concatenated inventory item IDs string
*/
static std::string getInventoryItemIDsAsString(const util::Vector<std::string>& inventoryItemIds)
{
int numberOfInventoryItems = inventoryItemIds.getSize();
std::string inventoryItemIDs;
for (int index = 0; index < numberOfInventoryItems; index++)
{
inventoryItemIDs += inventoryItemIds[index];
if (index < numberOfInventoryItems - 1)
{
inventoryItemIDs += '|';
}
}
return inventoryItemIDs;
}
/*
Function: getInventoryItemIDsAsVector (static helper)
Description: Converts a string of inventory item IDs separated by '|' into a vector.
Parameters:
- inventoryItemIDsString: const std::string&, concatenated inventory item IDs string
Returns:
- util::Vector<std::string>: Vector of inventory item IDs
*/
static util::Vector<std::string> getInventoryItemIDsAsVector(const std::string& inventoryItemIDsString)
{
util::Vector<std::string> inventoryItemIDs;
std::string inventoryItemID;
std::istringstream serializedInventoryItemIDs(inventoryItemIDsString);
while (getline(serializedInventoryItemIDs, inventoryItemID, '|'))
{
inventoryItemIDs.push_back(inventoryItemID);
}
return inventoryItemIDs;
}
/*
Function: serialize
Description: Serializes the service into a CSV-formatted string.
Parameters:
- None
Returns:
- std::string: Serialized service record
*/
std::string Service::serialize() const
{
std::ostringstream serializedService;
serializedService << m_id << ','
<< m_name << ','
<< getInventoryItemIDsAsString(m_requiredInventoryItemIDs) << ','
<< m_laborCost << ','
<< util::getStateString(m_status);
return serializedService.str();
}
/*
Function: deserialize
Description: Deserializes a CSV-formatted string into a Service object.
Parameters:
- record: const std::string&, serialized service record
Returns:
- Service*: Pointer to the deserialized Service object
Throws:
- std::runtime_error if labor cost parsing fails
*/
Service* Service::deserialize(const std::string& record)
{
std::string id, name;
std::string inventoryItemIDsString, laborCostString, statusString;
double laborCost;
std::istringstream serializedService(record);
getline(serializedService, id, ',');
getline(serializedService, name, ',');
getline(serializedService, inventoryItemIDsString, ',');
getline(serializedService, laborCostString, ',');
getline(serializedService, statusString, ',');
util::Vector<std::string> inventoryItemIDs = getInventoryItemIDsAsVector(inventoryItemIDsString);
try
{
laborCost = std::stod(laborCostString);
}
catch (...)
{
throw std::runtime_error("Invalid labor cost");
}
util::State status = util::getState(statusString);
return Factory::getObject<Service>(
id,
name,
inventoryItemIDs,
laborCost,
status
);
}
/*
Function: getHeaders
Description: Retrieves the CSV headers for service serialization.
Parameters:
- None
Returns:
- std::string: Header string ("ID,Name,InventoryIDs,LaborCost,Status")
*/
std::string Service::getHeaders()
{
return "ID,Name,InventoryIDs,LaborCost,Status";
}
@@ -1,7 +1,6 @@
#pragma once
#include <string>
#include "Map.h"
#include "Vector.h"
#include "Enums.h"
class InventoryItem;
@@ -12,17 +11,14 @@ private:
static int m_uid;
std::string m_id;
std::string m_name;
util::Vector<std::string> m_requiredInventoryItemIDs;
util::Map<std::string, InventoryItem*> m_requiredInventoryItems;
double m_laborCost;
util::State m_status;
public:
Service();
Service(const std::string& name, const util::Map<std::string, InventoryItem*>& requiredInventoryItems, double laborCost);
Service(const std::string& id, const std::string& name, const util::Vector<std::string>& requiredInventoryItemIDs, double laborCost, util::State state);
const std::string& getId() const;
const std::string& getName() const;
const util::Vector<std::string>& getRequiredInventoryItemIDs() const;
const util::Map<std::string, InventoryItem*>& getRequiredInventoryItems() const;
double getLaborCost() const;
util::State getState() const;
@@ -31,7 +27,4 @@ public:
void setRequiredInventoryItems(const util::Map<std::string, InventoryItem*>& requiredInventoryItems);
void setLaborCost(double laborCost);
void setState(util::State status);
std::string serialize() const;
static Service* deserialize(const std::string&);
static std::string getHeaders();
};
@@ -1,19 +1,42 @@
#include <stdexcept>
#include <sstream>
/*
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 "Service.h"
#include "Enums.h"
#include "Factory.h"
#include "StringHelper.h"
int ServiceBooking::m_uid = 0;
/*
Function: ServiceBooking
Description: Default constructor that initializes a new service booking
with a unique ID, no customer or technician, and zero discount.
Parameter: None
Return type: Constructor
*/
ServiceBooking::ServiceBooking()
: m_id("SRV" + std::to_string(++m_uid)),
m_customer(nullptr),
m_assignedTechnician(nullptr),
m_discountPercentage(0.0) {}
/*
Function: ServiceBooking
Description: Parameterized constructor that initializes a service booking
with customer, vehicle, services, and discount details.
Parameter: util::ServiceJobStatus status - current booking status
const util::Map<std::string, Service*>& services - map of services
const std::string& customerId - ID of the customer
User* customer - pointer to the customer object
const std::string& vehicleNumber - vehicle registration number
const std::string& vehicleBrand - brand of the vehicle
const std::string& vehicleModel - model of the vehicle
double discountPercentage - discount applied to the booking
Return type: Constructor
*/
ServiceBooking::ServiceBooking(
util::ServiceJobStatus status,
const util::Map<std::string,
@@ -23,8 +46,6 @@ ServiceBooking::ServiceBooking(
const std::string& vehicleNumber,
const std::string& vehicleBrand,
const std::string& vehicleModel,
const std::string& assignedTechnicianId,
User* assignedTechnician,
double discountPercentage
)
: m_id("SRV" + std::to_string(++m_uid)),
@@ -35,319 +56,249 @@ ServiceBooking::ServiceBooking(
m_vehicleNumber(vehicleNumber),
m_vehicleBrand(vehicleBrand),
m_vehicleModel(vehicleModel),
m_assignedTechnicianId(assignedTechnicianId),
m_assignedTechnician(assignedTechnician),
m_discountPercentage(discountPercentage)
{
int numberOfServices = m_services.getSize();
auto servicePointers = m_services.getValues();
for (int index = 0; index < numberOfServices; index++)
{
m_serviceIDs.push_back(servicePointers[index]->getId());
}
}
/*
Function: ServiceBooking (parameterized constructor with ID)
Description: Initializes a service booking with an existing ID, status, service IDs,
customer details, vehicle details, technician ID, and discount percentage.
Updates UID tracking based on ID.
Parameters:
- id: const std::string&, unique booking ID
- status: util::ServiceJobStatus, job status of the booking
- serviceIDs: const util::Vector<std::string>&, IDs of booked services
- customerId: const std::string&, ID of the customer
- vehicleNumber: const std::string&, vehicle number
- vehicleBrand: const std::string&, vehicle brand
- vehicleModel: const std::string&, vehicle model
- assignedTechnicianId: const std::string&, ID of the assigned technician
- discountPercentage: double, discount applied
Returns:
- A new ServiceBooking object
*/
ServiceBooking::ServiceBooking(
const std::string& id,
util::ServiceJobStatus status,
const util::Vector<std::string>& serviceIDs,
const std::string& customerId,
const std::string& vehicleNumber,
const std::string& vehicleBrand,
const std::string& vehicleModel,
const std::string& assignedTechnicianId,
double discountPercentage
)
: m_id(id),
m_status(status),
m_serviceIDs(serviceIDs),
m_customerId(customerId),
m_customer(nullptr),
m_vehicleNumber(vehicleNumber),
m_vehicleBrand(vehicleBrand),
m_vehicleModel(vehicleModel),
m_assignedTechnicianId(assignedTechnicianId),
m_assignedTechnicianId(""),
m_assignedTechnician(nullptr),
m_discountPercentage(discountPercentage)
{
int idNumber = util::extractNumber(m_id);
if (idNumber > m_uid)
{
m_uid = idNumber;
}
}
/*
Function: getId
Description: Retrieves the unique identifier of the service booking.
Parameter: None
Return type: const std::string&
*/
const std::string& ServiceBooking::getId() const
{
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
{
return m_status;
}
/*
Function: getServiceIDs
Description: Retrieves the IDs of services booked.
Parameters:
- None
Returns:
- const util::Vector<std::string>&: Service IDs
Function: getServices
Description: Retrieves the services associated with the booking.
Parameter: None
Return type: const util::Map<std::string, Service*>&
*/
const util::Vector<std::string>& ServiceBooking::getServiceIDs() const
{
return m_serviceIDs;
}
const util::Map<std::string, Service*>& ServiceBooking::getServices() const
{
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
{
return m_customerId;
}
/*
Function: getCustomer
Description: Retrieves the customer object associated with the booking.
Parameter: None
Return type: User*
*/
User* ServiceBooking::getCustomer() const
{
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
{
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
{
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
{
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
{
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;
}
/*
Function: getDiscountPercentage
Description: Retrieves the discount percentage applied to the booking.
Parameter: None
Return type: double
*/
double ServiceBooking::getDiscountPercentage() const
{
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)
{
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)
{
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)
{
m_services = services;
m_serviceIDs.clear();
int numberOfServices = m_services.getSize();
auto servicePointers = m_services.getValues();
for (int index = 0; index < numberOfServices; index++)
{
m_serviceIDs.push_back(servicePointers[index]->getId());
}
}
/*
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
m_assignedTechnicianId = assignedTechnicianId;
}
/*
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;
}
/*
Function: setDiscountPercentage
Description: Sets the discount percentage for the booking.
Parameter: double discountPercentage - new discount percentage
Return type: void
*/
void ServiceBooking::setDiscountPercentage(double discountPercentage)
{
m_discountPercentage = discountPercentage;
}
/*
Function: getServiceIDsAsString (static helper)
Description: Converts a vector of service IDs into a single string separated by '|'.
Parameters:
- serviceIDs: const util::Vector<std::string>&, vector of service IDs
Returns:
- std::string: Concatenated service IDs string
*/
static std::string getServiceIDsAsString(const util::Vector<std::string>& serviceIDs)
{
int numberOfServices = serviceIDs.getSize();
std::string serviceIDsString;
for (int index = 0; index < numberOfServices; index++)
{
serviceIDsString += serviceIDs[index];
if (index < numberOfServices - 1)
{
serviceIDsString += '|';
}
}
return serviceIDsString;
}
/*
Function: getServiceIDsAsVector (static helper)
Description: Converts a string of service IDs separated by '|' into a vector.
Parameters:
- serviceIDsString: const std::string&, concatenated service IDs string
Returns:
- util::Vector<std::string>: Vector of service IDs
*/
static util::Vector<std::string> getServiceIDsAsVector(const std::string& serviceIDsString)
{
util::Vector<std::string> serviceIDs;
std::string serviceID;
std::istringstream serializedServiceIDs(serviceIDsString);
while (getline(serializedServiceIDs, serviceID, '|'))
{
serviceIDs.push_back(serviceID);
}
return serviceIDs;
}
/*
Function: serialize
Description: Serializes the service booking into a CSV-formatted string.
Parameters:
- None
Returns:
- std::string: Serialized booking record
*/
std::string ServiceBooking::serialize() const
{
std::ostringstream serializedBooking;
serializedBooking << m_id << ','
<< util::getServiceJobStatusString(m_status) << ','
<< getServiceIDsAsString(m_serviceIDs) << ','
<< m_customerId << ','
<< m_vehicleNumber << ','
<< m_vehicleBrand << ','
<< m_vehicleModel << ','
<< m_assignedTechnicianId << ','
<< m_discountPercentage << ',';
return serializedBooking.str();
}
/*
Function: deserialize
Description: Deserializes a CSV-formatted string into a ServiceBooking object.
Parameters:
- record: const std::string&, serialized booking record
Returns:
- ServiceBooking*: Pointer to the deserialized ServiceBooking object
Throws:
- std::runtime_error if discount percentage parsing fails
*/
ServiceBooking* ServiceBooking::deserialize(const std::string& record)
{
std::string id, customerId, vehicleNumber, vehicleBrand, vehicleModel, assignedTechnicianId;
std::string serviceJobStatusString, serviceIDsString, discountPercentageString;
double discountPercentage;
std::istringstream serializedBooking(record);
getline(serializedBooking, id, ',');
getline(serializedBooking, serviceJobStatusString, ',');
getline(serializedBooking, serviceIDsString, ',');
getline(serializedBooking, customerId, ',');
getline(serializedBooking, vehicleNumber, ',');
getline(serializedBooking, vehicleBrand, ',');
getline(serializedBooking, vehicleModel, ',');
getline(serializedBooking, assignedTechnicianId, ',');
getline(serializedBooking, discountPercentageString, ',');
util::Vector<std::string> serviceIDs = getServiceIDsAsVector(serviceIDsString);
try
{
discountPercentage = std::stod(discountPercentageString);
}
catch (...)
{
throw std::runtime_error("Invalid discount percentage");
}
util::ServiceJobStatus status = util::getServiceJobStatus(serviceJobStatusString);
return Factory::getObject<ServiceBooking>(
id,
status,
serviceIDs,
customerId,
vehicleNumber,
vehicleBrand,
vehicleModel,
assignedTechnicianId,
discountPercentage
);
}
/*
Function: getHeaders
Description: Retrieves the CSV headers for service booking serialization.
Parameters:
- None
Returns:
- std::string: Header string ("ID,Status,ServiceIDs,CustomerID,VehicleNumber,VehicleBrand,VehicleModel,AssignedTechnicianID,DiscountPercentage")
*/
std::string ServiceBooking::getHeaders()
{
return "ID,Status,ServiceIDs,CustomerID,VehicleNumber,VehicleBrand,VehicleModel,AssignedTechnicianID,DiscountPercentage";
}
@@ -1,7 +1,14 @@
/*
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
#include <string>
#include "Map.h"
#include "Vector.h"
#include "Enums.h"
class Service;
@@ -13,7 +20,6 @@ private:
static int m_uid;
std::string m_id;
util::ServiceJobStatus m_status;
util::Vector<std::string> m_serviceIDs;
util::Map<std::string, Service*> m_services;
std::string m_customerId;
User* m_customer;
@@ -34,24 +40,10 @@ public:
const std::string& vehicleNumber,
const std::string& vehicleBrand,
const std::string& vehicleModel,
const std::string& assignedTechnicianId,
User* assignedTechnician,
double discountPercentage
);
ServiceBooking(
const std::string& id,
util::ServiceJobStatus status,
const util::Vector<std::string>& serviceIDs,
const std::string& customerId,
const std::string& vehicleNumber,
const std::string& vehicleBrand,
const std::string& vehicleModel,
const std::string& assignedTechnicianId,
double discountPercentage
);
const std::string& getId() const;
util::ServiceJobStatus getStatus() const;
const util::Vector<std::string>& getServiceIDs() const;
const util::Map<std::string, Service*>& getServices() const;
const std::string& getCustomerId() const;
User* getCustomer() const;
@@ -59,7 +51,7 @@ public:
const std::string& getVehicleBrand() const;
const std::string& getVehicleModel() const;
const std::string& getAssignedTechnicianId() const;
const User* getAssignedTechnician() const;
User* getAssignedTechnician() const;
double getDiscountPercentage() const;
void setId(const std::string& id);
void setStatus(const util::ServiceJobStatus& status);
@@ -72,7 +64,4 @@ public:
void setAssignedTechnicianId(const std::string& assignedTechnicianId);
void setAssignedTechnician(User* assignedTechnician);
void setDiscountPercentage(double discountPercentage);
std::string serialize() const;
static ServiceBooking* deserialize(const std::string&);
static std::string getHeaders();
};
@@ -1,9 +1,6 @@
#include <sstream>
#include "User.h"
#include "Notification.h"
#include "Enums.h"
#include "Factory.h"
#include "StringHelper.h"
int User::m_uid = 0;
@@ -22,45 +19,11 @@ User::User(const std::string& userName, const std::string& password, const std::
m_type(role),
m_status(util::State::ACTIVE) {}
/*
Function: User (parameterized constructor with ID)
Description: Initializes a user with an existing ID, credentials, personal details,
role, and state. Updates UID tracking based on ID.
Parameters:
- userId: const std::string&, unique user ID
- userName: const std::string&, username
- password: const std::string&, password
- name: const std::string&, full name
- phone: const std::string&, phone number
- email: const std::string&, email address
- role: util::UserType, role of the user
- status: util::State, state of the user (ACTIVE/INACTIVE)
Returns:
- A new User object
*/
User::User(const std::string& userId, const std::string& userName, const std::string& password, const std::string& name, const std::string& phone, const std::string& email, util::UserType role, util::State status)
: m_id(userId),
m_userName(userName),
m_password(password),
m_name(name),
m_phone(phone),
m_email(email),
m_type(role),
m_status(status)
{
int idNumber = util::extractNumber(m_id);
if (idNumber > m_uid)
{
m_uid = idNumber;
}
}
User::~User()
{
auto values = m_notifications.getValues();
for (int index = 0; index < values.getSize(); index++)
for (int index = 0; index < m_notifications.getSize(); index++)
{
delete values[index];
delete m_notifications.getValues()[index];
}
}
@@ -157,71 +120,3 @@ void User::setState(util::State status)
void User::update(Notification* notification)
{
}
/*
Function: serialize
Description: Serializes the user into a CSV-formatted string.
Parameters:
- None
Returns:
- std::string: Serialized user record
*/
std::string User::serialize() const
{
std::ostringstream serializedUser;
serializedUser << m_id << ','
<< m_userName << ','
<< m_password << ','
<< m_name << ','
<< m_phone << ','
<< m_email << ','
<< util::getUserTypeString(m_type) << ','
<< util::getStateString(m_status);
return serializedUser.str();
}
/*
Function: deserialize
Description: Deserializes a CSV-formatted string into a User object.
Parameters:
- record: const std::string&, serialized user record
Returns:
- User*: Pointer to the deserialized User object
*/
User* User::deserialize(const std::string& record)
{
std::string id, name, username, phone, password, email;
std::string userTypeString, stateString;
std::istringstream serializedUser(record);
getline(serializedUser, id, ',');
getline(serializedUser, username, ',');
getline(serializedUser, password, ',');
getline(serializedUser, name, ',');
getline(serializedUser, phone, ',');
getline(serializedUser, email, ',');
getline(serializedUser, userTypeString, ',');
getline(serializedUser, stateString);
util::UserType userType = util::getUserType(userTypeString);
util::State status = util::getState(stateString);
return Factory::getObject<User>(id,
username,
password,
name,
phone,
email,
userType,
status);
}
/*
Function: getHeaders
Description: Retrieves the CSV headers for user serialization.
Parameters:
- None
Returns:
- std::string: Header string ("ID,Username,Password,Name,Phone,Email,UserType,UserStatus")
*/
std::string User::getHeaders()
{
return "ID,Username,Password,Name,Phone,Email,UserType,UserStatus";
}
@@ -22,7 +22,6 @@ private:
public:
User();
User(const std::string& userName, const std::string& password, const std::string& name, const std::string& phone, const std::string& email, util::UserType role);
User(const std::string& userId, const std::string& userName, const std::string& password, const std::string& name, const std::string& phone, const std::string& email, util::UserType role, util::State status);
~User();
const std::string& getId() const;
const std::string& getUserName() const;
@@ -43,7 +42,4 @@ public:
void setRole(util::UserType role);
void setState(util::State status);
void update(Notification* notification) override;
std::string serialize() const;
static User* deserialize(const std::string&);
static std::string getHeaders();
};
@@ -1,3 +1,81 @@
/*
File: AuthenticationManagementService.cpp
Description: Implementation file containing the method definitions of the
AuthenticationManagementService class, including login, logout,
password change, and retrieval of the authenticated user.
Author: Trenser
Date:19-May-2026
*/
#include <stdexcept>
#include "AuthenticationManagementService.h"
#include "User.h"
User* AuthenticationManagementService::m_authenticatedUser = nullptr;
/*
Function: login
Description: Authenticates a user by checking the provided username and password
against the stored users in the DataStore. If successful, sets the
authenticated user.
Parameter: const std::string& username - users username
const std::string& password - users password
Return type: bool - true if login successful, false otherwise
*/
bool AuthenticationManagementService::login(const std::string& username, const std::string& password)
{
util::Map<std::string, User*> users = m_dataStore.getUsers();
int usersMapSize = users.getSize();
for (int index = 0; index < usersMapSize; index++)
{
User* user = users.getValueAt(index);
if (username == user->getUserName())
{
if (password == user->getPassword())
{
m_authenticatedUser = user;
return true;
}
return false;
}
}
return false;
}
/*
Function: getAuthenticatedUser
Description: Retrieves the currently authenticated user.
Parameter: None
Return type: User* - pointer to the authenticated user
*/
User* AuthenticationManagementService::getAuthenticatedUser()
{
return m_authenticatedUser;
}
/*
Function: logout
Description: Logs out the currently authenticated user by clearing the
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,3 +1,11 @@
/*
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
#include <string>
#include "DataStore.h"
@@ -1,104 +1 @@
/*
File: InventoryManagementService.cpp
Description: Implements the InventoryManagementService class, which manages inventory
items and observer relationships within the system. Provides methods
for loading and saving inventory items from persistent storage, as well
as attaching and persisting observers for notification handling.
Author: Trenser
Date: 22-May-2026
*/
#include "InventoryManagementService.h"
#include "FileManager.h"
#include "InventoryItem.h"
#include "Utility.h"
#include "Config.h"
/*
Function: getObserverIDs
Description: Retrieves the IDs of all observers currently attached to the
InventoryManagementService.
Parameters:
- None
Returns:
- util::Vector<std::string>: Vector of observer user IDs
*/
util::Vector<std::string> InventoryManagementService::getObserverIDs()
{
util::Vector<std::string> observerIDs;
int numberOfObservers = m_observers.getSize();
for (int index = 0; index < numberOfObservers; index++)
{
User* observer = m_observers.getValueAt(index);
if (observer)
{
observerIDs.push_back(observer->getId());
}
}
return observerIDs;
}
/*
Function: loadInventoryItems
Description: Loads inventory items from persistent storage into the datastore.
Uses FileManager to deserialize inventory items from the configured file.
Parameters:
- None
Returns:
- void
*/
void InventoryManagementService::loadInventoryItems()
{
util::FileManager<InventoryItem> inventoryItemFileManager(config::file::INVENTORYITEM_FILE);
auto& inventoryItems = m_dataStore.getInventoryItems();
auto inventoryItemsMap = inventoryItemFileManager.load();
int numberOfInventoryItems = inventoryItemsMap.getSize();
for (int index = 0; index < numberOfInventoryItems; index++)
{
inventoryItems[inventoryItemsMap.getKeyAt(index)] = inventoryItemsMap.getValueAt(index);
}
}
/*
Function: saveInventoryItems
Description: Saves inventory items from the datastore to persistent storage.
Uses FileManager to serialize inventory items into the configured file.
Parameters:
- None
Returns:
- void
*/
void InventoryManagementService::saveInventoryItems()
{
util::FileManager<InventoryItem> inventoryItemFileManager(config::file::INVENTORYITEM_FILE);
auto& inventoryItems = m_dataStore.getInventoryItems();
inventoryItemFileManager.save(inventoryItems);
}
/*
Function: loadObservers
Description: Loads observer IDs from persistent storage and attaches corresponding
users as observers to the InventoryManagementService.
Parameters:
- None
Returns:
- void
*/
void InventoryManagementService::loadObservers()
{
util::loadObservers(config::file::INVENTORYMANAGEMENTOBSERVERS, this, m_dataStore);
}
/*
Function: saveObservers
Description: Saves the current observer IDs of the InventoryManagementService
to persistent storage for future retrieval.
Parameters:
- None
Returns:
- void
*/
void InventoryManagementService::saveObservers()
{
util::saveObservers(config::file::INVENTORYMANAGEMENTOBSERVERS, this);
}
@@ -1,7 +1,6 @@
#pragma once
#include <string>
#include "Map.h"
#include "Vector.h"
#include "NotificationManagementService.h"
#include "DataStore.h"
@@ -12,7 +11,6 @@ class InventoryManagementService : public NotificationManagementService
private:
DataStore& m_dataStore;
static util::Map<std::string, User*> m_observers;
util::Vector<std::string> getObserverIDs() override;
public:
InventoryManagementService() : m_dataStore(DataStore::getInstance()) {}
util::Map<std::string, InventoryItem*> getInventoryItems();
@@ -23,8 +21,4 @@ public:
void sendNotification(User* user, const std::string& title, const std::string& message) override;
void attach(User* user) override;
void detach(User* user) override;
void loadInventoryItems();
void saveInventoryItems();
void loadObservers();
void saveObservers();
};
@@ -10,5 +10,4 @@ public:
virtual void sendNotification(User* recipient, const std::string& title, const std::string& message) = 0;
virtual void attach(User* user) = 0;
virtual void detach(User* user) = 0;
virtual util::Vector<std::string> getObserverIDs() = 0;
};
@@ -1,123 +1 @@
#include <stdexcept>
#include "PaymentManagementService.h"
#include "Invoice.h"
#include "FileManager.h"
#include "Utility.h"
#include "Config.h"
/*
Function: getObserverIDs
Description: Retrieves the IDs of all observers currently attached to the
PaymentManagementService.
Parameters:
- None
Returns:
- util::Vector<std::string>: Vector of observer user IDs
*/
util::Vector<std::string> PaymentManagementService::getObserverIDs()
{
util::Vector<std::string> observerIDs;
int numberOfObservers = m_observers.getSize();
for (int index = 0; index < numberOfObservers; index++)
{
User* observer = m_observers.getValueAt(index);
if (observer)
{
observerIDs.push_back(observer->getId());
}
}
return observerIDs;
}
/*
Function: loadInvoices
Description: Loads invoices from persistent storage into the datastore.
Validates associated service bookings and inventory parts before
attaching them to each invoice. Throws exceptions if invalid IDs
are encountered.
Parameters:
- None
Returns:
- void
Throws:
- std::runtime_error if a booking ID or part ID is invalid
*/
void PaymentManagementService::loadInvoices()
{
util::FileManager<Invoice> invoiceFileManager(config::file::INVOICE_FILE);
auto& invoices = m_dataStore.getInvoices();
auto& serviceBookings = m_dataStore.getServiceBookings();
auto& inventoryItems = m_dataStore.getInventoryItems();
auto invoicesMap = invoiceFileManager.load();
for (int invoiceIndex = 0; invoiceIndex < invoicesMap.getSize(); invoiceIndex++)
{
Invoice* invoice = invoicesMap.getValueAt(invoiceIndex);
int bookingIndex = serviceBookings.find(invoice->getBookingId());
if (bookingIndex == -1)
{
throw std::runtime_error("Invalid Booking ID");
}
ServiceBooking* booking = serviceBookings.getValueAt(bookingIndex);
invoice->setBooking(booking);
util::Map<std::string, InventoryItem*> invoiceParts;
auto& partIDs = invoice->getPartIDs();
for (int partIndex = 0; partIndex < partIDs.getSize(); partIndex++)
{
const std::string& partID = partIDs[partIndex];
int inventoryIndex = inventoryItems.find(partID);
if (inventoryIndex == -1)
{
throw std::runtime_error("Invalid Part ID");
}
invoiceParts[partID] = inventoryItems.getValueAt(inventoryIndex);
}
invoice->setParts(invoiceParts);
invoices[invoice->getId()] = invoice;
}
}
/*
Function: saveInvoices
Description: Saves invoices from the datastore to persistent storage.
Uses FileManager to serialize invoices into the configured file.
Parameters:
- None
Returns:
- void
*/
void PaymentManagementService::saveInvoices()
{
util::FileManager<Invoice> invoiceFileManager(config::file::INVOICE_FILE);
auto& invoices = m_dataStore.getInvoices();
invoiceFileManager.save(invoices);
}
/*
Function: loadObservers
Description: Loads observer IDs from persistent storage and attaches corresponding
users as observers to the PaymentManagementService.
Parameters:
- None
Returns:
- void
Throws:
- std::runtime_error if an observer ID is invalid (not found in datastore)
*/
void PaymentManagementService::loadObservers()
{
util::loadObservers(config::file::PAYMENTMANAGEMENTOBSERVERS, this, m_dataStore);
}
/*
Function: saveObservers
Description: Saves the current observer IDs of the PaymentManagementService
to persistent storage for future retrieval.
Parameters:
- None
Returns:
- void
*/
void PaymentManagementService::saveObservers()
{
util::saveObservers(config::file::PAYMENTMANAGEMENTOBSERVERS, this);
}
@@ -13,7 +13,6 @@ class PaymentManagementService : public NotificationManagementService
private:
DataStore& m_dataStore;
static util::Map<std::string, User*> m_observers;
util::Vector<std::string> getObserverIDs() override;
public:
PaymentManagementService() : m_dataStore(DataStore::getInstance()) {}
void generateInvoice(ServiceBooking* booking);
@@ -23,8 +22,4 @@ public:
void sendNotification(User* user, const std::string& title, const std::string& message) override;
void attach(User* user) override;
void detach(User* user) override;
void loadInvoices();
void saveInvoices();
void loadObservers();
void saveObservers();
};
@@ -1,326 +1,98 @@
/*
File: ServiceManagementService.cpp
Description: Implementation file containing the method definitions of the
ServiceManagementService class, including service and combo package
purchasing logic, booking creation, and notification handling.
Author: Trenser
Date:19-May-2026
*/
#include <stdexcept>
#include "ServiceManagementService.h"
#include "FileManager.h"
#include "AuthenticationManagementService.h"
#include "Service.h"
#include "ComboPackage.h"
#include "ServiceBooking.h"
#include "JobCard.h"
#include "Config.h"
#include "Utility.h"
#include "ComboPackage.h"
#include "Factory.h"
/*
Function: getObserverIDs
Description: Retrieves the IDs of all observers currently attached to the
ServiceManagementService.
Parameters:
- None
Returns:
- util::Vector<std::string>: Vector of observer user IDs
Function: purchaseService
Description: Creates a new service booking for the authenticated user. Validates
service IDs, retrieves services from the DataStore, and generates a
booking. Sends a notification upon successful booking.
Parameter: const util::Vector<std::string>& serviceIDs - IDs of services to purchase
const std::string& vehicleNumber - vehicle registration number
const std::string& vehicleBrand - brand of the vehicle
const std::string& vehicleModel - model of the vehicle
Return type: void
*/
util::Vector<std::string> ServiceManagementService::getObserverIDs()
void ServiceManagementService::purchaseService(const util::Vector<std::string>& serviceIDs, const std::string& vehicleNumber, const std::string& vehicleBrand, const std::string& vehicleModel)
{
util::Vector<std::string> observerIDs;
int numberOfObservers = m_observers.getSize();
for (int index = 0; index < numberOfObservers; index++)
AuthenticationManagementService m_authenticationManagementService;
auto authenticatedUser = m_authenticationManagementService.getAuthenticatedUser();
if (authenticatedUser == nullptr)
{
User* observer = m_observers.getValueAt(index);
if (observer)
{
observerIDs.push_back(observer->getId());
throw std::runtime_error("No user is currently logged in!");
}
}
return observerIDs;
}
/*
Function: loadServices
Description: Loads services from persistent storage into the datastore.
Validates required inventory items and attaches them to each service.
Parameters:
- None
Returns:
- void
Throws:
- std::runtime_error if an inventory item ID is invalid
*/
void ServiceManagementService::loadServices()
{
util::FileManager<Service> serviceFileManager(config::file::SERVICE_FILE);
auto& services = m_dataStore.getServices();
auto& inventoryItems = m_dataStore.getInventoryItems();
auto servicesMap = serviceFileManager.load();
for (int serviceIndex = 0; serviceIndex < servicesMap.getSize(); serviceIndex++)
auto& servicesMap = m_dataStore.getServices();
auto& serviceBookingMap = m_dataStore.getServiceBookings();
util::Map<std::string, Service*> selectedServices;
int selectedServicesCount = serviceIDs.getSize();
for (int index = 0; index < selectedServicesCount; index++)
{
Service* service = servicesMap.getValueAt(serviceIndex);
services[service->getId()] = service;
util::Map<std::string, InventoryItem*> inventoryItemsMap;
auto& inventoryItemIDs = service->getRequiredInventoryItemIDs();
for (int inventoryItemIndex = 0; inventoryItemIndex < inventoryItemIDs.getSize(); inventoryItemIndex++)
{
const std::string& inventoryItemID = inventoryItemIDs[inventoryItemIndex];
int index = inventoryItems.find(inventoryItemID);
if (index == -1)
{
throw std::runtime_error("Invalid Inventory Item ID");
}
inventoryItemsMap[inventoryItemID] = inventoryItems.getValueAt(index);
}
service->setRequiredInventoryItems(inventoryItemsMap);
}
}
/*
Function: saveServices
Description: Saves services from the datastore to persistent storage.
Uses FileManager to serialize services into the configured file.
Parameters:
- None
Returns:
- void
*/
void ServiceManagementService::saveServices()
{
util::FileManager<Service> serviceFileManager(config::file::SERVICE_FILE);
auto& services = m_dataStore.getServices();
serviceFileManager.save(services);
}
/*
Function: loadComboPackages
Description: Loads combo packages from persistent storage into the datastore.
Validates associated services and attaches them to each package.
Parameters:
- None
Returns:
- void
Throws:
- std::runtime_error if a service ID is invalid
*/
void ServiceManagementService::loadComboPackages()
{
util::FileManager<ComboPackage> comboPackageFileManager(config::file::COMBOPACKAGE_FILE);
auto& comboPackages = m_dataStore.getComboPackages();
auto& services = m_dataStore.getServices();
auto comboPackagesMap = comboPackageFileManager.load();
for (int packageIndex = 0; packageIndex < comboPackagesMap.getSize(); packageIndex++)
{
ComboPackage* comboPackage = comboPackagesMap.getValueAt(packageIndex);
util::Map<std::string, Service*> packageServices;
auto& serviceIDs = comboPackage->getServiceIDs();
for (int serviceIndex = 0; serviceIndex < serviceIDs.getSize(); serviceIndex++)
{
const std::string& serviceID = serviceIDs[serviceIndex];
int serviceMapIndex = services.find(serviceID);
if (serviceMapIndex == -1)
{
throw std::runtime_error("Invalid Service ID");
}
packageServices[serviceID] = services.getValueAt(serviceMapIndex);
}
comboPackage->setServices(packageServices);
comboPackages[comboPackage->getId()] = comboPackage;
}
}
/*
Function: saveComboPackages
Description: Saves combo packages from the datastore to persistent storage.
Uses FileManager to serialize combo packages into the configured file.
Parameters:
- None
Returns:
- void
*/
void ServiceManagementService::saveComboPackages()
{
util::FileManager<ComboPackage> comboPackageFileManager(config::file::COMBOPACKAGE_FILE);
auto& comboPackages = m_dataStore.getComboPackages();
comboPackageFileManager.save(comboPackages);
}
/*
Function: loadServiceBookings
Description: Loads service bookings from persistent storage into the datastore.
Validates associated services, customers, and technicians before
attaching them to each booking.
Parameters:
- None
Returns:
- void
Throws:
- std::runtime_error if a service ID, customer ID, or technician ID is invalid
- std::runtime_error if a user is not of the expected type (customer/technician)
*/
void ServiceManagementService::loadServiceBookings()
{
util::FileManager<ServiceBooking> bookingFileManager(config::file::SERVICEBOOKING_FILE);
auto& serviceBookings = m_dataStore.getServiceBookings();
auto& services = m_dataStore.getServices();
auto& users = m_dataStore.getUsers();
auto bookingsMap = bookingFileManager.load();
for (int bookingIndex = 0; bookingIndex < bookingsMap.getSize(); bookingIndex++)
{
ServiceBooking* booking = bookingsMap.getValueAt(bookingIndex);
util::Map<std::string, Service*> bookingServices;
auto& serviceIDs = booking->getServiceIDs();
for (int serviceIndex = 0; serviceIndex < serviceIDs.getSize(); serviceIndex++)
{
const std::string& serviceID = serviceIDs[serviceIndex];
int serviceMapIndex = services.find(serviceID);
if (serviceMapIndex == -1)
{
throw std::runtime_error("Invalid Service ID");
}
bookingServices[serviceID] = services.getValueAt(serviceMapIndex);
}
booking->setServices(bookingServices);
int customerIndex = users.find(booking->getCustomerId());
if (customerIndex == -1)
{
throw std::runtime_error("Invalid Customer ID");
}
User* customer = users.getValueAt(customerIndex);
if (customer->getUserType() != util::UserType::CUSTOMER)
{
throw std::runtime_error("User is not a customer");
}
booking->setCustomer(customer);
const std::string& technicianId = booking->getAssignedTechnicianId();
if (!technicianId.empty())
{
int technicianIndex = users.find(technicianId);
if (technicianIndex == -1)
{
throw std::runtime_error("Invalid Technician ID");
}
User* technician = users.getValueAt(technicianIndex);
if (technician->getUserType() != util::UserType::TECHNICIAN)
{
throw std::runtime_error("User is not a technician");
}
booking->setAssignedTechnician(technician);
}
serviceBookings[booking->getId()] = booking;
}
}
/*
Function: saveServiceBookings
Description: Saves service bookings from the datastore to persistent storage.
Uses FileManager to serialize bookings into the configured file.
Parameters:
- None
Returns:
- void
*/
void ServiceManagementService::saveServiceBookings()
{
util::FileManager<ServiceBooking> bookingFileManager(config::file::SERVICEBOOKING_FILE);
auto& serviceBookings = m_dataStore.getServiceBookings();
bookingFileManager.save(serviceBookings);
}
/*
Function: loadJobCards
Description: Loads job cards from persistent storage into the datastore.
Validates associated bookings, services, and technicians before
attaching them to each job card.
Parameters:
- None
Returns:
- void
Throws:
- std::runtime_error if a booking ID, service ID, or technician ID is invalid
- std::runtime_error if a service does not belong to the booking
- std::runtime_error if a user is not a technician
*/
void ServiceManagementService::loadJobCards()
{
util::FileManager<JobCard> jobCardFileManager(config::file::JOBCARD_FILE);
auto& jobCards = m_dataStore.getJobCards();
auto& serviceBookings = m_dataStore.getServiceBookings();
auto& services = m_dataStore.getServices();
auto& users = m_dataStore.getUsers();
auto jobCardsMap = jobCardFileManager.load();
for (int jobCardIndex = 0; jobCardIndex < jobCardsMap.getSize(); jobCardIndex++)
{
JobCard* jobCard = jobCardsMap.getValueAt(jobCardIndex);
int bookingIndex = serviceBookings.find(jobCard->getBookingId());
if (bookingIndex == -1)
{
throw std::runtime_error("Invalid Booking ID");
}
ServiceBooking* booking = serviceBookings.getValueAt(bookingIndex);
jobCard->setBooking(booking);
int serviceIndex = services.find(jobCard->getServiceId());
int serviceIndex = servicesMap.find(serviceIDs[index]);
if (serviceIndex == -1)
{
throw std::runtime_error("Invalid Service ID");
throw std::runtime_error("Service not found!");
}
Service* service = services.getValueAt(serviceIndex);
if (booking->getServices().find(jobCard->getServiceId()) == -1)
Service* service = servicesMap.getValueAt(serviceIndex);
selectedServices[service->getId()] = service;
}
ServiceBooking* serviceBooking = Factory::getObject<ServiceBooking>(util::ServiceJobStatus::STARTED, selectedServices, authenticatedUser->getId(), authenticatedUser, vehicleNumber, vehicleBrand, vehicleModel, 0);
if (serviceBooking == nullptr)
{
throw std::runtime_error("Service does not belong to booking");
}
jobCard->setService(service);
int technicianIndex = users.find(jobCard->getTechnicianId());
if (technicianIndex == -1)
{
throw std::runtime_error("Invalid Technician ID");
}
User* technician = users.getValueAt(technicianIndex);
if (technician->getUserType() != util::UserType::TECHNICIAN)
{
throw std::runtime_error("User is not a technician");
}
jobCard->setTechnician(technician);
jobCards[jobCard->getId()] = jobCard;
throw std::runtime_error("Failed to create service booking");
}
serviceBookingMap[serviceBooking->getId()] = serviceBooking;
sendNotification(authenticatedUser,
"Service Booking succeeded",
"Your service booking has been successfully placed with ID " + serviceBooking->getId());
}
/*
Function: saveJobCards
Description: Saves job cards from the datastore to persistent storage.
Uses FileManager to serialize job cards into the configured file.
Parameters:
- None
Returns:
- void
Function: purchaseComboPackage
Description: Creates a new service booking for a combo package. Validates the combo
package ID, retrieves services from the package, and generates a booking
with the applicable discount. Sends a notification upon successful booking.
Parameter: const std::string& comboPackageID - ID of the combo package
const std::string& vehicleNumber - vehicle registration number
const std::string& vehicleBrand - brand of the vehicle
const std::string& vehicleModel - model of the vehicle
Return type: void
*/
void ServiceManagementService::saveJobCards()
void ServiceManagementService::purchaseComboPackage(const std::string& comboPackageID, const std::string& vehicleNumber, const std::string& vehicleBrand, const std::string& vehicleModel)
{
util::FileManager<JobCard> jobCardFileManager(config::file::JOBCARD_FILE);
auto& jobCards = m_dataStore.getJobCards();
jobCardFileManager.save(jobCards);
}
/*
Function: loadObservers
Description: Loads observer IDs from persistent storage and attaches corresponding
users as observers to the ServiceManagementService.
Parameters:
- None
Returns:
- void
Throws:
- std::runtime_error if an observer ID is invalid (not found in datastore)
*/
void ServiceManagementService::loadObservers()
{
util::loadObservers(config::file::SERVICEMANAGEMENTOBSERVERS, this, m_dataStore);
}
/*
Function: saveObservers
Description: Saves the current observer IDs of the ServiceManagementService
to persistent storage for future retrieval.
Parameters:
- None
Returns:
- void
*/
void ServiceManagementService::saveObservers()
{
util::saveObservers(config::file::SERVICEMANAGEMENTOBSERVERS, this);
AuthenticationManagementService m_authenticationManagementService;
auto authenticatedUser = m_authenticationManagementService.getAuthenticatedUser();
if (authenticatedUser == nullptr)
{
throw std::runtime_error("No user is currently logged in!");
}
auto& comboPackagesMap = m_dataStore.getComboPackages();
auto& serviceBookingMap = m_dataStore.getServiceBookings();
int comboPackageIndex = comboPackagesMap.find(comboPackageID);
if (comboPackageIndex == -1)
{
throw std::runtime_error("Combo Package not found!");
}
const ComboPackage* comboPackage = comboPackagesMap[comboPackageID];
util::Map<std::string, Service*> selectedServices = comboPackage->getServices();
ServiceBooking* serviceBooking = Factory::getObject<ServiceBooking>(util::ServiceJobStatus::STARTED, selectedServices, authenticatedUser->getId(), authenticatedUser, vehicleNumber, vehicleBrand, vehicleModel, comboPackage->getDiscountPercentage());
if (serviceBooking == nullptr)
{
throw std::runtime_error("Failed to create combo package service booking");
}
serviceBookingMap[serviceBooking->getId()] = serviceBooking;
sendNotification(authenticatedUser,
"Combo Package Service Booking succeeded",
"Your service booking for the combo package has been successfully placed with ID " + serviceBooking->getId());
}
@@ -1,3 +1,11 @@
/*
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
#include <string>
#include "Map.h"
@@ -14,7 +22,6 @@ class ServiceManagementService : public NotificationManagementService
private:
DataStore& m_dataStore;
static util::Map<std::string, User*> m_observers;
util::Vector<std::string> getObserverIDs() override;
public:
ServiceManagementService() : m_dataStore(DataStore::getInstance()) {}
util::Map<std::string, Service*> getServices();
@@ -35,14 +42,4 @@ public:
void sendNotification(User* user, const std::string& title, const std::string& message) override;
void attach(User* user) override;
void detach(User* user) override;
void loadServices();
void saveServices();
void loadComboPackages();
void saveComboPackages();
void loadServiceBookings();
void saveServiceBookings();
void loadJobCards();
void saveJobCards();
void loadObservers();
void saveObservers();
};
@@ -1,73 +1,112 @@
#include "UserManagementService.h"
#include "FileManager.h"
/*
File: UserManagementService.cpp
Description: Implementation file containing the method definitions of the
UserManagementService class, including user creation, updates,
and ensuring an admin account exists.
Author: Trenser
Date:19-May-2026
*/
#include <stdexcept>
#include "User.h"
#include "Notification.h"
#include "Enums.h"
#include "Config.h"
#include "UserManagementService.h"
#include "ServiceManagementService.h"
#include "PaymentManagementService.h"
#include "InventoryManagementService.h"
#include "Factory.h"
/*
Function: loadUsers
Description: Loads users and notifications from persistent storage into the datastore.
Validates that each notifications recipient exists and attaches the
notification to the corresponding user.
Parameters:
- None
Returns:
- void
Throws:
- std::runtime_error if a notification recipient user ID is invalid
Function: ensureAdminExists
Description: Ensures that at least one admin user exists in the system.
If no admin is found, creates a default admin user using
configuration constants.
Parameter: None
Return type: void
*/
void UserManagementService::loadUsers()
void UserManagementService::ensureAdminExists()
{
util::FileManager<User> userFileManager(config::file::USER_FILE);
util::FileManager<Notification> notificationFileManager(config::file::NOTIFICATION_FILE);
auto& users = m_dataStore.getUsers();
auto usersMap = userFileManager.load();
auto notificationsMap = notificationFileManager.load();
int numberOfUsers = usersMap.getSize();
int numberOfNotifications = notificationsMap.getSize();
for (int index = 0; index < numberOfUsers; index++)
auto& usersMap = m_dataStore.getUsers();
int usersMapSize = usersMap.getSize();
bool isAdminFound = false;
for (int index = 0; index < usersMapSize; index++)
{
users[usersMap.getKeyAt(index)] = usersMap.getValueAt(index);
User* user = usersMap.getValueAt(index);
if (user && user->getUserType() == util::UserType::ADMIN)
{
isAdminFound = true;
break;
}
for (int index = 0; index < numberOfNotifications; index++)
{
Notification* notification = notificationsMap.getValueAt(index);
const std::string& recipientUserId = notification->getRecipientUserId();
int userIndex = users.find(recipientUserId);
if (userIndex == -1)
{
throw std::runtime_error("Invalid recipient user ID");
}
User* user = users.getValueAt(userIndex);
user->addNotification(notification);
if (!isAdminFound)
{
createUser(
config::admin::DEFAULT_ADMIN_USERNAME,
config::admin::DEFAULT_ADMIN_NAME,
config::admin::DEFAULT_ADMIN_PASSWORD,
config::admin::DEFAULT_ADMIN_EMAIL,
config::admin::DEFAULT_ADMIN_PHONE,
util::UserType::ADMIN);
}
}
/*
Function: saveUsers
Description: Saves users and their notifications from the datastore to persistent storage.
Collects notifications from all users into a single map before saving.
Parameters:
- None
Returns:
- void
Function: createUser
Description: Creates a new user with the provided details. Validates that
the username is unique, then attaches the user to relevant
management services (payment, service, inventory).
Parameter: const std::string& username - users username
const std::string& name - users name
const std::string& password - users password
const std::string& email - users email address
const std::string& phone - users phone number
util::UserType type - type of user (ADMIN, CUSTOMER, TECHNICIAN)
Return type: void
*/
void UserManagementService::saveUsers()
void UserManagementService::createUser(const std::string& username, const std::string& name, const std::string& password, const std::string& email, const std::string& phone, util::UserType type)
{
util::FileManager<User> userFileManager(config::file::USER_FILE);
util::FileManager<Notification> notificationFileManager(config::file::NOTIFICATION_FILE);
auto& users = m_dataStore.getUsers();
util::Map<std::string, Notification*> notifications;
for (int userIndex = 0; userIndex < users.getSize(); userIndex++)
InventoryManagementService inventoryManagementService;
PaymentManagementService paymentManagementService;
ServiceManagementService serviceManagementService;
auto& usersMap = m_dataStore.getUsers();
int index = usersMap.findIf(
[&](const std::string&, User* user)
{
User* user = users.getValueAt(userIndex);
auto& userNotifications = user->getNotifications();
for (int notificationIndex = 0; notificationIndex < userNotifications.getSize(); notificationIndex++)
return user->getUserName() == username;
}
);
if (index != -1)
{
notifications[userNotifications.getKeyAt(notificationIndex)] =
userNotifications.getValueAt(notificationIndex);
throw std::runtime_error("Username already exists");
}
User* newUser = Factory::getObject<User>(username, password, name, phone, email, type);
usersMap.insert(newUser->getId(), newUser);
paymentManagementService.attach(newUser);
serviceManagementService.attach(newUser);
if (newUser->getUserType() == util::UserType::ADMIN)
{
inventoryManagementService.attach(newUser);
}
userFileManager.save(users);
notificationFileManager.save(notifications);
}
/*
Function: updateUserDetails
Description: Updates the email and phone details of an existing user.
Throws an exception if the user does not exist.
Parameter: const std::string& userID - ID of the user to update
const std::string& email - new email address
const std::string& phone - new phone number
Return type: void
*/
void UserManagementService::updateUserDetails(const std::string& userID, const std::string& email, const std::string& phone)
{
auto& usersMap = m_dataStore.getUsers();
int index = usersMap.find(userID);
if (index == -1)
{
throw std::runtime_error("User does not exist!");
}
User* user = usersMap.getValueAt(index);
user->setEmail(email);
user->setPhone(phone);
}
@@ -1,3 +1,11 @@
/*
File: UserManagementService.h
Description: Header file declaring the UserManagementService class, which manages
user creation, updates, retrieval, removal, notifications, and ensures
the existence of an admin account.
Author: Trenser
Date:19-May-2026
*/
#pragma once
#include <string>
#include "Map.h"
@@ -13,7 +21,7 @@ private:
DataStore& m_dataStore;
public:
UserManagementService() : m_dataStore(DataStore::getInstance()) {}
void createUser(const std::string& username, const std::string& password, const std::string& email, const std::string& phone, util::UserType type);
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 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::UserType type);
@@ -21,6 +29,5 @@ public:
void removeUser(const std::string& userID);
util::Vector<Notification*> getUserNotifications(const std::string& userID);
void deleteNotification(const std::string& notificationID, const std::string& userID);
void loadUsers();
void saveUsers();
void ensureAdminExists();
};
@@ -1,19 +1,21 @@
/*
File: Config.h
Description: Header file declaring configuration constants for the Vehicle Service System.
Includes default admin account details such as username, name, password,
email, and phone number.
Author: Trenser
Date:19-May-2026
*/
#pragma once
namespace config
{
namespace file
namespace admin
{
constexpr const char* INVENTORYITEM_FILE = "files/InventoryItem.csv";
constexpr const char* USER_FILE = "files/User.csv";
constexpr const char* NOTIFICATION_FILE = "files/Notification.csv";
constexpr const char* SERVICE_FILE = "files/Service.csv";
constexpr const char* COMBOPACKAGE_FILE = "files/ComboPackage.csv";
constexpr const char* SERVICEBOOKING_FILE = "files/ServiceBooking.csv";
constexpr const char* JOBCARD_FILE = "files/JobCard.csv";
constexpr const char* INVOICE_FILE = "files/Invoice.csv";
constexpr const char* SERVICEMANAGEMENTOBSERVERS = "files/ServiceManagementObservers.csv";
constexpr const char* PAYMENTMANAGEMENTOBSERVERS = "files/PaymentManagementObservers.csv";
constexpr const char* INVENTORYMANAGEMENTOBSERVERS = "files/InventoryManagementObservers.csv";
constexpr const char* DEFAULT_ADMIN_USERNAME = "admin";
constexpr const char* DEFAULT_ADMIN_NAME = "admin";
constexpr const char* DEFAULT_ADMIN_PASSWORD = "";
constexpr const char* DEFAULT_ADMIN_EMAIL = "admin@vss";
constexpr const char* DEFAULT_ADMIN_PHONE = "0000000000";
}
}
@@ -147,9 +147,9 @@ namespace util
switch (status)
{
case State::ACTIVE:
return "ACTIVE";
return "STARTED";
case State::INACTIVE:
return "INACTIVE";
return "COMPLETED";
}
throw std::invalid_argument("Invalid State");
}
@@ -160,7 +160,7 @@ namespace util
{
return State::ACTIVE;
}
if (value == "INACTIVE")
if (value == "COMPLETED")
{
return State::INACTIVE;
}
@@ -1,79 +0,0 @@
/*
File: FileHelper.h
Description: Provides utility functions for loading and saving records
from and to CSV-like text files. Ensures files are created
if missing and supports simple record persistence.
Author: Trenser
Date: 22-May-2026
*/
#pragma once
#include <fstream>
#include <string>
#include <stdexcept>
#include "Vector.h"
namespace util
{
/*
Function: loadRecords
Description: Loads records from a given file path into a vector of strings.
Skips the header line if present. Creates the file if it does not exist.
Parameters:
- filePath: const std::string&, path to the file
Returns:
- util::Vector<std::string>: Vector containing all records (excluding header)
Throws:
- None (creates file if missing)
*/
inline util::Vector<std::string> loadRecords(const std::string& filePath)
{
util::Vector<std::string> records;
std::ifstream file(filePath);
if (!file.is_open())
{
std::ofstream newFile(filePath);
newFile.close();
file.open(filePath);
}
std::string line;
bool isHeader = true;
while (std::getline(file, line))
{
if (isHeader)
{
isHeader = false;
continue;
}
records.push_back(line);
}
return records;
}
/*
Function: saveRecords
Description: Saves records to a given file path. Overwrites existing content
and writes a header line followed by all records.
Parameters:
- filePath: const std::string&, path to the file
- records: const util::Vector<std::string>&, vector of records to save
Returns:
- void
Throws:
- std::runtime_error if the file cannot be opened for writing
*/
inline void saveRecords(const std::string& filePath, const util::Vector<std::string>& records)
{
std::ofstream file(filePath, std::ios::trunc);
if (!file.is_open())
{
throw std::runtime_error("Failed to open file " + filePath);
}
file << "Values" << '\n';
int numberOfRecords = records.getSize();
for (int index = 0; index < numberOfRecords; index++)
{
file << records[index] << '\n';
}
}
}
@@ -1,116 +0,0 @@
/*
File: FileManager.h
Description: Declares and implements a generic FileManager template class for
loading and saving objects to and from files. Uses serialization
and deserialization methods defined in the object type T.
Provides persistence support for system entities such as Users,
Services, InventoryItems, etc.
Author: Trenser
Date: 22-May-2026
*/
#pragma once
#include <stdexcept>
#include <fstream>
#include "Vector.h"
#include "Map.h"
namespace util
{
template <typename T> using objects = util::Map<std::string, T*>;
template <typename T>
class FileManager
{
private:
std::string m_filePath;
public:
FileManager() : m_filePath("") {}
FileManager(const std::string& filePath) : m_filePath(filePath) {}
objects<T> load();
void save(const objects<T>&);
};
/*
Function: load
Description: Loads records from the file into a map of objects.
Skips the header line, deserializes each record into an object of type T,
and stores them in a map keyed by object ID.
Parameters:
- None
Returns:
- util::Map<std::string, T*> containing deserialized objects
Throws:
- std::runtime_error if deserialization fails for any record
*/
template <typename T>
objects<T> FileManager<T>::load()
{
objects<T> records;
std::ifstream file(m_filePath);
if (!file.is_open())
{
std::ofstream newFile(m_filePath);
newFile.close();
file.open(m_filePath);
}
util::Vector<std::string> lines;
std::string line;
while (std::getline(file, line))
{
lines.push_back(line);
}
int numberOfLines = lines.getSize();
bool isHeader = true;
for (int lineIndex = 0; lineIndex < numberOfLines; lineIndex++)
{
const auto& record = lines[lineIndex];
if (isHeader)
{
isHeader = false;
continue;
}
auto object = T::deserialize(record);
if (!object)
{
throw std::runtime_error("Failed to deserialize record");
}
records[object->getId()] = object;
}
return records;
}
/*
Function: save
Description: Saves records to the file. Serializes each object of type T into a string,
writes a header line, and then writes all serialized records to the file.
Parameters:
- records: const util::Map<std::string, T*>&, map of objects to save
Returns:
- void
Throws:
- std::runtime_error if the file cannot be opened for writing
*/
template <typename T>
void FileManager<T>::save(const objects<T>& records)
{
util::Vector<std::string> lines;
lines.push_back(T::getHeaders());
int numberOfRecords = records.getSize();
for (int recordIndex = 0; recordIndex < numberOfRecords; recordIndex++)
{
const auto& record = records.getValueAt(recordIndex);
lines.push_back(record->serialize());
}
std::ofstream file(m_filePath, std::ios::trunc);
if (!file.is_open())
{
throw std::runtime_error("Failed to open file " + m_filePath);
}
int numberOfLines = lines.getSize();
for (int lineIndex = 0; lineIndex < numberOfLines; lineIndex++)
{
file << lines[lineIndex] << '\n';
}
}
}
@@ -34,7 +34,7 @@ namespace util
/*
* Function: read
* Description: Reads a line of text input from console into a string and cleans it up.
* Description: Reads a line of text input from console into a string.
* Parameters:
* value - reference to a string where the input will be stored
* Returns:
@@ -43,15 +43,6 @@ namespace util
inline void read(std::string& value)
{
std::getline(std::cin >> std::ws, value);
std::string cleanedValue;
for (int index = 0; index < value.length(); index++)
{
if (value[index] != ',')
{
cleanedValue += value[index];
}
}
value = cleanedValue;
}
/*
@@ -1,36 +0,0 @@
/*
File: StringHelper.h
Description: Provides utility functions for extracting numeric values from strings.
Useful for parsing IDs, codes, or mixed alphanumeric inputs where
digits need to be isolated and converted into integers.
Author: Trenser
Date: 22-May-2026
*/
#include <cctype>
#include <string>
namespace util
{
/*
Function: extractNumber
Description: Extracts all digits from the given string and converts them into an integer.
Ignores non-digit characters. For example, "abc123xyz" returns 123.
Parameters:
- input: const std::string&, the input string containing digits and/or other characters
Returns:
- int: The integer value formed by concatenating all digits in the string
*/
inline int extractNumber(const std::string& input)
{
int result = 0;
for (char character : input)
{
if (std::isdigit(static_cast<unsigned char>(character)))
{
result = result * 10 + (character - '0');
}
}
return result;
}
}
@@ -1,63 +1,49 @@
/*
File: ObserversHelper.h
Description: Provides utility functions for loading and saving observers
in the notification management system. Ensures that observer
IDs are validated against existing users in the datastore
before attaching them to the notification service.
File: Utility.h
Description: Header file declaring utility functions used across the system,
including cost calculation for services and combo packages.
Author: Trenser
Date: 22-May-2026
Date:19-May-2026
*/
#pragma once
#include "NotificationManagementService.h"
#include "FileHelper.h"
#include "DataStore.h"
#include "Service.h"
#include "InventoryItem.h"
namespace util
/*
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)
{
/*
Function: loadObservers
Description: Loads observer IDs from a file and attaches the corresponding users
to the notification management service. Validates that each observer ID
exists in the datastore before attaching.
Parameters:
- filePath: const std::string&, path to the file containing observer IDs
- service: NotificationManagementService*, pointer to the notification service
- dataStore: DataStore&, reference to the datastore containing users
Returns:
- void
Throws:
- std::runtime_error if an observer ID is invalid (not found in datastore)
*/
inline void loadObservers(const std::string& filePath, NotificationManagementService* service, DataStore& dataStore)
double cost = 0;
auto& requiredInventoryItems = service->getRequiredInventoryItems();
int requiredInventoryItemsSize = requiredInventoryItems.getSize();
for (int index = 0; index < requiredInventoryItemsSize; index++)
{
auto observerIDs = util::loadRecords(filePath);
auto& users = dataStore.getUsers();
for (int index = 0; index < observerIDs.getSize(); index++)
{
const std::string& observerID = observerIDs[index];
int userIndex = users.find(observerID);
if (userIndex == -1)
{
throw std::runtime_error("Invalid Observer ID");
}
service->attach(users.getValueAt(userIndex));
}
}
/*
Function: saveObservers
Description: Saves the current observer IDs from the notification management service
to a file for persistence.
Parameters:
- filePath: const std::string&, path to the file where observer IDs will be saved
- service: NotificationManagementService*, pointer to the notification service
Returns:
- void
*/
inline void saveObservers(const std::string& filePath, NotificationManagementService* service)
{
auto observerIDs = service->getObserverIDs();
util::saveRecords(filePath, observerIDs);
cost += requiredInventoryItems.getValueAt(index)->getPrice();
}
return cost;
}
/*
Function: calculateComboServiceEstimatedCost
Description: Calculates the estimated total cost of a combo package by summing
the labor and parts costs of all services included in the package.
Parameter: const ComboPackage* comboPackage - pointer to the combo package object
Return type: double - estimated total cost of the combo package
*/
inline double calculateComboServiceEstimatedCost(const ComboPackage* comboPackage)
{
double cost = 0;
auto& services = comboPackage->getServices();
int servicesSize = services.getSize();
for (int index = 0; index < servicesSize; index++)
{
const Service* service = services.getValueAt(index);
cost += calculatePartsCost(service) + service->getLaborCost();
}
return cost;
}
@@ -1,21 +1,54 @@
/*
File: CustomerMenu.cpp
Description: Implementation file containing the method definitions of the
CustomerMenu class, including menu handling, service selection,
combo package booking, profile updates, and password management.
Author: Trenser
Date:19-May-2026
*/
#include <iomanip>
#include "CustomerMenu.h"
#include "Service.h"
#include "InventoryItem.h"
#include "ComboPackage.h"
#include "Service.h"
#include "InputHelper.h"
#include "OutputHelper.h"
#include "Validator.h"
#include "Vector.h"
#include "Utility.h"
#include "Map.h"
/*
Function: showMenu
Description: Displays the customer menu and handles user input until logout is selected.
Parameter: None
Return type: void
*/
void CustomerMenu::showMenu()
{
bool isMenuActive = true;
while (isMenuActive)
while (true)
{
try
{
int choice;
util::clear();
std::cout << "" << std::endl;
std::cout << "Customer Menu"
<< "\n1. Select a service"
<< "\n2. Select a combo package"
<< "\n3. Update Profile"
<< "\n4. Change Password"
<< "\n5. View Service History"
<< "\n6. Complete Payments"
<< "\n7. View Invoices"
<< "\n8. View Notifications"
<< "\n9. Configure Notifications"
<< "\n10. Logout"
<< "\nEnter a choice: ";
util::read(choice);
if (!handleOperation(choice))
{
isMenuActive = false;
break;
}
}
catch (const std::exception& e)
@@ -26,29 +59,277 @@ void CustomerMenu::showMenu()
}
}
/*
Function: handleOperation
Description: Executes the corresponding customer operation based on the selected menu choice.
Parameter: int choice - selected menu option
Return type: bool - true if menu continues, false if logout
*/
bool CustomerMenu::handleOperation(int choice)
{
switch (choice)
{
case 1:
selectService();
break;
case 2:
selectComboPackage();
break;
case 3:
updateDetails();
break;
case 4:
changePassword();
break;
case 5:
viewServiceHistory();
break;
case 6:
completePayments();
break;
case 7:
viewInvoices();
break;
case 8:
viewNotifications();
break;
case 9:
configureNotifications();
break;
case 10:
logout();
return false;
default:
std::cout << "Enter a valid choice!" << std::endl;
util::pressEnter();
}
return true;
}
/*
Function: logout
Description: Logs out the currently authenticated customer user.
Parameter: None
Return type: void
*/
void CustomerMenu::logout()
{
m_controller.logout();
}
/*
Function: changePassword
Description: Allows the customer to change their password after validation.
Parameter: None
Return type: void
*/
void CustomerMenu::changePassword()
{
std::string newPassword;
util::clear();
std::cout << "Enter new password: ";
util::read(newPassword);
m_controller.changePassword(newPassword);
if (!util::isPasswordValid(newPassword))
{
std::cout << "Error: Password is not strong enough!";
util::pressEnter();
return;
}
std::cout << "Password changed successfully";
util::pressEnter();
}
/*
Function: updateDetails
Description: Allows the customer to update their email and phone number after validation.
Parameter: None
Return type: void
*/
void CustomerMenu::updateDetails()
{
std::string email, phone;
util::clear();
std::cout << "Enter new email: ";
util::read(email);
if (!util::isEmailValid(email))
{
std::cout << "Error: Email is invalid!";
util::pressEnter();
return;
}
std::cout << "Enter new phone: ";
util::read(phone);
if (!util::isPhoneNumberValid(phone))
{
std::cout << "Error: Phone number is invalid!";
util::pressEnter();
return;
}
m_controller.updateUserDetails(email, phone);
std::cout << "Profile details updated successfully";
util::pressEnter();
}
/*
Function: selectServiceFromServices
Description: Displays active services and allows the customer to select one by index.
Parameter: const util::Map<std::string, const Service*>& services - list of services
Return type: const Service* - selected service
*/
static const Service* selectServiceFromServices(const util::Map<std::string, const Service*>& services)
{
util::Map<int, const Service*> activeServicesMap;
int currentIndex = 1;
int userInputIndex;
std::cout << std::left
<< std::setw(10) << "Index"
<< std::setw(15) << "Service ID"
<< std::setw(25) << "Service Name"
<< std::setw(15) << "Estimated Cost"
<< std::endl;
for (int index = 0; index < services.getSize(); index++)
{
const Service* currentService = services.getValueAt(index);
if (currentService->getState() != util::State::ACTIVE)
{
continue;
}
activeServicesMap.insert(currentIndex, currentService);
double partsCost = calculatePartsCost(currentService);
std::cout << std::left
<< std::setw(10) << currentIndex
<< std::setw(15) << currentService->getId()
<< std::setw(25) << currentService->getName()
<< std::setw(15) << (currentService->getLaborCost() + partsCost)
<< std::endl;
currentIndex++;
}
if (activeServicesMap.getSize() == 0)
{
std::cout << "No active services available." << std::endl;
return nullptr;
}
std::cout << "Enter service index: ";
util::read(userInputIndex);
if (activeServicesMap.find(userInputIndex) == -1)
{
std::cout << "Invalid service index." << std::endl;
return nullptr;
}
return activeServicesMap[userInputIndex];
}
/*
Function: selectService
Description: Allows the customer to select a service, provide vehicle details,
and book the service through the controller.
Parameter: None
Return type: void
*/
void CustomerMenu::selectService()
{
std::string vehicleNumber, vehicleBrand, vehicleModel;
auto services = m_controller.getServices();
util::Vector<std::string> selectedServices;
util::clear();
const Service* selectedService = selectServiceFromServices(services);
if (selectedService == nullptr)
{
std::cout << "Failed to book service!";
util::pressEnter();
return;
}
selectedServices.push_back(selectedService->getId());
util::clear();
std::cout << "Enter vehicle number: ";
util::read(vehicleNumber);
std::cout << "Enter vehicle brand: ";
util::read(vehicleBrand);
std::cout << "Enter vehicle model: ";
util::read(vehicleModel);
m_controller.purchaseService(selectedServices, vehicleNumber, vehicleBrand, vehicleModel);
std::cout << "Service has been booked successfully";
util::pressEnter();
}
/*
Function: selectComboPackageFromPackages
Description: Displays active combo packages and allows the customer to select one by index.
Parameter: const util::Map<std::string, const ComboPackage*>& comboPackages - list of combo packages
Return type: const ComboPackage* - selected combo package
*/
static const ComboPackage* selectComboPackageFromPackages(const util::Map<std::string, const ComboPackage*>& comboPackages)
{
util::Map<int, const ComboPackage*> activeComboPackages;
int currentIndex = 1;
int userInputIndex;
std::cout << std::left
<< std::setw(10) << "Index"
<< std::setw(15) << "Combo Package ID"
<< std::setw(15) << "Combo Package Name"
<< std::setw(15) << "Estimate Cost"
<< std::endl;
for (int index = 0; index < comboPackages.getSize(); index++)
{
const ComboPackage* currentComboPackage = comboPackages.getValueAt(index);
if (currentComboPackage->getState() != util::State::ACTIVE)
{
continue;
}
activeComboPackages.insert(currentIndex, currentComboPackage);
std::cout << std::left
<< std::setw(10) << currentIndex
<< std::setw(15) << currentComboPackage->getId()
<< std::setw(25) << currentComboPackage->getPackageName()
<< std::setw(15) << calculateComboServiceEstimatedCost(currentComboPackage)
<< std::endl;
currentIndex++;
}
if (activeComboPackages.getSize() == 0)
{
std::cout << "No active combo packages available." << std::endl;
return nullptr;
}
std::cout << "Enter combo package index: ";
util::read(userInputIndex);
if (activeComboPackages.find(userInputIndex) == -1)
{
std::cout << "Invalid combo package index." << std::endl;
return nullptr;
}
return activeComboPackages[userInputIndex];
}
/*
Function: selectComboPackage
Description: Allows the customer to select a combo package, provide vehicle details,
and book the package through the controller.
Parameter: None
Return type: void
*/
void CustomerMenu::selectComboPackage()
{
std::string vehicleNumber, vehicleBrand, vehicleModel;
auto comboPackages = m_controller.getComboPackages();
util::clear();
const ComboPackage* selectedComboPackage = selectComboPackageFromPackages(comboPackages);
if (selectedComboPackage == nullptr)
{
std::cout << "Failed to book combo package!";
util::pressEnter();
return;
}
util::clear();
std::cout << "Enter vehicle number: ";
util::read(vehicleNumber);
std::cout << "Enter vehicle brand: ";
util::read(vehicleBrand);
std::cout << "Enter vehicle model: ";
util::read(vehicleModel);
m_controller.purchaseComboPackage(selectedComboPackage->getId(), vehicleNumber, vehicleBrand, vehicleModel);
std::cout << "Combo Package has been booked successfully";
util::pressEnter();
}
void CustomerMenu::viewServiceHistory()
@@ -1,3 +1,12 @@
/*
File: CustomerMenu.h
Description: Header file declaring the CustomerMenu class, which provides
customer operations such as selecting services, booking combo
packages, updating profile details, managing payments, viewing
invoices, and configuring notifications.
Author: Trenser
Date:19-May-2026
*/
#pragma once
#include "Controller.h"
@@ -0,0 +1,62 @@
/*
File: MenuHelper.h
Description: Header file declaring the MenuHelper class, which provides
utility functions for menu-driven operations such as
notification selection and display.
Author: Trenser
Date:19-May-2026
*/
#pragma once
#include <string>
#include <iomanip>
#include "Notification.h"
#include "Map.h"
#include "InputHelper.h"
#include "OutputHelper.h"
/*
Function: selectNotification
Description: Displays a list of notifications with index, ID, title, and timestamp.
Allows the user to select a notification by index. Returns the selected
notification or nullptr if the selection is invalid.
Parameter: const util::Vector<const Notification*>& notifications - list of notifications
Return type: const Notification* - pointer to the selected notification
*/
inline const Notification* selectNotification(const util::Vector<const Notification*>& notifications)
{
if (notifications.getSize() == 0)
{
std::cout << "No notifications available." << std::endl;
return nullptr;
}
std::cout << std::left
<< std::setw(6) << "Index"
<< std::setw(15) << "ID"
<< std::setw(30) << "Title"
<< std::setw(25) << "Timestamp"
<< std::endl;
int currentIndex = 1;
for (int iterator = 0; iterator < notifications.getSize(); iterator++)
{
const Notification* currentNotification = notifications[iterator];
if (currentNotification)
{
std::cout << std::left
<< std::setw(6) << currentIndex
<< std::setw(15) << currentNotification->getId()
<< std::setw(30) << currentNotification->getTitle()
<< std::setw(25) << currentNotification->getCreatedAt().toString()
<< std::endl;
currentIndex++;
}
}
int selectedIndex;
std::cout << "Select notification: ";
util::read(selectedIndex);
if (selectedIndex < 1 || selectedIndex > notifications.getSize())
{
std::cout << "Invalid selection." << std::endl;
return nullptr;
}
return notifications[selectedIndex - 1];
}
@@ -1,10 +1,27 @@
/*
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 "InputHelper.h"
#include "OutputHelper.h"
#include "Enums.h"
#include "User.h"
#include "Validator.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()
{
m_controller.loadSystemData();
bool isMenuActive = true;
while (isMenuActive)
{
@@ -25,9 +42,14 @@ void UserInterface::run()
util::pressEnter();
}
}
m_controller.saveSystemData();
}
/*
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)
{
switch (choice)
@@ -48,12 +70,90 @@ bool UserInterface::handleOperation(int choice)
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()
{
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";
}
}
/*
Function: registerCustomer
Description: Registers a new customer by collecting and validating details such as
username, name, email, password, and phone number. Delegates creation
to the controller.
Parameter: None
Return type: void
*/
void UserInterface::registerCustomer()
{
std::string username, name, email, phone, password;
util::clear();
std::cout << "Enter username: ";
util::read(username);
std::cout << "Enter name: ";
util::read(name);
std::cout << "Enter email: ";
util::read(email);
if (!util::isEmailValid(email))
{
std::cout << "Error: Email is invalid!";
util::pressEnter();
return;
}
std::cout << "Enter password: ";
util::read(password);
if (!util::isPasswordValid(password))
{
std::cout << "Error: Password is invalid!";
util::pressEnter();
return;
}
std::cout << "Enter phone: ";
util::read(phone);
if (!util::isPhoneNumberValid(phone))
{
std::cout << "Error: Phone number is invalid!";
util::pressEnter();
return;
}
m_controller.createCustomer(username, name, password, email, phone);
std::cout << "Registration is successful";
util::pressEnter();
}
@@ -1,3 +1,12 @@
/*
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
#include "Controller.h"
#include "AdminMenu.h"