diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.cpp index eff3229..3db950c 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.cpp @@ -1,7 +1,24 @@ +/* +File: Trenser.VehicleServiceSystem.cpp +Description: Entry point for the Vehicle Service Management System. + Initializes the UserInterface and starts the application loop. +Author: Trenser +Date: 19-May-2026 +*/ + #include "UserInterface.h" +/* +Function: main +Description: The main entry point of the application. + Creates a UserInterface object and invokes the run method to start the system. +Parameters: + - None +Returns: + - int: Exit status code (0 for successful execution). +*/ int main() { UserInterface userInterface; userInterface.run(); -} +} \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj index fd7c056..8627061 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj @@ -171,10 +171,14 @@ + + + + diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters index 701e0c5..73b9291 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters @@ -233,6 +233,18 @@ Header Files\Models + + Header Files\Utilities + + + Header Files\Utilities + + + Header Files\Utilities + + + Header Files\Utilities + Header Files\Utilities diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp index 058f0d2..f1ca400 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp @@ -1,39 +1,113 @@ +/* +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 "ComboPackage.h" #include "Controller.h" +#include "Enums.h" #include "InventoryItem.h" +#include "Invoice.h" +#include "JobCard.h" #include "Service.h" #include "ServiceBooking.h" -#include "JobCard.h" #include "User.h" -#include "Invoice.h" +#include +/* +Function: login +Description: Authenticates a user by delegating to the authentication management service. +Parameter: const std::string& username - user’s username + const std::string& password - user’s 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 - customer’s username + const std::string& name - customer’s name + const std::string& password - customer’s password + const std::string& email - customer’s email + const std::string& phone - customer’s 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: createTechnician +Description: Creates a new technician account with provided details by + delegating to the user management service. +Parameter: const std::string& username - technician's username + const std::string& password - technician's password + const std::string& email - technician's email address + const std::string& phoneNumber - technician's phone number +Return type: void +*/ +void Controller::createTechnician(const std::string& username, const std::string& name, const std::string& password, const std::string& email, const std::string& phoneNumber) { + m_userManagementService.createUser(username, name, password, email, phoneNumber, util::UserType::TECHNICIAN); } +/* +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); } /* @@ -55,36 +129,120 @@ util::Map Controller::getServices() return readOnlyServices; } +/* +Function: getComboPackages +Description: Retrieves all available combo packages from the service + management service and constructs a read-only map. +Parameter: None +Return type: util::Map +*/ util::Map Controller::getComboPackages() { - return util::Map(); + util::Map currentAvailableComboPackages = m_serviceManagementService.getComboPackages(); + util::Map readOnlyComboPackages; + for (int iterator = 0; iterator < currentAvailableComboPackages.getSize(); iterator++) + { + ComboPackage* currentComboPackage = currentAvailableComboPackages.getValueAt(iterator); + if (currentComboPackage) + { + readOnlyComboPackages.insert(currentComboPackage->getId(), currentComboPackage); + } + } + return readOnlyComboPackages; } +/* +Function: purchaseService +Description: Purchases one or more services for a vehicle by delegating to the service management service. +Parameter: const util::Vector& 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& 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); } +/* +Function: getInventoryItems +Description: Retrieves all inventory items from the inventory management service + and constructs a read-only map for external use. +Parameter: None +Return type: util::Map +*/ util::Map Controller::getInventoryItems() { - util::Map dummyMap; - return dummyMap; + auto inventoryItems = m_inventoryManagementService.getInventoryItems(); + util::Map readOnlyInventoryItems; + int inventoryItemsMapSize = inventoryItems.getSize(); + for (int index = 0; index < inventoryItemsMapSize; index++) + { + readOnlyInventoryItems.insert(inventoryItems.getKeyAt(index), inventoryItems.getValueAt(index)); + } + return readOnlyInventoryItems; } +/* +Function: getInventoryItem +Description: Retrieves a specific inventory item by its ID from the inventory management service. +Parameter: const std::string& inventoryItemID - ID of the inventory item +Return type: const InventoryItem* +*/ const InventoryItem* Controller::getInventoryItem(const std::string& inventoryItemID) { - return nullptr; + return m_inventoryManagementService.getInventoryItem(inventoryItemID); } +/* +Function: addInventoryItem +Description: Adds a new inventory item with specified details to the inventory management service. +Parameter: const std::string& partName - name of the part + int quantity - quantity of the part + double price - price of the part +Return type: void +*/ void Controller::addInventoryItem(const std::string& partName, int quantity, double price) { + m_inventoryManagementService.addInventoryItem(partName, quantity, price); } +/* +Function: removeInventoryItem +Description: Removes an inventory item from the inventory management service by its ID. +Parameter: const std::string& inventoryItemID - ID of the inventory item +Return type: void +*/ void Controller::removeInventoryItem(const std::string& inventoryItemID) { + m_inventoryManagementService.removeInventoryItem(inventoryItemID); +} + +/* +Function: addInventoryItemStock +Description: Adds stock to an existing inventory item in the inventory management service. +Parameter: const std::string& selectedItemId - ID of the inventory item + int quantity - quantity to add +Return type: void +*/ +void Controller::addInventoryItemStock(const std::string& selectedItemId, int quantity) +{ + m_inventoryManagementService.addInventoryItemStock(selectedItemId, quantity); } /* @@ -125,9 +283,22 @@ util::Map Controller::getServiceBookingsByUs return readOnlyServiceBookingsByUserMap; } +/* +Function: getUsers +Description: Retrieves all users from the user management service and + constructs a read-only map. +Parameter: None +Return type: util::Map +*/ util::Map Controller::getUsers() { - return util::Map(); + auto listOfUsers = m_userManagementService.getUsers(); + util::Map readOnlyUserList; + for (int iterator = 0; iterator < listOfUsers.getSize(); iterator++) + { + readOnlyUserList.insert(listOfUsers.getKeyAt(iterator), listOfUsers.getValueAt(iterator)); + } + return readOnlyUserList; } /* @@ -226,16 +397,49 @@ void Controller::completeJob(const std::string& jobID) m_serviceManagementService.completeJob(jobID); } +/* +Function: removeUser +Description: Removes a user by ID. Cancels associated service bookings + and technician jobs before removing the user from the system. +Parameter: const std::string& userID - ID of the user to remove +Return type: void +*/ void Controller::removeUser(const std::string& userID) { + User* user = m_userManagementService.getUser(userID); + if (!user) + { + throw std::runtime_error("Error User not Found.\n"); + } + m_serviceManagementService.cancelCustomerServiceBookings(userID); + m_serviceManagementService.cancelTechnicianJobs(userID); + m_userManagementService.removeUser(userID); } +/* +Function: createComboPackage +Description: Creates a new combo package with specified services and discount + percentage by delegating to the service management service. +Parameter: const std::string& name - name of the combo package + const util::Vector& serviceIDs - list of service IDs + double discountPercentage - discount percentage for the package +Return type: void +*/ void Controller::createComboPackage(const std::string& name, const util::Vector& serviceIDs, double discountPercentage) { + m_serviceManagementService.createComboPackage(name, serviceIDs, discountPercentage); } +/* +Function: removeComboPackage +Description: Removes a combo package by ID by delegating to the service + management service. +Parameter: const std::string& comboPackageID - ID of the combo package +Return type: void +*/ void Controller::removeComboPackage(const std::string& comboPackageID) { + m_serviceManagementService.removeComboPackage(comboPackageID); } /* @@ -274,19 +478,142 @@ void Controller::completePayment(const std::string& invoiceID, util::PaymentMode m_paymentManagementService.completePayment(invoiceID, paymentMode); } +/* +Function: getNotifications +Description: Retrieves all notifications for the currently authenticated user. + Converts them into a read-only vector before returning. +Parameters: None +Return type: util::Vector +*/ util::Vector Controller::getNotifications() { - return util::Vector(); + const User* authenticatedUser = m_authenticationManagementService.getAuthenticatedUser(); + if (!authenticatedUser) + { + throw std::runtime_error("No user is currently logged in!"); + } + auto notifications = m_userManagementService.getUserNotifications(authenticatedUser->getId()); + int numberOfNotifications = notifications.getSize(); + util::Vector readOnlyNotifications; + for (int index = 0; index < numberOfNotifications; index++) + { + readOnlyNotifications.push_back(notifications[index]); + } + return readOnlyNotifications; } +/* +Function: deleteNotification +Description: Deletes a specific notification for the currently authenticated user. +Parameters: + - notificationID: std::string, the unique identifier of the notification +Return type: void +*/ void Controller::deleteNotification(const std::string& notificationID) { + const User* authenticatedUser = m_authenticationManagementService.getAuthenticatedUser(); + if (!authenticatedUser) + { + throw std::runtime_error("No user is currently logged in!"); + } + m_userManagementService.deleteNotification(notificationID, authenticatedUser->getId()); } -void Controller::configureNotifications(const std::string& userID, bool paymentNotifications, bool serviceNotifications) +/* +Function: configureNotifications +Description: Configures notification preferences for the authenticated user. + Attaches or detaches the user from payment and service notifications. +Parameters: + - paymentNotifications: bool, enable/disable payment notifications + - serviceNotifications: bool, enable/disable service notifications +Return type: void +*/ +void Controller::configureNotifications(bool paymentNotifications, bool serviceNotifications) { + User* authenticatedUser = m_authenticationManagementService.getAuthenticatedUser(); + if (authenticatedUser) + { + if (paymentNotifications) + { + m_paymentManagementService.attach(authenticatedUser); + } + else + { + m_paymentManagementService.detach(authenticatedUser); + } + if (serviceNotifications) + { + m_serviceManagementService.attach(authenticatedUser); + } + else + { + m_serviceManagementService.detach(authenticatedUser); + } + } + else + { + throw std::runtime_error("No user is currently logged in!"); + } } +/* +Function: loadSystemData +Description: Loads all system data from persistent storage into memory. + Invokes the respective management services to load users, inventory items, services, + combo packages, service bookings, job cards, invoices, and observers. +Parameters: + - None +Returns: + - void +*/ +void Controller::loadSystemData() +{ + 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(); +} + +/* +Function: runSystemChecks +Description: Runs system checks to ensure critical configurations, such as verifying admin existence. +Parameter: None +Return type: void +*/ void Controller::runSystemChecks() { -} \ No newline at end of file + m_userManagementService.ensureAdminExists(); + m_inventoryManagementService.sendLowStockAlerts(); + m_paymentManagementService.sendPaymentReminders(); +} + diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h index 7a47874..e75ebd4 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h @@ -1,12 +1,21 @@ +/* +File: Controller.h +Description: Header file declaring the Controller class, which manages + user authentication, inventory, services, bookings, job cards, + invoices, and notifications in the system. +Author: Trenser +Date:19-May-2026 +*/ + #pragma once -#include "Map.h" #include -#include "Enums.h" -#include "PaymentManagementService.h" #include "AuthenticationManagementService.h" +#include "Enums.h" +#include "InventoryManagementService.h" +#include "Map.h" +#include "PaymentManagementService.h" #include "ServiceManagementService.h" #include "UserManagementService.h" -#include "InventoryManagementService.h" class Service; class ComboPackage; @@ -20,17 +29,18 @@ class Notification; class Controller { private: - AuthenticationManagementService m_authenticationManagementService; - PaymentManagementService m_paymentManagementService; - ServiceManagementService m_serviceManagementService; + AuthenticationManagementService m_authenticationManagementService; UserManagementService m_userManagementService; + ServiceManagementService m_serviceManagementService; + InventoryManagementService m_inventoryManagementService; + 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 createTechnician(const std::string& username, const std::string& name, const std::string& password, const std::string& email, const std::string& phone); void updateUserDetails(const std::string& email, const std::string& phone); util::Map getServices(); util::Map getComboPackages(); @@ -39,6 +49,7 @@ public: util::Map getInventoryItems(); const InventoryItem* getInventoryItem(const std::string& inventoryItemID); void addInventoryItem(const std::string& partName, int quantity, double price); + void addInventoryItemStock(const std::string& selectedItemId, int quantity); void removeInventoryItem(const std::string& inventoryItemID); util::Map getServiceBookings(); util::Map getServiceBookingsByUser(const std::string userID); @@ -56,6 +67,8 @@ public: void completePayment(const std::string& invoiceID, util::PaymentMode paymentMode); util::Vector getNotifications(); void deleteNotification(const std::string& notificationID); - void configureNotifications(const std::string& userID, bool paymentNotifications, bool serviceNotifications); + void configureNotifications(bool paymentNotifications, bool serviceNotifications); + void loadSystemData(); + void saveSystemData(); void runSystemChecks(); }; \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/patterns/Observer.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/patterns/Observer.h index 98f0efa..7fd7262 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/patterns/Observer.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/patterns/Observer.h @@ -1,3 +1,10 @@ +/* +File: Observer.h +Description: Declares the Observer interface for handling notifications in the Vehicle Service Management System. +Author: Trenser +Date: 19-May-2026 +*/ + #pragma once class Notification; @@ -6,5 +13,5 @@ class Observer { public: virtual ~Observer() = default; - virtual void update(Notification* notification) = 0; + virtual void addNotification(Notification* notification) = 0; }; \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/patterns/Subject.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/patterns/Subject.h index 309a59d..09b8ac3 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/patterns/Subject.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/patterns/Subject.h @@ -1,6 +1,14 @@ +/* +File: Subject.h +Description: Declares the Subject interface for managing user attachments and detachments in the Observer design pattern within the Vehicle Service Management System. +Author: Trenser +Date: 19-May-2026 +*/ + #pragma once #include #include "Map.h" +#include "Vector.h" class User; class Notification; diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.cpp index dd0e016..3419f44 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.cpp @@ -1,46 +1,128 @@ +/* +File: DataStore.cpp +Description: Implements the DataStore class which provides a centralized singleton repository + for managing system data in the Vehicle Service Management System. + Includes accessors for users, services, combo packages, service bookings, + job cards, inventory items, invoices, and payments. +Author: Trenser +Date: 19-May-2026 +*/ + #include "DataStore.h" +/* +Function: getInstance +Description: Provides a singleton instance of the DataStore class. +Parameters: + - None +Returns: + - Reference to the single DataStore instance. +*/ DataStore& DataStore::getInstance() { static DataStore dataStore; return dataStore; } +/* +Function: getUsers +Description: Retrieves the internal map of users. +Parameters: + - None +Returns: + - Reference to util::Map containing all users. +*/ util::Map& DataStore::getUsers() { return m_users; } +/* +Function: getServices +Description: Retrieves the internal map of services. +Parameters: + - None +Returns: + - Reference to util::Map containing all services. +*/ util::Map& DataStore::getServices() { return m_services; } +/* +Function: getComboPackages +Description: Retrieves the internal map of combo packages. +Parameters: + - None +Returns: + - Reference to util::Map containing all combo packages. +*/ util::Map& DataStore::getComboPackages() { return m_comboPackages; } +/* +Function: getServiceBookings +Description: Retrieves the internal map of service bookings. +Parameters: + - None +Returns: + - Reference to util::Map containing all service bookings. +*/ util::Map& DataStore::getServiceBookings() { return m_serviceBookings; } +/* +Function: getJobCards +Description: Retrieves the internal map of job cards. +Parameters: + - None +Returns: + - Reference to util::Map containing all job cards. +*/ util::Map& DataStore::getJobCards() { return m_jobCards; } +/* +Function: getInventoryItems +Description: Retrieves the internal map of inventory items. +Parameters: + - None +Returns: + - Reference to util::Map containing all inventory items. +*/ util::Map& DataStore::getInventoryItems() { return m_inventoryItems; } +/* +Function: getInvoices +Description: Retrieves the internal map of invoices. +Parameters: + - None +Returns: + - Reference to util::Map containing all invoices. +*/ util::Map& DataStore::getInvoices() { return m_invoices; } +/* +Function: getPayments +Description: Retrieves the internal map of payments. +Parameters: + - None +Returns: + - Reference to util::Map containing all payments. +*/ util::Map& DataStore::getPayments() { return m_payments; diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.h index 924e8e4..cde9b4e 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.h @@ -1,5 +1,11 @@ -#pragma once +/* +File: DataStore.h +Description: Declares the DataStore singleton class responsible for managing collections of users, services, combo packages, service bookings, job cards, inventory items, invoices, and payments in the Vehicle Service Management System. +Author: Trenser +Date: 19-May-2026 +*/ +#pragma once #include #include "Map.h" diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/files/README.md b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/files/README.md new file mode 100644 index 0000000..6e6b93e --- /dev/null +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/files/README.md @@ -0,0 +1 @@ +Place files here. \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ComboPackage.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ComboPackage.cpp index 6216922..4e69d9f 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ComboPackage.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ComboPackage.cpp @@ -1,65 +1,341 @@ +/* +File: ComboPackage.cpp +Description: Implements the ComboPackage class which represents a bundled set of services in the Vehicle Service Management System. + Provides constructors, accessors, and mutators for package details such as ID, name, discount percentage, state, + and associated services. +Author: Trenser +Date: 19-May-2026 +*/ + +#include +#include #include "ComboPackage.h" +#include "Service.h" +#include "Factory.h" +#include "StringHelper.h" int ComboPackage::m_uid = 0; +/* +Function: ComboPackage +Description: Default constructor that initializes a new combo package with a unique ID, + active state, and zero discount percentage. +Parameters: + - None +Returns: + - A new ComboPackage object. +*/ ComboPackage::ComboPackage() : m_id("CMP" + std::to_string(++m_uid)), m_status(util::State::ACTIVE), m_discountPercentage(0.0) {} +/* +Function: ComboPackage +Description: Parameterized constructor that initializes a new combo package with a unique ID, + specified package name, discount percentage, active state, and associated services. +Parameters: + - packageName: Name of the combo package. + - discountPercentage: Discount percentage applied to the package. + - services: Map of services included in the package. +Returns: + - A new ComboPackage object. +*/ ComboPackage::ComboPackage(const std::string& packageName, double discountPercentage, const util::Map& services) : m_id("CMP" + std::to_string(++m_uid)), m_packageName(packageName), m_discountPercentage(discountPercentage), m_status(util::State::ACTIVE), - m_services(services) {} + 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&, 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& 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; + } +} + +/* +Function: getId +Description: Retrieves the unique ID of the combo package. +Parameters: + - None +Returns: + - const std::string& representing the package ID. +*/ const std::string& ComboPackage::getId() const { return m_id; } +/* +Function: getPackageName +Description: Retrieves the name of the combo package. +Parameters: + - None +Returns: + - const std::string& representing the package name. +*/ const std::string& ComboPackage::getPackageName() const { return m_packageName; } +/* +Function: getDiscountPercentage +Description: Retrieves the discount percentage applied to the combo package. +Parameters: + - None +Returns: + - double representing the discount percentage. +*/ double ComboPackage::getDiscountPercentage() const { return m_discountPercentage; } +/* +Function: getState +Description: Retrieves the current state (ACTIVE/INACTIVE) of the combo package. +Parameters: + - None +Returns: + - util::State representing the package state. +*/ util::State ComboPackage::getState() const { return m_status; } +const util::Vector& ComboPackage::getServiceIDs() const +{ + return m_serviceIDs; +} + +/* +Function: getServices +Description: Retrieves the map of services included in the combo package. +Parameters: + - None +Returns: + - const util::Map& representing the services. +*/ const util::Map& ComboPackage::getServices() const { return m_services; } +/* +Function: setId +Description: Sets the unique ID of the combo package. +Parameters: + - id: New ID string. +Returns: + - void +*/ void ComboPackage::setId(const std::string& id) { m_id = id; } +/* +Function: setPackageName +Description: Sets the name of the combo package. +Parameters: + - packageName: New package name string. +Returns: + - void +*/ void ComboPackage::setPackageName(const std::string& packageName) { m_packageName = packageName; } +/* +Function: setDiscountPercentage +Description: Sets the discount percentage for the combo package. +Parameters: + - discountPercentage: New discount percentage value. +Returns: + - void +*/ void ComboPackage::setDiscountPercentage(double discountPercentage) { m_discountPercentage = discountPercentage; } +/* +Function: setServices +Description: Sets the services included in the combo package. +Parameters: + - services: Map of services to be associated with the package. +Returns: + - void +*/ void ComboPackage::setServices(const util::Map& 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: setState +Description: Sets the state (ACTIVE/INACTIVE) of the combo package. +Parameters: + - status: New state value. +Returns: + - void +*/ 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&, vector of service IDs +Returns: + - std::string: Concatenated service IDs string +*/ +static std::string getServiceIDsAsString(const util::Vector& 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: Vector of service IDs +*/ +static util::Vector getServiceIDsAsVector(const std::string& serviceIDsString) +{ + util::Vector 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 serviceIDs = getServiceIDsAsVector(serviceIDsString); + util::State status = util::getState(statusString); + return Factory::getObject( + 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"; +} diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ComboPackage.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ComboPackage.h index 4b28d54..941c2b3 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ComboPackage.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ComboPackage.h @@ -1,6 +1,14 @@ +/* +File: ComboPackage.h +Description: Declares the ComboPackage class which represents a service package with a unique ID, package name, discount percentage, associated services, and status in the Vehicle Service Management System. +Author: Trenser +Date: 19-May-2026 +*/ + #pragma once #include #include "Map.h" +#include "Vector.h" #include "Enums.h" class Service; @@ -12,14 +20,17 @@ private: std::string m_id; std::string m_packageName; double m_discountPercentage; + util::Vector m_serviceIDs; util::Map m_services; util::State m_status; public: ComboPackage(); ComboPackage(const std::string& packageName, double discountPercentage, const util::Map& services); + ComboPackage(const std::string& id, const std::string& packageName, double discountPercentage, const util::Vector& serviceIDs, util::State status); const std::string& getId() const; const std::string& getPackageName() const; double getDiscountPercentage() const; + const util::Vector& getServiceIDs() const; const util::Map& getServices() const; util::State getState() const; void setId(const std::string& id); @@ -27,4 +38,7 @@ public: void setDiscountPercentage(double discountPercentage); void setServices(const util::Map& services); void setState(util::State status); + std::string serialize() const; + static ComboPackage* deserialize(const std::string&); + static std::string getHeaders(); }; \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/InventoryItem.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/InventoryItem.cpp index c3dbbaa..f34b8a5 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/InventoryItem.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/InventoryItem.cpp @@ -1,13 +1,45 @@ +/* +File: InventoryItem.cpp +Description: Implements the InventoryItem class which represents an inventory item in the Vehicle Service Management System. + Provides constructors, accessors, and mutators for item details such as ID, part name, quantity, price, and state. +Author: Trenser +Date: 19-May-2026 +*/ + +#include +#include +#include "Factory.h" +#include "StringHelper.h" #include "InventoryItem.h" int InventoryItem::m_uid = 0; +/* +Function: InventoryItem +Description: Default constructor that initializes a new inventory item with a unique ID, + active state, zero quantity, and zero price. +Parameters: + - None +Returns: + - A new InventoryItem object. +*/ InventoryItem::InventoryItem() : m_id("IIM" + std::to_string(++m_uid)), m_quantity(0), m_status(util::State::ACTIVE), m_price(0.0) {} +/* +Function: InventoryItem +Description: Parameterized constructor that initializes a new inventory item with a unique ID, + specified part name, quantity, price, and active state. +Parameters: + - partName: Name of the inventory item. + - quantity: Initial quantity of the item. + - price: Price of the item. +Returns: + - A new InventoryItem object. +*/ InventoryItem::InventoryItem(const std::string& partName, int quantity, double price) : m_id("IIM" + std::to_string(++m_uid)), m_partName(partName), @@ -15,52 +47,232 @@ 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; + } +} + +/* +Function: getId +Description: Retrieves the unique ID of the inventory item. +Parameters: + - None +Returns: + - const std::string& representing the item ID. +*/ const std::string& InventoryItem::getId() const { return m_id; } +/* +Function: getPartName +Description: Retrieves the part name of the inventory item. +Parameters: + - None +Returns: + - const std::string& representing the part name. +*/ const std::string& InventoryItem::getPartName() const { return m_partName; } +/* +Function: getQuantity +Description: Retrieves the current quantity of the inventory item. +Parameters: + - None +Returns: + - int representing the quantity. +*/ int InventoryItem::getQuantity() const { return m_quantity; } +/* +Function: getPrice +Description: Retrieves the price of the inventory item. +Parameters: + - None +Returns: + - double representing the price. +*/ double InventoryItem::getPrice() const { return m_price; } +/* +Function: getState +Description: Retrieves the current state (ACTIVE/INACTIVE) of the inventory item. +Parameters: + - None +Returns: + - util::State representing the item state. +*/ util::State InventoryItem::getState() const { return m_status; } +/* +Function: setId +Description: Sets the unique ID of the inventory item. +Parameters: + - id: New ID string. +Returns: + - void +*/ void InventoryItem::setId(const std::string& id) { m_id = id; } +/* +Function: setPartName +Description: Sets the part name of the inventory item. +Parameters: + - partName: New part name string. +Returns: + - void +*/ void InventoryItem::setPartName(const std::string& partName) { m_partName = partName; } +/* +Function: setQuantity +Description: Sets the quantity of the inventory item. +Parameters: + - quantity: New quantity value. +Returns: + - void +*/ void InventoryItem::setQuantity(int quantity) { m_quantity = quantity; } +/* +Function: setPrice +Description: Sets the price of the inventory item. +Parameters: + - price: New price value. +Returns: + - void +*/ void InventoryItem::setPrice(double price) { m_price = price; } +/* +Function: setState +Description: Sets the state (ACTIVE/INACTIVE) of the inventory item. +Parameters: + - status: New state value. +Returns: + - void +*/ 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( + 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"; } \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/InventoryItem.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/InventoryItem.h index d9618bc..5808e8f 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/InventoryItem.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/InventoryItem.h @@ -1,3 +1,12 @@ +/* +File: InventoryItem.h +Description: Declares the InventoryItem class which represents parts in the Vehicle Service Management System. + Each item has a unique ID, part name, quantity, price, and status. +Author: Trenser +Date: 19-May-2026 +*/ + + #pragma once #include #include "Enums.h" @@ -14,6 +23,7 @@ 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; @@ -24,4 +34,7 @@ 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(); }; \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.cpp index 507f274..f24a013 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.cpp @@ -1,7 +1,31 @@ +/* +File: Invoice.cpp +Description: Implements the Invoice class which represents an invoice in the Vehicle Service Management System. + Provides constructors, accessors, and mutators for invoice details such as ID, booking, costs, + discount percentage, total amount, payment details, and status. +Author: Trenser +Date: 19-May-2026 +*/ + +#include +#include #include "Invoice.h" +#include "Factory.h" +#include "InventoryItem.h" +#include "StringHelper.h" int Invoice::m_uid = 0; +/* +Function: Invoice +Description: Default constructor that initializes a new invoice with a unique ID, + null booking, zero costs, zero discount, zero total amount, + and default payment method and status. +Parameters: + - None +Returns: + - A new Invoice object. +*/ Invoice::Invoice() : m_id("INV" + std::to_string(++m_uid)), m_booking(nullptr), @@ -12,13 +36,30 @@ Invoice::Invoice() m_paymentMethod(util::PaymentMode()), m_status(util::PaymentStatus()) {} +/* +Function: Invoice +Description: Parameterized constructor that initializes a new invoice with a unique ID and specified details. +Parameters: + - bookingId: ID of the associated service booking. + - booking: Pointer to the ServiceBooking object. + - invoiceDate: Timestamp of when the invoice was created. + - laborCost: Cost of labor for the service. + - parts: Map of inventory items used in the service. + - partsCost: Total cost of parts. + - discountPercentage: Discount applied to the invoice. + - totalAmount: Final total amount after discount. + - paymentDate: Timestamp of when payment was made. + - paymentMethod: Payment mode (ONLINE/OFFLINE). + - status: Payment status (PENDING/COMPLETED). +Returns: + - A new Invoice object. +*/ Invoice::Invoice( const std::string& bookingId, ServiceBooking* booking, const util::Timestamp& invoiceDate, double laborCost, - const util::Map& parts, + const util::Map& parts, double partsCost, double discountPercentage, double totalAmount, @@ -37,124 +78,495 @@ Invoice::Invoice( m_totalAmount(totalAmount), m_paymentDate(paymentDate), m_paymentMethod(paymentMethod), - m_status(status) {} + 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& 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; + } +} +/* +Function: getId +Description: Retrieves the unique ID of the invoice. +Returns: + - const std::string& representing the invoice ID. +*/ const std::string& Invoice::getId() const { return m_id; } +/* +Function: getBookingId +Description: Retrieves the booking ID associated with the invoice. +Returns: + - const std::string& representing the booking ID. +*/ const std::string& Invoice::getBookingId() const { return m_bookingId; } +/* +Function: getBooking +Description: Retrieves the pointer to the associated ServiceBooking. +Returns: + - ServiceBooking* representing the booking. +*/ ServiceBooking* Invoice::getBooking() const { return m_booking; } +/* +Function: getInvoiceDate +Description: Retrieves the timestamp of the invoice creation date. +Returns: + - const util::Timestamp& representing the invoice date. +*/ const util::Timestamp& Invoice::getInvoiceDate() const { return m_invoiceDate; } +/* +Function: getLaborCost +Description: Retrieves the labor cost associated with the invoice. +Returns: + - double representing the labor cost. +*/ 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&: Part IDs +*/ +const util::Vector& Invoice::getPartIDs() const +{ + return m_partIDs; +} + +/* +Function: getParts +Description: Retrieves the map of inventory items used in the service. +Returns: + - const util::Map& representing the parts. +*/ const util::Map& Invoice::getParts() const { return m_parts; } +/* +Function: getPartsCost +Description: Retrieves the total cost of parts used in the service. +Returns: + - double representing the parts cost. +*/ double Invoice::getPartsCost() const { return m_partsCost; } +/* +Function: getDiscountPercentage +Description: Retrieves the discount percentage applied to the invoice. +Returns: + - double representing the discount percentage. +*/ double Invoice::getDiscountPercentage() const { return m_discountPercentage; } +/* +Function: getTotalAmount +Description: Retrieves the total amount of the invoice after discount. +Returns: + - double representing the total amount. +*/ double Invoice::getTotalAmount() const { return m_totalAmount; } +/* +Function: getPaymentDate +Description: Retrieves the timestamp of the payment date. +Returns: + - const util::Timestamp& representing the payment date. +*/ const util::Timestamp& Invoice::getPaymentDate() const { return m_paymentDate; } +/* +Function: getPaymentMethod +Description: Retrieves the payment mode used for the invoice. +Returns: + - util::PaymentMode representing the payment method. +*/ util::PaymentMode Invoice::getPaymentMethod() const { return m_paymentMethod; } +/* +Function: getStatus +Description: Retrieves the payment status of the invoice. +Returns: + - util::PaymentStatus representing the payment status. +*/ util::PaymentStatus Invoice::getStatus() const { return m_status; } +/* +Function: setId +Description: Sets the unique ID of the invoice. +Parameters: + - id: New invoice ID string. +Returns: + - void +*/ void Invoice::setId(const std::string& id) { m_id = id; } +/* +Function: setBookingId +Description: Sets the booking ID associated with the invoice. +Parameters: + - bookingId: New booking ID string. +Returns: + - void +*/ void Invoice::setBookingId(const std::string& bookingId) { m_bookingId = bookingId; } +/* +Function: setBooking +Description: Sets the associated ServiceBooking pointer. +Parameters: + - booking: Pointer to the ServiceBooking object. +Returns: + - void +*/ void Invoice::setBooking(ServiceBooking* booking) { m_booking = booking; } +/* +Function: setInvoiceDate +Description: Sets the invoice creation date. +Parameters: + - invoiceDate: New timestamp for the invoice date. +Returns: + - void +*/ void Invoice::setInvoiceDate(const util::Timestamp& invoiceDate) { m_invoiceDate = invoiceDate; } +/* +Function: setLaborCost +Description: Sets the labor cost for the invoice. +Parameters: + - laborCost: New labor cost value. +Returns: + - void +*/ void Invoice::setLaborCost(double laborCost) { m_laborCost = laborCost; } +/* +Function: setParts +Description: Sets the inventory items used in the service. +Parameters: + - parts: Map of inventory items. +Returns: + - void +*/ void Invoice::setParts(const util::Map& 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()); + } } +/* +Function: setPartsCost +Description: Sets the total cost of parts used in the service. +Parameters: + - partsCost: New parts cost value. +Returns: + - void +*/ void Invoice::setPartsCost(double partsCost) { m_partsCost = partsCost; } +/* +Function: setDiscountPercentage +Description: Sets the discount percentage applied to the invoice. +Parameters: + - discountPercentage: New discount percentage value. +Returns: + - void +*/ void Invoice::setDiscountPercentage(double discountPercentage) { m_discountPercentage = discountPercentage; } +/* +Function: setTotalAmount +Description: Sets the total amount of the invoice. +Parameters: + - totalAmount: New total amount value. +Returns: + - void +*/ void Invoice::setTotalAmount(double totalAmount) { m_totalAmount = totalAmount; } +/* +Function: setPaymentDate +Description: Sets the payment date for the invoice. +Parameters: + - paymentDate: New timestamp for the payment date. +Returns: + - void +*/ void Invoice::setPaymentDate(const util::Timestamp& paymentDate) { m_paymentDate = paymentDate; } +/* +Function: setPaymentMethod +Description: Sets the payment mode for the invoice. +Parameters: + - paymentMethod: New payment mode value. +Returns: + - void +*/ void Invoice::setPaymentMethod(util::PaymentMode paymentMethod) { m_paymentMethod = paymentMethod; } +/* +Function: setStatus +Description: Sets the payment status of the invoice. +Parameters: + - status: New payment status value. +Returns: + - void +*/ 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&, vector of part IDs +Returns: + - std::string: Concatenated part IDs string +*/ +static std::string getPartIDsAsString(const util::Vector& 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: Vector of part IDs +*/ +static util::Vector getPartIDsAsVector(const std::string& partIDsString) +{ + util::Vector 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 partIDs = getPartIDsAsVector(partIDsString); + util::PaymentMode paymentMethod = util::getPaymentMode(paymentMethodString); + util::PaymentStatus status = util::getPaymentStatus(statusString); + return Factory::getObject( + 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"; +} \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.h index f78f7c9..3374de9 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.h @@ -1,6 +1,16 @@ +/* +File: Invoice.h +Description: Declares the Invoice class which represents billing details for a service booking in the Vehicle Service Management System. + Each invoice includes booking information, labor cost, parts used, discount percentage, total amount, payment details, and status. +Author: Trenser +Date: 19-May-2026 +*/ + + #pragma once #include #include "Map.h" +#include "Vector.h" #include "Timestamp.h" #include "Enums.h" @@ -16,6 +26,7 @@ private: ServiceBooking* m_booking; util::Timestamp m_invoiceDate; double m_laborCost; + util::Vector m_partIDs; util::Map m_parts; double m_partsCost; double m_discountPercentage; @@ -23,7 +34,6 @@ private: util::Timestamp m_paymentDate; util::PaymentMode m_paymentMethod; util::PaymentStatus m_status; - public: Invoice(); Invoice( @@ -39,11 +49,25 @@ public: util::PaymentMode paymentMethod, util::PaymentStatus status ); + Invoice( + const std::string& id, + const std::string& bookingId, + const util::Timestamp& invoiceDate, + const util::Vector& 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& getPartIDs() const; const util::Map& getParts() const; double getPartsCost() const; double getDiscountPercentage() const; @@ -63,4 +87,7 @@ public: 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(); }; \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.cpp index b9f1eee..214a8e0 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.cpp @@ -1,7 +1,28 @@ +/* +File: JobCard.cpp +Description: Implementation file containing the method definitions of the + JobCard class, including constructors, getters, and setters + for job card attributes. +Author: Trenser +Date:19-May-2026 +*/ + +#include +#include #include "JobCard.h" +#include "Factory.h" +#include "StringHelper.h" +#include "Enums.h" int JobCard::m_uid = 0; +/* +Function: JobCard +Description: Default constructor that initializes a new job card with + a unique ID and default values. +Parameter: None +Return type: Constructor +*/ JobCard::JobCard() : m_id("JC" + std::to_string(++m_uid)), m_booking(nullptr), @@ -9,6 +30,22 @@ JobCard::JobCard() m_technician(nullptr), m_status(util::ServiceJobStatus()) {} +/* +Function: JobCard +Description: Parameterized constructor that initializes a new job card with a unique ID and specified details. +Parameters: + - bookingId: ID of the associated service booking. + - booking: Pointer to the ServiceBooking object. + - service: Pointer to the Service object. + - serviceId: ID of the associated service. + - technicianId: ID of the assigned technician. + - technician: Pointer to the User object representing the technician. + - assignedDate: Timestamp of when the job was assigned. + - status: Current status of the job (STARTED/COMPLETED). + - completionDate: Timestamp of when the job was completed. +Returns: + - A new JobCard object. +*/ JobCard::JobCard(const std::string& bookingId, ServiceBooking* booking, Service* service, @@ -30,102 +67,363 @@ 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; + } +} + +/* +Function: getId +Description: Retrieves the unique ID of the job card. +Returns: + - const std::string& representing the job card ID. +*/ const std::string& JobCard::getId() const { return m_id; } +/* +Function: getBookingId +Description: Retrieves the booking ID associated with the job card. +Returns: + - const std::string& representing the booking ID. +*/ const std::string& JobCard::getBookingId() const { return m_bookingId; } +/* +Function: getBooking +Description: Retrieves the pointer to the associated ServiceBooking. +Returns: + - ServiceBooking* representing the booking. +*/ ServiceBooking* JobCard::getBooking() const { return m_booking; } +/* +Function: getService +Description: Retrieves the pointer to the associated Service. +Returns: + - Service* representing the service. +*/ Service* JobCard::getService() const { return m_service; } +/* +Function: getServiceId +Description: Retrieves the service ID associated with the job card. +Returns: + - const std::string& representing the service ID. +*/ const std::string& JobCard::getServiceId() const { return m_serviceId; } +/* +Function: getTechnicianId +Description: Retrieves the technician ID associated with the job card. +Returns: + - const std::string& representing the technician ID. +*/ const std::string& JobCard::getTechnicianId() const { return m_technicianId; } +/* +Function: getTechnician +Description: Retrieves the pointer to the assigned technician. +Returns: + - User* representing the technician. +*/ User* JobCard::getTechnician() const { return m_technician; } +/* +Function: getAssignedDate +Description: Retrieves the timestamp of when the job was assigned. +Returns: + - const util::Timestamp& representing the assigned date. +*/ const util::Timestamp& JobCard::getAssignedDate() const { return m_assignedDate; } +/* +Function: getStatus +Description: Retrieves the current status of the job. +Returns: + - ServiceJobStatus representing the job status. +*/ util::ServiceJobStatus JobCard::getStatus() const { return m_status; } +/* +Function: getCompletionDate +Description: Retrieves the timestamp of when the job was completed. +Returns: + - const util::Timestamp& representing the completion date. +*/ const util::Timestamp& JobCard::getCompletionDate() const { return m_completionDate; } +/* +Function: setId +Description: Sets the unique ID of the job card. +Parameters: + - id: New job card ID string. +Returns: + - void +*/ void JobCard::setId(const std::string& id) { m_id = id; } +/* +Function: setBookingId +Description: Sets the booking ID associated with the job card. +Parameters: + - bookingId: New booking ID string. +Returns: + - void +*/ void JobCard::setBookingId(const std::string& bookingId) { m_bookingId = bookingId; } +/* +Function: setBooking +Description: Sets the associated ServiceBooking pointer. +Parameters: + - booking: Pointer to the ServiceBooking object. +Returns: + - void +*/ void JobCard::setBooking(ServiceBooking* booking) { m_booking = booking; } +/* +Function: setService +Description: Sets the associated Service pointer. +Parameters: + - service: Pointer to the Service object. +Returns: + - void +*/ void JobCard::setService(Service* service) { m_service = service; } +/* +Function: setServiceId +Description: Sets the service ID associated with the job card. +Parameters: + - serviceId: New service ID string. +Returns: + - void +*/ void JobCard::setServiceId(const std::string& serviceId) { m_serviceId = serviceId; } +/* +Function: setTechnicianId +Description: Sets the technician ID associated with the job card. +Parameters: + - technicianId: New technician ID string. +Returns: + - void +*/ void JobCard::setTechnicianId(const std::string& technicianId) { m_technicianId = technicianId; } +/* +Function: setTechnician +Description: Sets the pointer to the assigned technician. +Parameters: + - technician: Pointer to the User object. +Returns: + - void +*/ void JobCard::setTechnician(User* technician) { m_technician = technician; } +/* +Function: setAssignedDate +Description: Sets the timestamp of when the job was assigned. +Parameters: + - assignedDate: New timestamp for the assigned date. +Returns: + - void +*/ void JobCard::setAssignedDate(const util::Timestamp& assignedDate) { m_assignedDate = assignedDate; } +/* +Function: setStatus +Description: Sets the current status of the job. +Parameters: + - status: New job status value. +Returns: + - void +*/ void JobCard::setStatus(util::ServiceJobStatus status) { m_status = status; } +/* +Function: setCompletionDate +Description: Sets the timestamp of when the job was completed. +Parameters: + - completionDate: New timestamp for the completion date. +Returns: + - void +*/ 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( + 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"; } \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.h index 40699c0..a845263 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.h @@ -1,3 +1,12 @@ +/* +File: JobCard.h +Description: Header file declaring the JobCard class, which represents + a service job card containing booking, service, technician, + and status details. +Author: Trenser +Date:19-May-2026 +*/ + #pragma once #include #include "Enums.h" @@ -21,7 +30,6 @@ private: util::Timestamp m_assignedDate; util::ServiceJobStatus m_status; util::Timestamp m_completionDate; - public: JobCard(); JobCard(const std::string& bookingId, @@ -34,6 +42,14 @@ public: 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, + const util::Timestamp& completionDate + ); const std::string& getId() const; const std::string& getBookingId() const; ServiceBooking* getBooking() const; @@ -54,4 +70,7 @@ public: void setAssignedDate(const util::Timestamp& assignedDate); void setStatus(util::ServiceJobStatus status); void setCompletionDate(const util::Timestamp& completionDate); + std::string serialize() const; + static JobCard* deserialize(const std::string&); + static std::string getHeaders(); }; \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Notification.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Notification.cpp index dc3ed1d..0bae917 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Notification.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Notification.cpp @@ -1,11 +1,42 @@ +/* +File: Notification.cpp +Description: Implements the Notification class which represents system notifications in the Vehicle Service Management System. + Provides constructors, accessors, and mutators for notification details such as ID, recipient, title, message, and timestamp. +Author: Trenser +Date: 19-May-2026 +*/ + +#include #include "Notification.h" +#include "StringHelper.h" +#include "Factory.h" int Notification::m_uid = 0; +/* +Function: Notification +Description: Default constructor that initializes a new notification with a unique ID and null recipient. +Parameters: + - None +Returns: + - A new Notification object. +*/ Notification::Notification() : m_id("NOT" + std::to_string(++m_uid)), m_recipient(nullptr) {} +/* +Function: Notification +Description: Parameterized constructor that initializes a new notification with a unique ID and specified details. +Parameters: + - recipientUserId: ID of the recipient user. + - recipient: Pointer to the User object representing the recipient. + - title: Title of the notification. + - message: Message content of the notification. + - createdAt: Timestamp of when the notification was created. +Returns: + - A new Notification object. +*/ Notification::Notification(const std::string& recipientUserId, User* recipient, const std::string& title, const std::string& message, const util::Timestamp& createdAt) : m_id("NOT" + std::to_string(++m_uid)), m_recipientUserId(recipientUserId), @@ -14,62 +45,243 @@ 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; + } +} + +/* +Function: getId +Description: Retrieves the unique ID of the notification. +Returns: + - const std::string& representing the notification ID. +*/ const std::string& Notification::getId() const { return m_id; } +/* +Function: getRecipientUserId +Description: Retrieves the recipient user ID associated with the notification. +Returns: + - const std::string& representing the recipient user ID. +*/ const std::string& Notification::getRecipientUserId() const { return m_recipientUserId; } +/* +Function: getRecipient +Description: Retrieves the pointer to the recipient user. +Returns: + - User* representing the recipient. +*/ User* Notification::getRecipient() const { return m_recipient; } +/* +Function: getTitle +Description: Retrieves the title of the notification. +Returns: + - const std::string& representing the notification title. +*/ const std::string& Notification::getTitle() const { return m_title; } +/* +Function: getMessage +Description: Retrieves the message content of the notification. +Returns: + - const std::string& representing the notification message. +*/ const std::string& Notification::getMessage() const { return m_message; } +/* +Function: getCreatedAt +Description: Retrieves the timestamp of when the notification was created. +Returns: + - const util::Timestamp& representing the creation timestamp. +*/ const util::Timestamp& Notification::getCreatedAt() const { return m_createdAt; } +/* +Function: setId +Description: Sets the unique ID of the notification. +Parameters: + - id: New notification ID string. +Returns: + - void +*/ void Notification::setId(const std::string& id) { m_id = id; } +/* +Function: setRecipientUserId +Description: Sets the recipient user ID for the notification. +Parameters: + - recipientUserId: New recipient user ID string. +Returns: + - void +*/ void Notification::setRecipientUserId(const std::string& recipientUserId) { m_recipientUserId = recipientUserId; } +/* +Function: setRecipient +Description: Sets the recipient user pointer for the notification. +Parameters: + - recipient: Pointer to the User object. +Returns: + - void +*/ void Notification::setRecipient(User* recipient) { m_recipient = recipient; } +/* +Function: setTitle +Description: Sets the title of the notification. +Parameters: + - title: New notification title string. +Returns: + - void +*/ void Notification::setTitle(const std::string& title) { m_title = title; } +/* +Function: setMessage +Description: Sets the message content of the notification. +Parameters: + - message: New notification message string. +Returns: + - void +*/ void Notification::setMessage(const std::string& message) { m_message = message; } +/* +Function: setCreatedAt +Description: Sets the timestamp of when the notification was created. +Parameters: + - createdAt: New timestamp value. +Returns: + - void +*/ 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( + 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"; } \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Notification.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Notification.h index f86499e..57869fa 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Notification.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Notification.h @@ -1,3 +1,11 @@ +/* +File: Notification.h +Description: Declares the Notification class which represents system messages sent to users in the Vehicle Service Management System. + Each notification includes a unique ID, recipient details, title, message content, and timestamp of creation. +Author: Trenser +Date: 19-May-2026 +*/ + #pragma once #include #include "Timestamp.h" @@ -17,6 +25,7 @@ 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; @@ -29,4 +38,7 @@ 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(); }; diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Service.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Service.cpp index fa7f509..0717467 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Service.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Service.cpp @@ -1,65 +1,337 @@ +/* +File: Service.cpp +Description: Implements the Service class which represents a vehicle service in the Vehicle Service Management System. + Provides constructors, accessors, and mutators for service details such as ID, name, required inventory items, + labor cost, and state. +Author: Trenser +Date: 19-May-2026 +*/ + +#include #include "Service.h" +#include "InventoryItem.h" +#include "StringHelper.h" +#include "Factory.h" int Service::m_uid = 0; +/* +Function: Service +Description: Default constructor that initializes a new service with a unique ID, + active state, and zero labor cost. +Parameters: + - None +Returns: + - A new Service object. +*/ Service::Service() : m_id("SRV" + std::to_string(++m_uid)), m_status(util::State::ACTIVE), m_laborCost(0.0) {} +/* +Function: Service +Description: Parameterized constructor that initializes a new service with a unique ID and specified details. +Parameters: + - name: Name of the service. + - requiredInventoryItems: Map of inventory items required for the service. + - laborCost: Labor cost associated with the service. +Returns: + - A new Service object. +*/ Service::Service(const std::string& name, const util::Map& requiredInventoryItems, double laborCost) : m_id("SRV" + std::to_string(++m_uid)), m_name(name), m_requiredInventoryItems(requiredInventoryItems), m_status(util::State::ACTIVE), - m_laborCost(laborCost) {} + 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&, 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& 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; + } +} + +/* +Function: getId +Description: Retrieves the unique ID of the service. +Returns: + - const std::string& representing the service ID. +*/ const std::string& Service::getId() const { return m_id; } +/* +Function: getName +Description: Retrieves the name of the service. +Returns: + - const std::string& representing the service name. +*/ 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&: Inventory item IDs +*/ +const util::Vector& Service::getRequiredInventoryItemIDs() const +{ + return m_requiredInventoryItemIDs; +} + +/* +Function: getRequiredInventoryItems +Description: Retrieves the map of inventory items required for the service. +Returns: + - const util::Map& representing the required inventory items. +*/ const util::Map& Service::getRequiredInventoryItems() const { return m_requiredInventoryItems; } +/* +Function: getLaborCost +Description: Retrieves the labor cost associated with the service. +Returns: + - double representing the labor cost. +*/ double Service::getLaborCost() const { return m_laborCost; } +/* +Function: getState +Description: Retrieves the current state (ACTIVE/INACTIVE) of the service. +Returns: + - util::State representing the service state. +*/ util::State Service::getState() const { return m_status; } +/* +Function: setId +Description: Sets the unique ID of the service. +Parameters: + - id: New service ID string. +Returns: + - void +*/ void Service::setId(const std::string& id) { m_id = id; } +/* +Function: setName +Description: Sets the name of the service. +Parameters: + - name: New service name string. +Returns: + - void +*/ void Service::setName(const std::string& name) { m_name = name; } +/* +Function: setRequiredInventoryItems +Description: Sets the inventory items required for the service. +Parameters: + - requiredInventoryItems: Map of inventory items. +Returns: + - void +*/ void Service::setRequiredInventoryItems(const util::Map& 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()); + } } +/* +Function: setLaborCost +Description: Sets the labor cost for the service. +Parameters: + - laborCost: New labor cost value. +Returns: + - void +*/ void Service::setLaborCost(double laborCost) { m_laborCost = laborCost; } +/* +Function: setState +Description: Sets the state (ACTIVE/INACTIVE) of the service. +Parameters: + - status: New state value. +Returns: + - void +*/ 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&, vector of inventory item IDs +Returns: + - std::string: Concatenated inventory item IDs string +*/ +static std::string getInventoryItemIDsAsString(const util::Vector& 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: Vector of inventory item IDs +*/ +static util::Vector getInventoryItemIDsAsVector(const std::string& inventoryItemIDsString) +{ + util::Vector 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 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( + 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"; } \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Service.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Service.h index b0d3175..b80e674 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Service.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Service.h @@ -1,6 +1,16 @@ +/* +File: Service.h +Description: Declares the Service class which represents a vehicle service in the Vehicle Service Management System. + Each service includes a unique ID, name, required inventory items, labor cost, and status. +Author: Trenser +Date: 19-May-2026 +*/ + + #pragma once #include #include "Map.h" +#include "Vector.h" #include "Enums.h" class InventoryItem; @@ -11,14 +21,17 @@ private: static int m_uid; std::string m_id; std::string m_name; + util::Vector m_requiredInventoryItemIDs; util::Map m_requiredInventoryItems; double m_laborCost; util::State m_status; public: Service(); Service(const std::string& name, const util::Map& requiredInventoryItems, double laborCost); + Service(const std::string& id, const std::string& name, const util::Vector& requiredInventoryItemIDs, double laborCost, util::State state); const std::string& getId() const; const std::string& getName() const; + const util::Vector& getRequiredInventoryItemIDs() const; const util::Map& getRequiredInventoryItems() const; double getLaborCost() const; util::State getState() const; @@ -27,4 +40,7 @@ public: void setRequiredInventoryItems(const util::Map& requiredInventoryItems); void setLaborCost(double laborCost); void setState(util::State status); + std::string serialize() const; + static Service* deserialize(const std::string&); + static std::string getHeaders(); }; \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.cpp index aeb7f4d..8e8b8d7 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.cpp @@ -1,14 +1,51 @@ +/* +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 +#include #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, + null customer, and zero discount percentage. +Parameters: None +Returns: A new ServiceBooking object. +*/ 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 new service booking with a unique ID and specified details. +Parameters: + - id: Booking ID string. + - status: Current status of the booking (e.g., PENDING, COMPLETED). + - services: Map of services included in the booking. + - customerId: ID of the customer. + - customer: Pointer to the User object representing the customer. + - vehicleNumber: Vehicle registration number. + - vehicleBrand: Brand of the vehicle. + - vehicleModel: Model of the vehicle. + - discountPercentage: Discount applied to the booking. +Returns: + - A new ServiceBooking object. +*/ ServiceBooking::ServiceBooking( - const std::string& id, util::ServiceJobStatus status, const util::Map& services, @@ -17,8 +54,6 @@ ServiceBooking::ServiceBooking( const std::string& vehicleNumber, const std::string& vehicleBrand, const std::string& vehicleModel, - const std::string& assignedTechnicianId, - const User* assignedTechnician, double discountPercentage ) : m_id("SRV" + std::to_string(++m_uid)), @@ -29,118 +64,456 @@ ServiceBooking::ServiceBooking( m_vehicleNumber(vehicleNumber), m_vehicleBrand(vehicleBrand), m_vehicleModel(vehicleModel), - m_assignedTechnicianId(assignedTechnicianId), - m_assignedTechnician(assignedTechnician), + m_assignedTechnicianId(""), + m_assignedTechnician(nullptr), m_discountPercentage(discountPercentage) { + 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&, 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& 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_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&: Service IDs +*/ +const util::Vector& ServiceBooking::getServiceIDs() const +{ + return m_serviceIDs; +} + +/* +Function: getServices +Description: Retrieves the services associated with the booking. +Parameter: None +Return type: const util::Map& +*/ +/* +Function: getServices +Description: Retrieves the services associated with the booking. +Parameter: None +Return type: const util::Map& +*/ const util::Map& 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& services - new services map +Return type: void +*/ void ServiceBooking::setServices(const util::Map& 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; } -void ServiceBooking::setAssignedTechnician(const User* assignedTechnician) +/* +Function: setAssignedTechnician +Description: Sets the technician object assigned to the booking. +Parameter: User* assignedTechnician - pointer to the technician object +Return type: void +*/ +void ServiceBooking::setAssignedTechnician(User* assignedTechnician) { m_assignedTechnician = assignedTechnician; } +/* +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&, vector of service IDs +Returns: + - std::string: Concatenated service IDs string +*/ +static std::string getServiceIDsAsString(const util::Vector& 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: Vector of service IDs +*/ +static util::Vector getServiceIDsAsVector(const std::string& serviceIDsString) +{ + util::Vector 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 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( + 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"; } \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.h index 8996d36..24acb32 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.h @@ -1,6 +1,15 @@ +/* +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 #include "Map.h" +#include "Vector.h" #include "Enums.h" class Service; @@ -12,6 +21,7 @@ private: static int m_uid; std::string m_id; util::ServiceJobStatus m_status; + util::Vector m_serviceIDs; util::Map m_services; std::string m_customerId; User* m_customer; @@ -19,12 +29,11 @@ private: std::string m_vehicleBrand; std::string m_vehicleModel; std::string m_assignedTechnicianId; - const User* m_assignedTechnician; + User* m_assignedTechnician; double m_discountPercentage; public: ServiceBooking(); ServiceBooking( - const std::string& id, util::ServiceJobStatus status, const util::Map& services, @@ -33,12 +42,22 @@ public: const std::string& vehicleNumber, const std::string& vehicleBrand, const std::string& vehicleModel, + double discountPercentage + ); + ServiceBooking( + const std::string& id, + util::ServiceJobStatus status, + const util::Vector& serviceIDs, + const std::string& customerId, + const std::string& vehicleNumber, + const std::string& vehicleBrand, + const std::string& vehicleModel, const std::string& assignedTechnicianId, - const User* assignedTechnician, double discountPercentage ); const std::string& getId() const; util::ServiceJobStatus getStatus() const; + const util::Vector& getServiceIDs() const; const util::Map& getServices() const; const std::string& getCustomerId() const; User* getCustomer() const; @@ -46,7 +65,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); @@ -57,6 +76,9 @@ public: void setVehicleBrand(const std::string& vehicleBrand); void setVehicleModel(const std::string& vehicleModel); void setAssignedTechnicianId(const std::string& assignedTechnicianId); - void setAssignedTechnician(const User* assignedTechnician); + void setAssignedTechnician(User* assignedTechnician); void setDiscountPercentage(double discountPercentage); + std::string serialize() const; + static ServiceBooking* deserialize(const std::string&); + static std::string getHeaders(); }; \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.cpp index 52d85a9..0b4e86e 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.cpp @@ -1,14 +1,48 @@ +/* +File: User.cpp +Description: Implements the User class which represents system users in the Vehicle Service Management System. + Provides constructors, destructor, accessors, and mutators for user details such as ID, username, + password, name, phone, email, role, state, and notifications. +Author: Trenser +Date: 19-May-2026 +*/ + +#include #include "User.h" #include "Notification.h" #include "Enums.h" +#include "Factory.h" +#include "StringHelper.h" int User::m_uid = 0; +/* +Function: User +Description: Default constructor that initializes a new user with a unique ID, + default role as CUSTOMER, and active state. +Parameters: + - None +Returns: + - A new User object. +*/ User::User() : m_id("USR" + std::to_string(++m_uid)), m_type(util::UserType::CUSTOMER), m_status(util::State::ACTIVE) {} +/* +Function: User +Description: Parameterized constructor that initializes a new user with a unique ID and specified details. +Parameters: + - userName: Username for login. + - password: Password for authentication. + - name: Full name of the user. + - phone: Phone number of the user. + - email: Email address of the user. + - role: Role of the user (CUSTOMER, ADMIN, TECHNICIAN, etc.). +Returns: + - A new User object. +*/ 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) : m_id("USR" + std::to_string(++m_uid)), m_userName(userName), @@ -19,104 +53,339 @@ User::User(const std::string& userName, const std::string& password, const std:: m_type(role), m_status(util::State::ACTIVE) {} -User::~User() +/* +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) { - for (int index = 0; index < m_notifications.getSize(); index++) + int idNumber = util::extractNumber(m_id); + if (idNumber > m_uid) { - delete m_notifications.getValues()[index]; + m_uid = idNumber; } } +/* +Function: ~User +Description: Destructor that cleans up dynamically allocated notifications associated with the user. +Parameters: + - None +Returns: + - void +*/ +User::~User() +{ + auto values = m_notifications.getValues(); + for (int index = 0; index < values.getSize(); index++) + { + delete values[index]; + } +} + +/* +Function: getId +Description: Retrieves the unique ID of the user. +Returns: + - const std::string& representing the user ID. +*/ const std::string& User::getId() const { return m_id; } +/* +Function: getUserName +Description: Retrieves the username of the user. +Returns: + - const std::string& representing the username. +*/ const std::string& User::getUserName() const { return m_userName; } +/* +Function: getPassword +Description: Retrieves the password of the user. +Returns: + - const std::string& representing the password. +*/ const std::string& User::getPassword() const { return m_password; } +/* +Function: getName +Description: Retrieves the full name of the user. +Returns: + - const std::string& representing the name. +*/ const std::string& User::getName() const { return m_name; } +/* +Function: getPhone +Description: Retrieves the phone number of the user. +Returns: + - const std::string& representing the phone number. +*/ const std::string& User::getPhone() const { return m_phone; } +/* +Function: getEmail +Description: Retrieves the email address of the user. +Returns: + - const std::string& representing the email. +*/ const std::string& User::getEmail() const { return m_email; } +/* +Function: getNotifications +Description: Retrieves the map of notifications associated with the user. +Returns: + - util::Map& representing the notifications. +*/ util::Map& User::getNotifications() { return m_notifications; } +/* +Function: getUserType +Description: Retrieves the role of the user. +Returns: + - util::UserType representing the user role. +*/ util::UserType User::getUserType() const { return m_type; } +/* +Function: getState +Description: Retrieves the current state (ACTIVE/INACTIVE) of the user. +Returns: + - util::State representing the user state. +*/ util::State User::getState() const { return m_status; } +/* +Function: setId +Description: Sets the unique ID of the user. +Parameters: + - id: New user ID string. +Returns: + - void +*/ void User::setId(const std::string& id) { m_id = id; } +/* +Function: setUserName +Description: Sets the username of the user. +Parameters: + - userName: New username string. +Returns: + - void +*/ void User::setUserName(const std::string& userName) { m_userName = userName; } +/* +Function: setPassword +Description: Sets the password of the user. +Parameters: + - password: New password string. +Returns: + - void +*/ void User::setPassword(const std::string& password) { m_password = password; } +/* +Function: setName +Description: Sets the full name of the user. +Parameters: + - name: New name string. +Returns: + - void +*/ void User::setName(const std::string& name) { m_name = name; } +/* +Function: setPhone +Description: Sets the phone number of the user. +Parameters: + - phone: New phone number string. +Returns: + - void +*/ void User::setPhone(const std::string& phone) { m_phone = phone; } +/* +Function: setEmail +Description: Sets the email address of the user. +Parameters: + - email: New email string. +Returns: + - void +*/ void User::setEmail(const std::string& email) { m_email = email; } +/* +Function: addNotification +Description: Adds a new notification to the user’s notification map. +Parameters: + - notification: Pointer to the Notification object. +Returns: + - void +*/ void User::addNotification(Notification* notification) { - m_notifications.insert(notification->getId(), notification); + if (notification) + { + m_notifications.insert(notification->getId(), notification); + } } +/* +Function: setRole +Description: Sets the role of the user. +Parameters: + - role: New user role value. +Returns: + - void +*/ void User::setRole(util::UserType role) { m_type = role; } +/* +Function: setState +Description: Sets the state (ACTIVE/INACTIVE) of the user. +Parameters: + - status: New state value. +Returns: + - void +*/ void User::setState(util::State status) { m_status = 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(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"; +} \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.h index bde21e1..12923f6 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.h @@ -1,3 +1,12 @@ +/* +File: User.h +Description: Declares the User class which represents system users in the Vehicle Service Management System. + Each user has a unique ID, credentials, personal details, notifications, role type, and status. + The User class also implements the Observer interface to handle notifications. +Author: Trenser +Date: 19-May-2026 +*/ + #pragma once #include #include "Map.h" @@ -22,6 +31,7 @@ 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; @@ -38,8 +48,10 @@ public: void setName(const std::string& name); void setPhone(const std::string& phone); void setEmail(const std::string& email); - void addNotification(Notification* notification); + void addNotification(Notification* notification) override; 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(); }; diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/AuthenticationManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/AuthenticationManagementService.cpp index ca07fee..dc3a94c 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/AuthenticationManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/AuthenticationManagementService.cpp @@ -1,3 +1,82 @@ +/* +File: AuthenticationManagementService.cpp +Description: Implementation file containing the method definitions of the + AuthenticationManagementService class, including logout and + password change logic. +Author: Trenser +Date:19-May-2026 +*/ + +#include #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 - user’s username + const std::string& password - user’s password +Return type: bool - true if login successful, false otherwise +*/ +bool AuthenticationManagementService::login(const std::string& username, const std::string& password) +{ + util::Map 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); +} diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/AuthenticationManagementService.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/AuthenticationManagementService.h index ee0ed91..47266a1 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/AuthenticationManagementService.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/AuthenticationManagementService.h @@ -1,3 +1,12 @@ +/* +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 #include "DataStore.h" diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.cpp index 39ef719..4331e0f 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.cpp @@ -1 +1,337 @@ +/* +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 +#include "Config.h" +#include "Enums.h" +#include "Factory.h" +#include "FileManager.h" +#include "InventoryItem.h" #include "InventoryManagementService.h" +#include "Timestamp.h" +#include "User.h" +#include "Utility.h" +#include "Vector.h" + + +util::Map InventoryManagementService::m_observers{}; + +/* +Function: sendLowStockAlertsToAdmins (static helper) +Description: Sends low stock alert notifications to all admin users for a given inventory item. +Parameters: + - inventoryManagementService: InventoryManagementService&, service used to send notifications + - inventoryItem: const InventoryItem*, pointer to the low-stock inventory item + - adminUsers: const util::Vector&, list of admin users to notify +Returns: + - None +*/ +static void sendLowStockAlertsToAdmins(InventoryManagementService& inventoryManagementService, const InventoryItem* inventoryItem, const util::Vector& adminUsers) +{ + int adminUsersSize = adminUsers.getSize(); + for (int index = 0; index < adminUsersSize; index++) + { + std::string title = "Low Stock Alert"; + std::string message = "The inventory item with ID " + inventoryItem->getId() + " has very low quantity in the inventory"; + inventoryManagementService.sendNotification( + adminUsers[index], + title, + message + ); + } +} + +/* +Function: sendLowStockAlerts +Description: Sends alerts to user for inventory items with low stock +Parameters: + - None +Returns: + - None +*/ +void InventoryManagementService::sendLowStockAlerts() +{ + auto& inventoryItems = m_dataStore.getInventoryItems(); + int inventoryItemsSize = inventoryItems.getSize(); + auto& usersMap = m_dataStore.getUsers(); + int usersMapSize = usersMap.getSize(); + util::Vector adminUsers; + for (int index = 0; index < usersMapSize; index++) + { + User* user = usersMap.getValueAt(index); + if (user->getUserType() == util::UserType::ADMIN) + { + adminUsers.push_back(user); + } + } + int adminUsersSize = adminUsers.getSize(); + if (adminUsersSize < 1) + { + throw std::runtime_error("The system has no admins present!"); + } + for (int index = 0; index <= inventoryItemsSize; index++) + { + InventoryItem* inventoryItem = inventoryItems.getValueAt(index); + if (inventoryItem && inventoryItem->getQuantity() < config::threshold::INVENTORY_LOW_STOCK_THRESHOLD) + { + sendLowStockAlertsToAdmins(*this, inventoryItem, adminUsers); + } + } +} + +/* +Function: getObserverIDs +Description: Retrieves the IDs of all observers currently attached to the + InventoryManagementService. +Parameters: + - None +Returns: + - util::Vector: Vector of observer user IDs +*/ +util::Vector InventoryManagementService::getObserverIDs() +{ + util::Vector 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 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 inventoryItemFileManager(config::file::INVENTORYITEM_FILE); + auto& inventoryItems = m_dataStore.getInventoryItems(); + inventoryItemFileManager.save(inventoryItems); +} + +/* +Function: loadObservers +Description: Loads observer IDs from persistent storage and attaches corresponding + users as observers to the InventoryManagementService. +Parameters: + - None +Returns: + - void +*/ +void InventoryManagementService::loadObservers() +{ + util::loadObservers(config::file::INVENTORYMANAGEMENTOBSERVERS, this, m_dataStore); +} + +/* +Function: saveObservers +Description: Saves the current observer IDs of the InventoryManagementService + to persistent storage for future retrieval. +Parameters: + - None +Returns: + - void +*/ +void InventoryManagementService::saveObservers() +{ + util::saveObservers(config::file::INVENTORYMANAGEMENTOBSERVERS, this); +} + +/* +Function: addInventoryItem +Description: Creates a new inventory item using the Factory and inserts it + into the DataStore. +Parameter: const std::string& partName - name of the part + int quantity - initial quantity of the part + double price - price of the part +Return type: void +*/ +void InventoryManagementService::addInventoryItem(const std::string& partName, int quantity, double price) +{ + InventoryItem* newItem = Factory::getObject(partName, quantity, price); + m_dataStore.getInventoryItems().insert(newItem->getId(), newItem); +} + +/* +Function: addInventoryItemStock +Description: Increases the stock quantity of an existing inventory item. +Parameter: const std::string& selectedItemId - ID of the inventory item + int quantity - quantity to add +Return type: void +*/ +void InventoryManagementService::addInventoryItemStock(const std::string& selectedItemId, int quantity) +{ + int index = m_dataStore.getInventoryItems().find(selectedItemId); + if (index != -1) + { + InventoryItem* item = m_dataStore.getInventoryItems().getValueAt(index); + if (item != nullptr) + { + int totalQuantity = item->getQuantity() + quantity; + item->setQuantity(totalQuantity); + } + } +} + +/* +Function: getInventoryItems +Description: Retrieves all inventory items stored in the DataStore. +Parameter: None +Return type: util::Map +*/ +util::Map InventoryManagementService::getInventoryItems() +{ + return m_dataStore.getInventoryItems(); +} + +/* +Function: removeInventoryItem +Description: Marks an inventory item as inactive instead of deleting it. +Parameter: const std::string& inventoryItemID - ID of the inventory item +Return type: void +*/ +void InventoryManagementService::removeInventoryItem(const std::string& inventoryItemID) +{ + int index = m_dataStore.getInventoryItems().find(inventoryItemID); + if (index != -1) + { + InventoryItem* item = m_dataStore.getInventoryItems().getValueAt(index); + if (item != nullptr) + { + item->setState(util::State::INACTIVE); + } + } +} + +/* +Function: getInventoryItem +Description: Retrieves a specific inventory item by its ID from the DataStore. +Parameter: const std::string& inventoryItemID - ID of the inventory item +Return type: InventoryItem* +*/ +InventoryItem* InventoryManagementService::getInventoryItem(const std::string& inventoryItemID) +{ + int index = m_dataStore.getInventoryItems().find(inventoryItemID); + if (index != -1) + { + return m_dataStore.getInventoryItems().getValueAt(index); + } + return nullptr; +} + +/* +Function: attach +Description: Adds a user to the observer list for receiving inventory notifications. +Parameters: + - user: User*, pointer to the user to be attached as an observer +Returns: + - None +*/ +void InventoryManagementService::attach(User* user) +{ + if (user) + { + const std::string& userID = user->getId(); + if (m_observers.find(userID) == -1) + { + m_observers[userID] = user; + } + } +} + +/* +Function: detach +Description: Removes a user from the observer list so they no longer receive inventory notifications. +Parameters: + - user: User*, pointer to the user to be detached from the observer list +Returns: + - None +*/ +void InventoryManagementService::detach(User* user) +{ + if (user) + { + const std::string& userID = user->getId(); + if (m_observers.find(userID) != -1) + { + m_observers.remove(userID); + } + } +} + +/* +Function: sendNotification +Description: Sends a notification to a user if they are subscribed as an observer. +Parameters: + - user: User*, pointer to the user receiving the notification + - title: std::string, title of the notification + - message: std::string, body/content of the notification +Returns: + - None +Throws: + - std::runtime_error if notification creation fails +*/ +void InventoryManagementService::sendNotification(User* user, const std::string& title, const std::string& message) +{ + if (user) + { + if (m_observers.find(user->getId()) != -1) + { + Notification* notification = + Factory::getObject( + user->getId(), + user, + "InventoryManagementService: " + title, + message, + util::Timestamp() + ); + if (notification) + { + user->addNotification(notification); + } + else + { + throw std::runtime_error("Failed to create notification"); + } + } + } +} + diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.h index 099b964..f5db383 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.h @@ -1,6 +1,16 @@ +/* +File: InventoryManagementService.h +Description: Header file declaring the InventoryManagementService class, + which manages inventory items, stock updates, and notifications + related to low stock alerts. Inherits from NotificationManagementService. +Author: Trenser +Date:19-May-2026 +*/ + #pragma once #include #include "Map.h" +#include "Vector.h" #include "NotificationManagementService.h" #include "DataStore.h" @@ -11,14 +21,20 @@ class InventoryManagementService : public NotificationManagementService private: DataStore& m_dataStore; static util::Map m_observers; + util::Vector getObserverIDs() override; public: InventoryManagementService() : m_dataStore(DataStore::getInstance()) {} util::Map getInventoryItems(); InventoryItem* getInventoryItem(const std::string& inventoryItemID); void addInventoryItem(const std::string& partName, int quantity, double price); void removeInventoryItem(const std::string& inventoryItemID); + void addInventoryItemStock(const std::string& selectedItemId, int quantity); void sendLowStockAlerts(); 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(); }; diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/NotificationManagementService.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/NotificationManagementService.h index b193b1d..33d214a 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/NotificationManagementService.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/NotificationManagementService.h @@ -1,6 +1,15 @@ +/* +File: NotificationManagementService.h +Description: Declares the NotificationManagementService abstract class which defines the contract for managing notifications in the Vehicle Service Management System. + Implements the Subject interface and provides pure virtual methods for sending notifications and managing user subscriptions (attach/detach). +Author: Trenser +Date: 19-May-2026 +*/ + #pragma once #include #include "Subject.h" +#include "Notification.h" #include "User.h" class NotificationManagementService : public Subject @@ -10,4 +19,5 @@ 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 getObserverIDs() = 0; }; diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp index c6e2f85..a922f31 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp @@ -1,13 +1,261 @@ -#include "PaymentManagementService.h" -#include "ServiceBooking.h" -#include "Service.h" -#include "InventoryItem.h" -#include "Utility.h" +/* +File: PaymentManagementService.cpp +Description: Implements the PaymentManagementService class which manages payment-related operations + in the Vehicle Service Management System. Provides functionality for attaching/detaching observers, + sending notifications, and issuing payment reminders based on invoice status and thresholds. +Author: Trenser +Date: 20-May-2026 +*/ + +#include +#include "Config.h" +#include "Enums.h" #include "Factory.h" -#include "Timestamp.h" +#include "FileManager.h" +#include "InventoryItem.h" #include "Invoice.h" #include "JobCard.h" -#include "Enums.h" +#include "PaymentManagementService.h" +#include "Service.h" +#include "ServiceBooking.h" +#include "Timestamp.h" +#include "User.h" +#include "Utility.h" + +util::Map PaymentManagementService::m_observers{}; + +/* +Function: attach +Description: Attaches a user as an observer to the PaymentManagementService for receiving notifications. +Parameters: + - user: Pointer to the User object to be attached. +Returns: + - void +*/ +void PaymentManagementService::attach(User* user) +{ + if (user) + { + const std::string& userID = user->getId(); + if (m_observers.find(userID) == -1) + { + m_observers[userID] = user; + } + } +} + +/* +Function: detach +Description: Detaches a user from the observer list of the PaymentManagementService. +Parameters: + - user: Pointer to the User object to be detached. +Returns: + - void +*/ +void PaymentManagementService::detach(User* user) +{ + if (user) + { + const std::string& userID = user->getId(); + if (m_observers.find(userID) != -1) + { + m_observers.remove(userID); + } + } +} + +/* +Function: sendNotification +Description: Sends a notification to a user if they are registered as an observer. +Parameters: + - user: Pointer to the User object to receive the notification. + - title: Title of the notification. + - message: Message content of the notification. +Returns: + - void +Throws: + - std::runtime_error if notification creation fails. +*/ +void PaymentManagementService::sendNotification(User* user, const std::string& title, const std::string& message) +{ + if (user) + { + if (m_observers.find(user->getId()) != -1) + { + Notification* notification = + Factory::getObject( + user->getId(), + user, + "PaymentManagementService: " + title, + message, + util::Timestamp() + ); + if (notification) + { + user->addNotification(notification); + } + else + { + throw std::runtime_error("Failed to create notification"); + } + } + } +} + +/* +Function: sendPaymentReminders +Description: Iterates through all invoices in the datastore and sends payment reminders to customers + whose invoices are pending beyond the configured threshold duration. +Parameters: + - None +Returns: + - void +*/ +void PaymentManagementService::sendPaymentReminders() +{ + auto& invoicesMap = m_dataStore.getInvoices(); + int invoicesMapSize = invoicesMap.getSize(); + for (int index = 0; index < invoicesMapSize; index++) + { + const Invoice* invoice = invoicesMap.getValueAt(index); + if (invoice && invoice->getStatus() == util::PaymentStatus::PENDING) + { + util::Timestamp invoiceCreationTimestamp = invoice->getInvoiceDate(); + util::Timestamp currentTimestamp; + if (util::Timestamp::getDurationInHours(invoiceCreationTimestamp, currentTimestamp) >= config::threshold::PAYMENT_REMINDER_THRESHOLD_HOURS) + { + const ServiceBooking* serviceBooking = invoice->getBooking(); + if (serviceBooking) + { + User* customer = serviceBooking->getCustomer(); + if (customer) + { + std::string title = "Payment Reminder"; + std::string message = "Your payment for Invoice ID " + invoice->getId() + " is still pending. Please complete the payment."; + sendNotification(customer, title, message); + } + } + } + } + } +} + +/* +Function: getObserverIDs +Description: Retrieves the IDs of all observers currently attached to the + PaymentManagementService. +Parameters: + - None +Returns: + - util::Vector: Vector of observer user IDs +*/ +util::Vector PaymentManagementService::getObserverIDs() +{ + util::Vector 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 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 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 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); +} /* Function: createInventoryItemsMap (static helper) diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.h index 56a2fd2..14b8c11 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.h @@ -1,3 +1,12 @@ +/* +File: PaymentManagementService.h +Description: Declares the PaymentManagementService class which manages payment operations in the Vehicle Service Management System. + Provides functionality to generate invoices, retrieve customer invoices, complete payments, send payment reminders, + and handle notifications using the Observer pattern. +Author: Trenser +Date: 19-May-2026 +*/ + #pragma once #include #include "Map.h" @@ -13,6 +22,7 @@ class PaymentManagementService : public NotificationManagementService private: DataStore& m_dataStore; static util::Map m_observers; + util::Vector getObserverIDs() override; public: PaymentManagementService() : m_dataStore(DataStore::getInstance()) {} void generateInvoice(ServiceBooking* booking); @@ -22,4 +32,8 @@ 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(); }; diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp index c9cb818..55920d5 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp @@ -1,16 +1,733 @@ -#include "ServiceManagementService.h" -#include "UserManagementService.h" -#include "ServiceBooking.h" -#include "Factory.h" -#include "JobCard.h" -#include "Timestamp.h" -#include "Service.h" -#include "Enums.h" -#include "InventoryItem.h" +/* +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 #include "AuthenticationManagementService.h" -#include "PaymentManagementService.h" +#include "ComboPackage.h" +#include "Config.h" +#include "DataStore.h" +#include "Enums.h" +#include "Factory.h" +#include "FileManager.h" +#include "InventoryItem.h" +#include "JobCard.h" #include "NotificationManagementService.h" +#include "PaymentManagementService.h" +#include "Service.h" +#include "ServiceBooking.h" +#include "ServiceManagementService.h" +#include "Timestamp.h" +#include "Timestamp.h" #include "User.h" +#include "UserManagementService.h" +#include "Utility.h" + +/* +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& serviceIDs - IDs of services to purchase + const std::string& vehicleNumber - vehicle registration number + const std::string& vehicleBrand - brand of the vehicle + const std::string& vehicleModel - model of the vehicle +Return type: void +*/ +void ServiceManagementService::purchaseService(const util::Vector& serviceIDs, const std::string& vehicleNumber, const std::string& vehicleBrand, const std::string& vehicleModel) +{ + AuthenticationManagementService m_authenticationManagementService; + auto authenticatedUser = m_authenticationManagementService.getAuthenticatedUser(); + if (authenticatedUser == nullptr) + { + throw std::runtime_error("No user is currently logged in!"); + } + auto& servicesMap = m_dataStore.getServices(); + auto& serviceBookingMap = m_dataStore.getServiceBookings(); + util::Map selectedServices; + int selectedServicesCount = serviceIDs.getSize(); + for (int index = 0; index < selectedServicesCount; index++) + { + int serviceIndex = servicesMap.find(serviceIDs[index]); + if (serviceIndex == -1) + { + throw std::runtime_error("Service not found!"); + } + Service* service = servicesMap.getValueAt(serviceIndex); + selectedServices[service->getId()] = service; + } + ServiceBooking* serviceBooking = Factory::getObject(util::ServiceJobStatus::STARTED, selectedServices, authenticatedUser->getId(), authenticatedUser, vehicleNumber, vehicleBrand, vehicleModel, 0); + if (serviceBooking == nullptr) + { + throw std::runtime_error("Failed to create service booking"); + } + serviceBookingMap[serviceBooking->getId()] = serviceBooking; + std::string title = "Service Booking succeeded"; + std::string message = "Your service booking has been successfully placed with ID " + serviceBooking->getId(); + sendNotification(authenticatedUser, title, message); +} + +/* +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::purchaseComboPackage(const std::string& comboPackageID, const std::string& vehicleNumber, const std::string& vehicleBrand, const std::string& vehicleModel) +{ + 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 selectedServices = comboPackage->getServices(); + ServiceBooking* serviceBooking = Factory::getObject(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; + std::string title = "Combo Package Service Booking succeeded"; + std::string message = "Your service booking for the combo package has been successfully placed with ID " + serviceBooking->getId(); + sendNotification(authenticatedUser, title, message); +} + +util::Map ServiceManagementService::m_observers{}; + +/* +Function: attach +Description: Attaches a user as an observer to the ServiceManagementService for receiving notifications. +Parameters: + - user: Pointer to the User object to be attached. +Returns: + - void +*/ +void ServiceManagementService::attach(User* user) +{ + if (user) + { + const std::string& userID = user->getId(); + if (m_observers.find(userID) == -1) + { + m_observers[userID] = user; + } + } +} + +/* +Function: detach +Description: Detaches a user from the observer list of the ServiceManagementService. +Parameters: + - user: Pointer to the User object to be detached. +Returns: + - void +*/ +void ServiceManagementService::detach(User* user) +{ + if (user) + { + const std::string& userID = user->getId(); + if (m_observers.find(userID) != -1) + { + m_observers.remove(userID); + } + } +} + +/* +Function: sendNotification +Description: Sends a notification to a user if they are registered as an observer. +Parameters: + - user: Pointer to the User object to receive the notification. + - title: Title of the notification. + - message: Message content of the notification. +Returns: + - void +Throws: + - std::runtime_error if notification creation fails. +*/ +void ServiceManagementService::sendNotification(User* user, const std::string& title, const std::string& message) +{ + if (user) + { + if (m_observers.find(user->getId()) != -1) + { + Notification* notification = + Factory::getObject( + user->getId(), + user, + "ServiceManagementService: " + title, + message, + util::Timestamp() + ); + if (notification) + { + user->addNotification(notification); + } + else + { + throw std::runtime_error("Failed to create notification"); + } + } + } +} + +/* +Function: getObserverIDs +Description: Retrieves the IDs of all observers currently attached to the + ServiceManagementService. +Parameters: + - None +Returns: + - util::Vector: Vector of observer user IDs +*/ +util::Vector ServiceManagementService::getObserverIDs() +{ + util::Vector 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: 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 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++) + { + Service* service = servicesMap.getValueAt(serviceIndex); + services[service->getId()] = service; + util::Map 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 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 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 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 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 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 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 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 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()); + if (serviceIndex == -1) + { + throw std::runtime_error("Invalid Service ID"); + } + Service* service = services.getValueAt(serviceIndex); + if (booking->getServices().find(jobCard->getServiceId()) == -1) + { + 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; + } +} + +/* +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 +*/ +void ServiceManagementService::saveJobCards() +{ + util::FileManager 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); +} + +/* +Function: cancelCustomerServiceBookings +Description: Cancels all service bookings associated with a given customer or technician. + Updates booking status, resets customer/technician assignments, sends notifications, + and restocks inventory items. +Parameter: const std::string& userID - ID of the customer or technician +Return type: void +*/ +void ServiceManagementService::cancelCustomerServiceBookings(const std::string& userID) +{ + const int INCREMENT_VALUE = 1; + auto& users = m_dataStore.getUsers(); + int userIndex = users.find(userID); + if (userIndex == -1) + { + throw std::runtime_error("User not found: " + userID); + } + User* user = users.getValueAt(userIndex); + if (user == nullptr) + { + throw std::runtime_error("User not found: " + userID); + } + util::UserType type = user->getUserType(); + auto& bookings = DataStore::getInstance().getServiceBookings(); + for (int bookingIterator = 0; bookingIterator < bookings.getSize(); bookingIterator++) + { + ServiceBooking* booking = bookings.getValueAt(bookingIterator); + if (booking != nullptr && + (booking->getCustomerId() == userID || booking->getAssignedTechnicianId() == userID)) + { + if (booking->getStatus() == util::ServiceJobStatus::PENDING || + booking->getStatus() == util::ServiceJobStatus::STARTED) + { + if (type == util::UserType::CUSTOMER) + { + booking->setStatus(util::ServiceJobStatus::CANCELLED); + booking->setCustomer(nullptr); + booking->setCustomerId(""); + User* assignedTechnician = booking->getAssignedTechnician(); + std::string title = "Customer Service Cancelled"; + std::string message = "The customer has cancelled their service booking. Your assigned job card has been cancelled and the inventory has been restocked."; + sendNotification(assignedTechnician, title, message); + } + else if (type == util::UserType::TECHNICIAN) + { + booking->setStatus(util::ServiceJobStatus::PENDING); + std::string title = "Technician Unavailable"; + std::string message = "Your assigned technician is no longer available. Your booking has been reset to pending, and we will reassign a new technician shortly."; + sendNotification(booking->getCustomer(), title, message); + } + booking->setAssignedTechnician(nullptr); + booking->setAssignedTechnicianId(""); + const auto& ListOfServices = booking->getServices(); + for (int serviceIterator = 0; serviceIterator < ListOfServices.getSize(); serviceIterator++) + { + Service* service = ListOfServices.getValueAt(serviceIterator); + if (service != nullptr) + { + const auto& items = service->getRequiredInventoryItems(); + for (int itemIterator = 0; itemIterator < items.getSize(); itemIterator++) + { + InventoryItem* item = items.getValueAt(itemIterator); + if (item != nullptr) + { + item->setQuantity(item->getQuantity() + INCREMENT_VALUE); + } + } + } + } + } + } + } +} + +/* +Function: cancelTechnicianJobs +Description: Cancels all jobs assigned to a technician. Updates job status, sends notifications, + and restocks inventory items used in the service. +Parameter: const std::string& technicianID - ID of the technician +Return type: void +*/ +void ServiceManagementService::cancelTechnicianJobs(const std::string& technicianID) +{ + const int INCREMENT_VALUE = 1; + auto& jobs = m_dataStore.getJobCards(); + for (int jobIterator = 0; jobIterator < jobs.getSize(); jobIterator++) + { + JobCard* job = jobs.getValueAt(jobIterator); + if (job != nullptr && job->getTechnicianId() == technicianID) + { + if (job->getStatus() == util::ServiceJobStatus::PENDING || job->getStatus() == util::ServiceJobStatus::STARTED) + { + job->setStatus(util::ServiceJobStatus::CANCELLED); + std::string title = "Job Cancelled"; + std::string message = "The Job has cancelled. Your job card has been cancelled and the inventory has been restocked."; + sendNotification(job->getTechnician(), title, message); + Service* service = job->getService(); + if (service != nullptr) + { + const auto& items = service->getRequiredInventoryItems(); + for (int itemIterator = 0; itemIterator < items.getSize(); itemIterator++) + { + InventoryItem* item = items.getValueAt(itemIterator); + if (item != nullptr) + { + item->setQuantity(item->getQuantity() + INCREMENT_VALUE); + } + } + } + } + } + } +} + +/* +Function: createComboPackage +Description: Creates a new combo package with two services and a discount percentage. + Validates service IDs, ensures uniqueness, and inserts the new package into the DataStore. +Parameter: const std::string& packageName - name of the combo package + const util::Vector& serviceIDsInNewCombo - list of service IDs + double discountPercentage - discount percentage for the package +Return type: void +*/ +void ServiceManagementService::createComboPackage(const std::string& packageName, const util::Vector& serviceIDsInNewCombo, double discountPercentage) +{ + if (packageName.empty()) + { + throw std::invalid_argument("The Combo Package Name cannot be empty.\n"); + } + if (serviceIDsInNewCombo.getSize() < 2 || serviceIDsInNewCombo.getSize() > 2) + { + throw std::invalid_argument("Combo package must contain only two services."); + } + if (discountPercentage < 0.0 || discountPercentage > 100.0) + { + throw std::invalid_argument("Discount percentage must be between 0 and 100."); + } + auto& servicesMap = m_dataStore.getServices(); + for (int index = 0; index < serviceIDsInNewCombo.getSize(); index++) + { + const std::string serviceid = serviceIDsInNewCombo[index]; + if (servicesMap.find(serviceid) == -1) + { + throw std::runtime_error("Service ID not found: " + serviceid); + } + } + auto& comboPackageMap = m_dataStore.getComboPackages(); + for (int iterator = 0; iterator < comboPackageMap.getSize(); iterator++) + { + ComboPackage* existingCombos = comboPackageMap.getValueAt(iterator); + const util::Map& servicesInsideExistingCombos = existingCombos->getServices(); + if (servicesInsideExistingCombos.getSize() == serviceIDsInNewCombo.getSize()) + { + bool isIdentical = true; + for (int serviceIterator = 0; serviceIterator < serviceIDsInNewCombo.getSize(); serviceIterator++) + { + const std::string& id = serviceIDsInNewCombo[serviceIterator]; + if (servicesInsideExistingCombos.find(id) == -1) + { + isIdentical = false; + break; + } + } + if (isIdentical) + { + throw std::runtime_error("A combo package with the same services already exists."); + } + } + } + util::Map selectedServices; + for (int iteratorOne = 0; iteratorOne < serviceIDsInNewCombo.getSize(); iteratorOne++) + { + const std::string& serviceId = serviceIDsInNewCombo[iteratorOne]; + int serviceIndex = servicesMap.find(serviceId); + if (serviceIndex == -1) + { + throw std::runtime_error("Service ID not found: " + serviceId); + } + selectedServices.insert(serviceId, servicesMap.getValueAt(serviceIndex)); + } + ComboPackage* newComboPackage = Factory::getObject(packageName, discountPercentage, selectedServices); + comboPackageMap.insert(newComboPackage->getId(), newComboPackage); +} + +/* +Function: getComboPackages +Description: Retrieves all combo packages stored in the DataStore. +Parameter: None +Return type: util::Map +*/ +util::Map ServiceManagementService::getComboPackages() +{ + return m_dataStore.getComboPackages(); +} + +/* +Function: removeComboPackage +Description: Removes a combo package by marking it inactive. Throws an exception if the package ID is not found. +Parameter: const std::string& comboPackageID - ID of the combo package +Return type: void +*/ +void ServiceManagementService::removeComboPackage(const std::string& comboPackageID) +{ + bool removed = false; + util::Map& currentComboPackages = m_dataStore.getComboPackages(); + for (int iterator = 0; iterator < currentComboPackages.getSize(); iterator++) + { + ComboPackage* currentComboPackage = currentComboPackages.getValueAt(iterator); + if (currentComboPackage && currentComboPackage->getId() == comboPackageID) + { + currentComboPackage->setState(util::State::INACTIVE); + removed = true; + break; + } + } + if (!removed) + { + throw std::runtime_error("Combo package with ID '" + comboPackageID + "' not found."); + } +} /* Function: getServiceBookings diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.h index ab5723e..2fdcc93 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.h @@ -1,3 +1,12 @@ +/* +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 #include "Map.h" @@ -14,6 +23,7 @@ class ServiceManagementService : public NotificationManagementService private: DataStore& m_dataStore; static util::Map m_observers; + util::Vector getObserverIDs() override; public: ServiceManagementService() : m_dataStore(DataStore::getInstance()) {} util::Map getServices(); @@ -30,9 +40,19 @@ public: void completeJob(const std::string& jobID); void cancelCustomerServiceBookings(const std::string& customerID); void cancelTechnicianJobs(const std::string& technicianID); - void createComboPackage(const std::string& name, const util::Vector& serviceIDs, double discountPercentage); + void createComboPackage(const std::string& packageName, const util::Vector& serviceIDs, double discountPercentage); void removeComboPackage(const std::string& comboPackageID); void sendNotification(User* user, const std::string& title, const std::string& message) override; void attach(User* user) override; 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(); }; diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp index 4f8adb2..7518d52 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp @@ -1,5 +1,296 @@ -#include "UserManagementService.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 +#include "Config.h" +#include "Enums.h" +#include "Factory.h" +#include "FileManager.h" +#include "InventoryManagementService.h" +#include "Notification.h" +#include "PaymentManagementService.h" +#include "ServiceManagementService.h" #include "User.h" +#include "UserManagementService.h" +#include "Vector.h" + + +/* +Function: ensureAdminExists +Description: Ensures that at least one admin user exists in the system. + If no admin is found, creates a default admin user using + configuration constants. +Parameter: None +Return type: void +*/ +void UserManagementService::ensureAdminExists() +{ + auto& usersMap = m_dataStore.getUsers(); + int usersMapSize = usersMap.getSize(); + bool isAdminFound = false; + for (int index = 0; index < usersMapSize; index++) + { + User* user = usersMap.getValueAt(index); + if (user && user->getUserType() == util::UserType::ADMIN) + { + isAdminFound = true; + break; + } + } + if (!isAdminFound) + { + createUser( + config::admin::DEFAULT_ADMIN_USERNAME, + config::admin::DEFAULT_ADMIN_NAME, + config::admin::DEFAULT_ADMIN_PASSWORD, + config::admin::DEFAULT_ADMIN_EMAIL, + config::admin::DEFAULT_ADMIN_PHONE, + util::UserType::ADMIN); + } +} + +/* +Function: createUser +Description: Creates a new user with the provided details. Validates that + the username is unique, then attaches the user to relevant + management services (payment, service, inventory). +Parameter: const std::string& username - user’s username + const std::string& name - user’s name + const std::string& password - user’s password + const std::string& email - user’s email address + const std::string& phone - user’s phone number + util::UserType type - type of user (ADMIN, CUSTOMER, TECHNICIAN) +Return type: void +*/ +void UserManagementService::createUser(const std::string& username, const std::string& name, const std::string& password, const std::string& email, const std::string& phone, util::UserType type) +{ + InventoryManagementService inventoryManagementService; + PaymentManagementService paymentManagementService; + ServiceManagementService serviceManagementService; + auto& usersMap = m_dataStore.getUsers(); + int index = usersMap.findIf( + [&](const std::string&, User* user) + { + return user->getUserName() == username; + } + ); + if (index != -1) + { + throw std::runtime_error("Username already exists"); + } + User* newUser = Factory::getObject(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); + } +} + +/* +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); +} + +/* +Function: getUserNotifications +Description: Retrieves all notifications associated with a given user ID. +Parameters: + - userID: The unique ID of the user whose notifications are to be retrieved. +Returns: + - util::Vector containing all notifications for the user. +Throws: + - std::runtime_error if no user is found with the given UserID or if the User object is invalid. +*/ +util::Vector UserManagementService::getUserNotifications(const std::string& userID) +{ + auto& usersMap = m_dataStore.getUsers(); + if (usersMap.find(userID) == -1) + { + throw std::runtime_error("No user found with given UserID"); + } + User* user = usersMap[userID]; + if (user) + { + auto& notifications = user->getNotifications(); + int numberOfNotifications = notifications.getSize(); + util::Vector notificationsVector; + for (int index = 0; index < numberOfNotifications; index++) + { + notificationsVector.push_back(notifications.getValueAt(index)); + } + return notificationsVector; + } + else + { + throw std::runtime_error("Invalid User object"); + } +} + +/* +Function: deleteNotification +Description: Deletes a specific notification associated with a given user ID. +Parameters: + - notificationID: The unique ID of the notification to be deleted. + - userID: The unique ID of the user whose notification is to be deleted. +Returns: + - void +Throws: + - std::runtime_error if no user is found with the given UserID or if no notification is found with the given NotificationID. +*/ +void UserManagementService::deleteNotification(const std::string& notificationID, const std::string& userID) +{ + auto& usersMap = m_dataStore.getUsers(); + if (usersMap.find(userID) == -1) + { + throw std::runtime_error("No user found with given UserID"); + } + User* user = usersMap[userID]; + auto& notifications = user->getNotifications(); + if (notifications.find(notificationID) == -1) + { + throw std::runtime_error("No notification found with given NotificationID"); + } + notifications.remove(notificationID); +} + +/* +Function: loadUsers +Description: Loads users and notifications from persistent storage into the datastore. + Validates that each notification’s recipient exists and attaches the + notification to the corresponding user. +Parameters: + - None +Returns: + - void +Throws: + - std::runtime_error if a notification recipient user ID is invalid +*/ +void UserManagementService::loadUsers() +{ + util::FileManager userFileManager(config::file::USER_FILE); + util::FileManager 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++) + { + users[usersMap.getKeyAt(index)] = usersMap.getValueAt(index); + } + for (int index = 0; index < numberOfNotifications; index++) + { + Notification* notification = notificationsMap.getValueAt(index); + const std::string& recipientUserId = notification->getRecipientUserId(); + int userIndex = users.find(recipientUserId); + if (userIndex == -1) + { + throw std::runtime_error("Invalid recipient user ID"); + } + User* user = users.getValueAt(userIndex); + user->addNotification(notification); + } +} + +/* +Function: saveUsers +Description: Saves users and their notifications from the datastore to persistent storage. + Collects notifications from all users into a single map before saving. +Parameters: + - None +Returns: + - void +*/ +void UserManagementService::saveUsers() +{ + util::FileManager userFileManager(config::file::USER_FILE); + util::FileManager notificationFileManager(config::file::NOTIFICATION_FILE); + auto& users = m_dataStore.getUsers(); + util::Map notifications; + for (int userIndex = 0; userIndex < users.getSize(); userIndex++) + { + User* user = users.getValueAt(userIndex); + auto& userNotifications = user->getNotifications(); + for (int notificationIndex = 0; notificationIndex < userNotifications.getSize(); notificationIndex++) + { + notifications[userNotifications.getKeyAt(notificationIndex)] = + userNotifications.getValueAt(notificationIndex); + } + } + userFileManager.save(users); + notificationFileManager.save(notifications); +} + +/* +Function: getUsers +Description: Retrieves all users stored in the DataStore. +Parameter: None +Return type: util::Map +*/ +util::Map UserManagementService::getUsers() +{ + return m_dataStore.getUsers(); +} + +/* +Function: getUser +Description: Retrieves a specific user by ID from the DataStore. +Parameter: const std::string& userID - ID of the user +Return type: User* +*/ +User* UserManagementService::getUser(const std::string& userID) +{ + int index = m_dataStore.getUsers().find(userID); + if (index != -1) + { + return m_dataStore.getUsers().getValueAt(index); + } + return nullptr; +} + +/* +Function: removeUser +Description: Marks a user as inactive in the DataStore instead of deleting them. +Parameter: const std::string& userID - ID of the user to remove +Return type: void +*/ +void UserManagementService::removeUser(const std::string& userID) +{ + int index = m_dataStore.getUsers().find(userID); + if (index != -1) + { + User* user = m_dataStore.getUsers().getValueAt(index); + if (user != nullptr) + { + user->setState(util::State::INACTIVE); + } + } +} util::Map UserManagementService::getUsers(util::UserType type) { diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.h index bb7a85a..6b9f518 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.h @@ -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 #include "Map.h" @@ -13,12 +21,15 @@ 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 getUsers(); util::Map getUsers(util::UserType type); - User* getUser(const std::string& userID); + User* getUser (const std::string& userID); void removeUser(const std::string& userID); util::Vector getUserNotifications(const std::string& userID); void deleteNotification(const std::string& notificationID, const std::string& userID); + void ensureAdminExists(); + void loadUsers(); + void saveUsers(); }; diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Config.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Config.h new file mode 100644 index 0000000..30bfad9 --- /dev/null +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Config.h @@ -0,0 +1,43 @@ +/* +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: 21-May-2026 +*/ + +#pragma once + +namespace config +{ + namespace admin + { + constexpr const char* DEFAULT_ADMIN_USERNAME = "admin"; + constexpr const char* DEFAULT_ADMIN_NAME = "admin"; + constexpr const char* DEFAULT_ADMIN_PASSWORD = ""; + constexpr const char* DEFAULT_ADMIN_EMAIL = "admin@vss"; + constexpr const char* DEFAULT_ADMIN_PHONE = "0000000000"; + } + + namespace threshold + { + constexpr int INVENTORY_LOW_STOCK_THRESHOLD = 5; + constexpr int PAYMENT_REMINDER_THRESHOLD_HOURS = 168; + } + + namespace file + { + 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"; + } +} diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h index 7dda730..e410eff 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h @@ -1,3 +1,12 @@ +/* +File: Enums.h +Description: Declares enumerations and utility functions for user types, payment modes, payment status, + service job status, and state management in the Vehicle Service Management System. + Provides string conversion and parsing functions for each enum type. +Author: Trenser +Date: 19-May-2026 +*/ + #pragma once #include @@ -27,7 +36,8 @@ namespace util { PENDING, STARTED, - COMPLETED + COMPLETED, + CANCELLED }; enum class State @@ -36,6 +46,14 @@ namespace util INACTIVE }; + /* + Function: getUserTypeString + Description: Converts a UserType enum value to its corresponding string representation. + Parameters: + - type: UserType enum value. + Returns: + - std::string representing the UserType. + */ inline std::string getUserTypeString(UserType type) { switch (type) @@ -50,6 +68,16 @@ namespace util throw std::invalid_argument("Invalid UserType"); } + /* + Function: getUserType + Description: Converts a string value to its corresponding UserType enum. + Parameters: + - value: std::string representing the UserType. + Returns: + - UserType enum value. + Throws: + - std::invalid_argument if the string does not match a valid UserType. + */ inline UserType getUserType(const std::string& value) { if (value == "ADMIN") @@ -67,6 +95,14 @@ namespace util throw std::invalid_argument("Invalid UserType string"); } + /* + Function: getPaymentModeString + Description: Converts a PaymentMode enum value to its corresponding string representation. + Parameters: + - mode: PaymentMode enum value. + Returns: + - std::string representing the PaymentMode. + */ inline std::string getPaymentModeString(PaymentMode mode) { switch (mode) @@ -81,6 +117,16 @@ namespace util throw std::invalid_argument("Invalid PaymentMode"); } + /* + Function: getPaymentMode + Description: Converts a string value to its corresponding PaymentMode enum. + Parameters: + - value: std::string representing the PaymentMode. + Returns: + - PaymentMode enum value. + Throws: + - std::invalid_argument if the string does not match a valid PaymentMode. + */ inline PaymentMode getPaymentMode(const std::string& value) { if (value == "ONLINE") @@ -94,6 +140,14 @@ namespace util throw std::invalid_argument("Invalid PaymentMode string"); } + /* + Function: getPaymentStatusString + Description: Converts a PaymentStatus enum value to its corresponding string representation. + Parameters: + - status: PaymentStatus enum value. + Returns: + - std::string representing the PaymentStatus. + */ inline std::string getPaymentStatusString(PaymentStatus status) { switch (status) @@ -106,6 +160,16 @@ namespace util throw std::invalid_argument("Invalid PaymentStatus"); } + /* + Function: getPaymentStatus + Description: Converts a string value to its corresponding PaymentStatus enum. + Parameters: + - value: std::string representing the PaymentStatus. + Returns: + - PaymentStatus enum value. + Throws: + - std::invalid_argument if the string does not match a valid PaymentStatus. + */ inline PaymentStatus getPaymentStatus(const std::string& value) { if (value == "PENDING") @@ -121,20 +185,40 @@ namespace util throw std::invalid_argument("Invalid PaymentStatus string"); } + /* + Function: getServiceJobStatusString + Description: Converts a ServiceJobStatus enum value to its corresponding string representation. + Parameters: + - status: ServiceJobStatus enum value. + Returns: + - std::string representing the ServiceJobStatus. + */ inline std::string getServiceJobStatusString(ServiceJobStatus status) { switch (status) { + case ServiceJobStatus::PENDING: + return "PENDING"; case ServiceJobStatus::STARTED: return "STARTED"; case ServiceJobStatus::COMPLETED: return "COMPLETED"; - case ServiceJobStatus::PENDING: - return "PENDING"; + case ServiceJobStatus::CANCELLED: + return "CANCELLED"; } throw std::invalid_argument("Invalid ServiceJobStatus"); } + /* + Function: getServiceJobStatus + Description: Converts a string value to its corresponding ServiceJobStatus enum. + Parameters: + - value: std::string representing the ServiceJobStatus. + Returns: + - ServiceJobStatus enum value. + Throws: + - std::invalid_argument if the string does not match a valid ServiceJobStatus. + */ inline ServiceJobStatus getServiceJobStatus(const std::string& value) { if (value == "STARTED") @@ -149,31 +233,53 @@ namespace util { return ServiceJobStatus::PENDING; } + if (value == "CANCELLED") + { + return ServiceJobStatus::CANCELLED; + } throw std::invalid_argument("Invalid ServiceJobStatus string"); } + /* + Function: getStateString + Description: Converts a State enum value to its corresponding string representation. + Parameters: + - status: State enum value. + Returns: + - std::string representing the State. + */ inline std::string getStateString(State status) { switch (status) { case State::ACTIVE: - return "STARTED"; + return "ACTIVE"; case State::INACTIVE: - return "COMPLETED"; + return "INACTIVE"; } throw std::invalid_argument("Invalid State"); } + /* + Function: getState + Description: Converts a string value to its corresponding State enum. + Parameters: + - value: std::string representing the State. + Returns: + - State enum value. + Throws: + - std::invalid_argument if the string does not match a valid State. + */ inline State getState(const std::string& value) { if (value == "ACTIVE") { return State::ACTIVE; } - if (value == "COMPLETED") + if (value == "INACTIVE") { return State::INACTIVE; } throw std::invalid_argument("Invalid State string"); } -} +} \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/FileHelper.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/FileHelper.h new file mode 100644 index 0000000..3a532b1 --- /dev/null +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/FileHelper.h @@ -0,0 +1,79 @@ +/* +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 +#include +#include +#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: Vector containing all records (excluding header) + Throws: + - None (creates file if missing) + */ + inline util::Vector loadRecords(const std::string& filePath) + { + util::Vector 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&, 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& 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'; + } + } +} diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/FileManager.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/FileManager.h new file mode 100644 index 0000000..35d2935 --- /dev/null +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/FileManager.h @@ -0,0 +1,117 @@ +/* +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 +#include +#include +#include "Vector.h" +#include "Map.h" + +namespace util +{ + template using objects = util::Map; + + template + class FileManager + { + private: + std::string m_filePath; + public: + FileManager() : m_filePath("") {} + FileManager(const std::string& filePath) : m_filePath(filePath) {} + objects load(); + void save(const objects&); + }; + + /* + 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 containing deserialized objects + Throws: + - std::runtime_error if deserialization fails for any record + */ + template + objects FileManager::load() + { + objects records; + std::ifstream file(m_filePath); + if (!file.is_open()) + { + std::ofstream newFile(m_filePath); + newFile.close(); + file.open(m_filePath); + } + util::Vector 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&, map of objects to save + Returns: + - void + Throws: + - std::runtime_error if the file cannot be opened for writing + */ + template + void FileManager::save(const objects& records) + { + util::Vector 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'; + } + } +} \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/InputHelper.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/InputHelper.h index d8fee08..e789442 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/InputHelper.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/InputHelper.h @@ -34,7 +34,7 @@ namespace util /* * Function: read - * Description: Reads a line of text input from console into a string. + * Description: Reads a line of text input from console into a string and cleans it up. * Parameters: * value - reference to a string where the input will be stored * Returns: @@ -43,6 +43,15 @@ 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; } /* diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/StringHelper.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/StringHelper.h new file mode 100644 index 0000000..0d7839a --- /dev/null +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/StringHelper.h @@ -0,0 +1,36 @@ +/* +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 +#include + +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(character))) + { + result = result * 10 + (character - '0'); + } + } + return result; + } +} \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Utility.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Utility.h index cb9b990..300d5c4 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Utility.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Utility.h @@ -1,15 +1,102 @@ -#pragma once -#include "Service.h" -#include "InventoryItem.h" +/* +File: Utility.h +Description: Header file declaring utility functions used across the system +Author: Trenser +Date:19-May-2026 +*/ -inline double calculatePartsCost(const Service* service) +#pragma once +#include "ComboPackage.h" +#include "DataStore.h" +#include "FileHelper.h" +#include "InventoryItem.h" +#include "NotificationManagementService.h" +#include "Service.h" + +namespace util { - double cost = 0; - auto& requiredInventoryItems = service->getRequiredInventoryItems(); - int requiredInventoryItemsSize = requiredInventoryItems.getSize(); - for (int index = 0; index < requiredInventoryItemsSize; index++) + /* + 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) { - cost += requiredInventoryItems.getValueAt(index)->getPrice(); + double cost = 0; + auto& requiredInventoryItems = service->getRequiredInventoryItems(); + int requiredInventoryItemsSize = requiredInventoryItems.getSize(); + for (int index = 0; index < requiredInventoryItemsSize; index++) + { + cost += requiredInventoryItems.getValueAt(index)->getPrice(); + } + return cost; + } + + /* + 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; + } + + /* + 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) + { + 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); } - return cost; } \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/AdminMenu.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/AdminMenu.cpp index 43cccc1..275b9b0 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/AdminMenu.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/AdminMenu.cpp @@ -1,65 +1,292 @@ -#include -#include "AdminMenu.h" -#include "MenuHelper.h" -#include "Service.h" -#include "InputHelper.h" -#include "OutputHelper.h" -#include "ServiceBooking.h" -#include "Enums.h" -#include "InventoryItem.h" +/* +File: AdminMenu.cpp +Description: Implements the AdminMenu class which provides the administrator’s console interface + in the Vehicle Service Management System. Handles menu display, user input, and + admin-specific operations such as inventory management, technician management, + service creation, combo package management, job assignment, and notifications. +Author: Trenser +Date: 19-May-2026 +*/ +#include +#include +#include "Enums.h" +#include "InputHelper.h" +#include "InventoryItem.h" +#include "MenuHelper.h" +#include "OutputHelper.h" +#include "Service.h" +#include "ServiceBooking.h" +#include "User.h" +#include "Utility.h" +#include "Validator.h" + +/* +Function: showMenu +Description: Displays the admin menu and handles user input until logout is selected. +Parameter: None +Return type: void +*/ void AdminMenu::showMenu() { - bool isMenuActive = true; - while (isMenuActive) + while (true) + { + try + { + int choice; + util::clear(); + std::cout << "Admin Menu" + << "\n1. View Stock Levels" + << "\n2. Add Inventory Item" + << "\n3. Remove Inventory Item" + << "\n4. Check Stock Availability" + << "\n5. Assign Job to Technician" + << "\n6. Add Technician" + << "\n7. Remove Customer/Technician" + << "\n8. Create Service" + << "\n9. Remove Service" + << "\n10. Create Combo Package" + << "\n11. Remove Combo Package" + << "\n12. View Notifications" + << "\n13. Change Password" + << "\n14. Logout" + << "\nEnter a choice: "; + util::read(choice); + if (!handleOperation(choice)) + { + break; + } + } + catch (const std::exception& e) + { + std::cout << "Exception: " << e.what() << std::endl; + util::pressEnter(); + } + } +} + +/* +Function: handleOperation +Description: Executes the corresponding admin operation based on the selected menu choice. +Parameter: int choice - selected menu option +Return type: bool - true if menu continues, false if logout +*/ +bool AdminMenu::handleOperation(int choice) +{ + switch (choice) + { + case 1: + viewStockLevels(); + break; + case 2: + addInventoryItem(); + break; + case 3: + removeInventoryItem(); + break; + case 4: + checkStockAvailability(); + break; + case 5: + assignJob(); + break; + case 6: + addTechnician(); + break; + case 7: + removeUser(); + break; + case 8: + createService(); + break; + case 9: + removeService(); + break; + case 10: + createComboPackages(); + break; + case 11: + removeComboPackage(); + break; + case 12: + viewNotifications(); + break; + case 13: + changePassword(); + break; + case 14: + logout(); + return false; + default: + std::cout << "Enter a valid choice!" << std::endl; + util::pressEnter(); + } + return true; +} + +/* +Function: logout +Description: Logs out the currently authenticated admin user. +Parameter: None +Return type: void +*/ +void AdminMenu::logout() +{ + m_controller.logout(); +} + +/* +Function: changePassword +Description: Allows the admin to change their password after validation. +Parameter: None +Return type: void +*/ +void AdminMenu::changePassword() +{ + changePasswordHelper(m_controller); +} + +/* +Function: viewStockLevels +Description: Displays all active inventory items with their details + including ID, part name, quantity, and price. +Parameter: None +Return type: void +*/ +void AdminMenu::viewStockLevels() +{ + util::clear(); + auto inventoryItems = m_controller.getInventoryItems(); + std::cout << std::left << std::setw(15) << "Item ID" + << std::setw(25) << "Part Name" + << std::setw(10) << "Quantity" + << std::setw(10) << "Price" + << std::endl; + for (int iterator = 0; iterator < inventoryItems.getSize(); ++iterator) { - try + const InventoryItem* item = inventoryItems.getValueAt(iterator); + if (item != nullptr) { - int choice; - util::clear(); - std::cout << "" << std::endl; - util::read(choice); - if (!handleOperation(choice)) + if (item->getState() != util::State::INACTIVE) { - isMenuActive = false; + std::cout << std::left << std::setw(15) << item->getId() + << std::setw(25) << item->getPartName() + << std::setw(10) << item->getQuantity() + << std::setw(10) << item->getPrice() + << std::endl; } } - catch (const std::exception& e) - { - std::cout << "Exception: " << e.what() << std::endl; - util::pressEnter(); - } } } -bool AdminMenu::handleOperation(int choice) -{ - return false; -} - - -void AdminMenu::logout() -{ -} - -void AdminMenu::changePassword() -{ -} - -void AdminMenu::viewStockLevels() -{ -} - +/* +Function: addInventoryItem +Description: Allows the admin to either add a new inventory item + or increase the quantity of an existing item. +Parameter: None +Return type: void +*/ void AdminMenu::addInventoryItem() { + util::clear(); + int choice, quantity; + double price; + std::string partName; + std::cout << "1. Add new item \n2. Add Quantity\nEnter your choice : "; + util::read(choice); + switch (choice) + { + case 1: + { + std::cout << "--------Enter Item Details----------\n"; + std::cout << "Part Name : "; + util::read(partName); + std::cout << "Quantity : "; + util::read(quantity); + std::cout << "Price : "; + util::read(price); + m_controller.addInventoryItem(partName, quantity, price); + std::cout << "New Item " << partName << " added to the Inventory.\n"; + break; + } + case 2: + { + auto inventoryItems = m_controller.getInventoryItems(); + addQuantityToItem(inventoryItems, m_controller); + break; + } + } + util::pressEnter(); } +/* +Function: removeInventoryItem +Description: Removes an active inventory item by marking it inactive + after user selection. +Parameter: None +Return type: void +*/ void AdminMenu::removeInventoryItem() { + util::clear(); + auto inventoryItems = m_controller.getInventoryItems(); + auto activeItems = filterActiveItems(inventoryItems); + int activeItemsSize = activeItems.getSize(); + if (activeItemsSize == 0) + { + std::cout << "No items available in Inventory." << std::endl; + util::pressEnter(); + return; + } + displayInventoryWithItems(activeItems); + int itemIndex; + std::cout << "Enter the index of the item to remove: "; + util::read(itemIndex); + if (itemIndex < 1 || itemIndex > activeItemsSize) + { + std::cout << "Invalid index selected." << std::endl; + util::pressEnter(); + return; + } + const InventoryItem* selectedItem = activeItems.getValueAt(itemIndex - 1); + if (selectedItem != nullptr) + { + if(selectedItem->getState() != util::State::INACTIVE) + { + std::string selectedItemId = selectedItem->getId(); + m_controller.removeInventoryItem(selectedItemId); + std::cout << "Item " << selectedItem->getPartName() << " removed successfully." << std::endl; + } + } + util::pressEnter(); } +/* +Function: checkStockAvailability +Description: Checks if a specific inventory item is available + and displays its details if active. +Parameter: None +Return type: void +*/ void AdminMenu::checkStockAvailability() { + util::clear(); + std::string itemId; + std::cout << "Enter the Item Id : "; + util::read(itemId); + const InventoryItem* selectedItem = m_controller.getInventoryItem(itemId); + if (selectedItem != nullptr) + { + if (selectedItem->getState() != util::State::INACTIVE) + { + std::cout << "Item Details\n"; + std::cout << "---------------------------------------------\n"; + std::cout << "Item ID : " << selectedItem->getId() << "\n"; + std::cout << "Part Name : " << selectedItem->getPartName() << "\n"; + std::cout << "Quantity : " << selectedItem->getQuantity() << "\n"; + } + } + util::pressEnter(); } /* @@ -159,22 +386,179 @@ void AdminMenu::removeService() util::pressEnter(); } +/* +Function: addTechnician +Description: Adds a new technician after validating username, password, email, and phone number. +Parameter: None +Return type: void +*/ void AdminMenu::addTechnician() { + util::clear(); + std::string username, name, password, email, phoneNumber; + std::cout << std::left << std::setw(25) << "Enter Technician Username: "; + util::read(username); + std::cout << std::left << std::setw(25) << "Enter Technician Name: "; + util::read(name); + std::cout << std::setw(25) << "Enter Technician Password: "; + util::read(password); + if(!util::isPasswordValid(password)) + { + std::cout << "Error: Password is invalid!"; + util::pressEnter(); + return; + } + std::cout << std::setw(25) << "Enter Technician Email: "; + util::read(email); + if(!util::isEmailValid(email)) + { + std::cout << "Error: Email is invalid!"; + util::pressEnter(); + return; + } + std::cout << std::setw(25) << "Enter Technician Phone: "; + util::read(phoneNumber); + if(!util::isPhoneNumberValid(phoneNumber)) + { + std::cout << "Error: Phone Number is invalid!"; + util::pressEnter(); + return; + } + m_controller.createTechnician(username, name, password, email, phoneNumber); + std::cout << "\nTechnician Added Successfully.\n"; + util::pressEnter(); } +/* +Function: removeUser +Description: Removes a selected active user (customer or technician) from the system. +Parameter: None +Return type: void +*/ void AdminMenu::removeUser() { + util::clear(); + int indexChoice; + auto listOfUsers = m_controller.getUsers(); + auto listOfActiveUsers = filterActiveUsers(listOfUsers); + int activeUserCount = listOfActiveUsers.getSize(); + if (activeUserCount < 1) + { + std::cout << "No Active users." << std::endl; + util::pressEnter(); + return; + } + displayAllActiveUsers(listOfActiveUsers, activeUserCount); + std::cout << "Enter the index of the user to delete : "; + util::read(indexChoice); + if (indexChoice < 1 || indexChoice > activeUserCount) + { + std::cout << "Error Invaild index.\n" << std::endl; + util::pressEnter(); + return; + } + const User* userToRemove = listOfActiveUsers.getValueAt(indexChoice - 1); + if (userToRemove != nullptr) + { + std::string userIdToRemove = userToRemove->getId(); + m_controller.removeUser(userIdToRemove); + std::cout << userToRemove->getUserName() << " removed Successfully.\n"; + } + util::pressEnter(); } +/* +Function: createComboPackages +Description: Creates a new combo package by selecting two active services and applying a discount. +Parameter: None +Return type: void +*/ void AdminMenu::createComboPackages() { + util::clear(); + auto serviceList = m_controller.getServices(); + const int NUMBER_OF_SERVICE_PER_PACKAGE = 2; + util::Vector selectedServiceID; + for (int iterator = 0; iterator < NUMBER_OF_SERVICE_PER_PACKAGE; iterator++) + { + const Service* chosenService = nullptr; + while (true) + { + chosenService = selectServiceFromServices(serviceList); + if (chosenService == nullptr) + { + std::cout << "Failed to create combo package!"; + util::pressEnter(); + return; + } + bool alreadyChosen = false; + for (int iteratorOne = 0; iteratorOne < selectedServiceID.getSize(); iteratorOne++) + { + if (selectedServiceID[iteratorOne] == chosenService->getId()) + { + alreadyChosen = true; + break; + } + } + if (alreadyChosen) + { + std::cout << "Service already selected. Please choose a different one." << std::endl; + continue; + } + selectedServiceID.push_back(chosenService->getId()); + util::clear(); + break; + } + } + std::string packageName; + double discountPercentage; + std::cout << "Enter combo package name: "; + util::read(packageName); + std::cout << "Enter discount percentage: "; + util::read(discountPercentage); + if (discountPercentage < 0.0 || discountPercentage > 100.0) + { + std::cout << "Error: Discount percentage must be between 0 and 100." << std::endl; + util::pressEnter(); + return; + } + m_controller.createComboPackage(packageName, selectedServiceID, discountPercentage); + std::cout << "Combo package '" << packageName << "' created successfully." << std::endl; + util::pressEnter(); } +/* +Function: removeComboPackage +Description: Removes a selected combo package from the system. +Parameter: None +Return type: void +*/ void AdminMenu::removeComboPackage() { + util::clear(); + util::Map currentComboPackages = m_controller.getComboPackages(); + std::string selectedComboPackageID = selectComboPackage(currentComboPackages); + if (selectedComboPackageID != "") + { + m_controller.removeComboPackage(selectedComboPackageID); + std::cout << "Combo Package removed successfully.\n"; + } + else + { + std::cout << "Combo package removal failed.\n"; + } + util::pressEnter(); } +/* +Function: viewNotifications +Description: Displays notifications for the admin and allows deletion of notifications. +Parameters: + - None +Returns: + - void +*/ void AdminMenu::viewNotifications() { -} \ No newline at end of file + viewAndDeleteNotification(m_controller); +} diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/AdminMenu.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/AdminMenu.h index 05fdd84..8b1b31f 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/AdminMenu.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/AdminMenu.h @@ -1,3 +1,12 @@ +/* +File: AdminMenu.h +Description: Header file declaring the AdminMenu class, which provides + administrative operations such as inventory management, + user management, service configuration, and notifications. +Author: Trenser +Date:19-May-2026 +*/ + #pragma once #include "Controller.h" diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp index dde094c..20f538c 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp @@ -1,64 +1,230 @@ +/* +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 -#include +#include "ComboPackage.h" #include "CustomerMenu.h" -#include "InputHelper.h" -#include "MenuHelper.h" -#include "OutputHelper.h" -#include "Invoice.h" #include "Enums.h" -#include "ServiceBooking.h" -#include "User.h" -#include "Timestamp.h" -#include "Service.h" +#include "InputHelper.h" #include "InventoryItem.h" +#include "Invoice.h" +#include "Map.h" +#include "Service.h" +#include "ServiceBooking.h" +#include "Timestamp.h" +#include "User.h" +#include "Validator.h" +#include "Vector.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) - { - try - { - int choice; - util::clear(); - std::cout << "" << std::endl; - util::read(choice); - if (!handleOperation(choice)) - { - isMenuActive = false; - } - } - catch (const std::exception& e) - { - std::cout << "Exception: " << e.what() << std::endl; - util::pressEnter(); - } - } + while (true) + { + try + { + int choice; + util::clear(); + 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)) + { + break; + } + } + catch (const std::exception& e) + { + std::cout << "Exception: " << e.what() << std::endl; + util::pressEnter(); + } + } } +/* +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) { - return false; + 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() { + changePasswordHelper(m_controller); } +/* +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: 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 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: 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(); } /* @@ -154,10 +320,34 @@ void CustomerMenu::viewInvoices() util::pressEnter(); } +/* +Function: viewNotifications +Description: Displays notifications for the customer and allows deletion of notifications. +Parameters: + - None +Returns: + - void +*/ void CustomerMenu::viewNotifications() { + viewAndDeleteNotification(m_controller); } + +/* +Function: configureNotifications +Description: Allows the customer to configure notification preferences for payment and service management. +Parameters: + - None +Returns: + - void +*/ void CustomerMenu::configureNotifications() { -} \ No newline at end of file + bool paymentServiceNotifications = getNotificationPreference("Payment Management Service"); + bool serviceManagementNotifications = getNotificationPreference("Service Management Service"); + m_controller.configureNotifications(paymentServiceNotifications, serviceManagementNotifications); + util::clear(); + std::cout << "Notification preferences updated successfully.\n"; + util::pressEnter(); +} diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.h index 886cf62..d491720 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.h @@ -1,3 +1,13 @@ +/* +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" diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/MenuHelper.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/MenuHelper.h index 975fcc7..6dcb97d 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/MenuHelper.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/MenuHelper.h @@ -1,15 +1,34 @@ +/* +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: 21-May-2026 +*/ + +#pragma once +#include #include -#include "Service.h" +#include +#include "ComboPackage.h" +#include "Controller.h" #include "Enums.h" -#include "User.h" -#include "JobCard.h" +#include "InputHelper.h" #include "InventoryItem.h" #include "Invoice.h" -#include "ServiceBooking.h" +#include "JobCard.h" #include "Map.h" -#include "Timestamp.h" -#include "InputHelper.h" +#include "Notification.h" #include "OutputHelper.h" +#include "Service.h" +#include "ServiceBooking.h" +#include "Timestamp.h" +#include "User.h" +#include "Utility.h" +#include "Validator.h" +#include "Vector.h" + /* Function: selectServicesToRemove (static helper) @@ -37,15 +56,15 @@ inline std::string selectServicesToRemove(util::Map { continue; } - std::cout << std::left - << std::setw(6) << currentIndex + std::cout << std::left + << std::setw(6) << currentIndex << std::setw(12) << currentService->getId() << std::setw(20) << currentService->getName() << std::setw(10) << currentService->getLaborCost() - << std::endl; + << std::endl; hasServices = true; currentServicesMap.insert(currentIndex++, currentService); - } + } if (!hasServices) { std::cout << "No services currently available." << std::endl; @@ -58,7 +77,7 @@ inline std::string selectServicesToRemove(util::Map return currentServicesMap.getValueAt(currentServicesMap.find(choice))->getId(); } else - { +{ std::cout << "Invalid choice." << std::endl; return ""; } @@ -71,7 +90,7 @@ Parameters: - currentInventoryItems: util::Map&, available inventory items - selectedInventoryItems: util::Vector&, vector to store selected item IDs Returns: - - void + - void */ static void selectInventoryItems(util::Map& currentInventoryItems, util::Vector& selectedInventoryItems) { @@ -84,7 +103,7 @@ static void selectInventoryItems(util::Map& c std::cout << "Inventory empty."; } while (doRun) - { +{ bool hasInventoryItems = false; int currentIndex = 1; currentInventoryMap.clear(); @@ -96,12 +115,12 @@ static void selectInventoryItems(util::Map& c << std::setw(10) << "Quantity" << std::endl; for (int iterator = 0; iterator < currentInventoryItems.getSize(); iterator++) - { + { const InventoryItem* currentInventoryItem = currentInventoryItems.getValueAt(iterator); if (currentInventoryItem->getState() == util::State::INACTIVE) - { - continue; - } + { + continue; + } std::cout << std::left << std::setw(6) << currentIndex << std::setw(12) << currentInventoryItem->getId() @@ -117,25 +136,25 @@ static void selectInventoryItems(util::Map& c { std::cout << "No items present in the inventory." << std::endl; doRun = false; - break; - } + break; + } std::cout << "Select the item (Index) or enter -1 to exit: "; util::read(choice); if (choice == -1) - { +{ doRun = false; - } + } else if (currentInventoryMap.find(choice) != -1) - { +{ selectedInventoryItems.push_back(currentInventoryMap.getValueAt(choice)->getId()); std::cout << "Item added successfully." << std::endl; - } - else - { + } + else + { std::cout << "Enter a valid integer." << std::endl; - } - } + } + } } /* @@ -150,10 +169,10 @@ Returns: */ static bool listServiceBookings(util::Map& currentBookings, int& bookingsSize, util::Map& serviceBookingsMap) { - int currentIndex = 1; + int currentIndex = 1; bool hasPendingService = false; - std::cout << std::left - << std::setw(10) << "Index" + std::cout << std::left + << std::setw(10) << "Index" << std::setw(10) << "ID" << std::setw(12) << "Status" << std::setw(12) << "CustID" @@ -163,16 +182,16 @@ static bool listServiceBookings(util::Map& c << std::setw(15) << "Model" << std::setw(20) << "Technician" << std::setw(15) << "TechnicianID" - << std::endl; + << std::endl; for (int iterator = 0; iterator < bookingsSize; iterator++) - { + { const ServiceBooking* currentBooking = currentBookings.getValueAt(iterator); if (currentBooking && currentBooking->getStatus() == util::ServiceJobStatus::PENDING) - { + { hasPendingService = true; const User* currentAssignedTechnician = currentBooking->getAssignedTechnician(); - std::cout << std::left - << std::setw(10) << currentIndex + std::cout << std::left + << std::setw(10) << currentIndex << std::setw(10) << currentBooking->getId() << std::setw(12) << util::getServiceJobStatusString(currentBooking->getStatus()) << std::setw(12) << currentBooking->getCustomerId() @@ -182,15 +201,15 @@ static bool listServiceBookings(util::Map& c << std::setw(15) << currentBooking->getVehicleModel() << std::setw(20) << ((currentAssignedTechnician == nullptr || currentAssignedTechnician->getName().empty()) ? "Null" : currentAssignedTechnician->getName()) << std::setw(15) << ((currentAssignedTechnician == nullptr || currentAssignedTechnician->getId().empty()) ? "Null" : currentAssignedTechnician->getId()) - << std::endl; + << std::endl; serviceBookingsMap.insert(currentIndex++, currentBooking); - } + } } if (!hasPendingService) - { + { std::cout << "No pending service available." << std::endl; return false; - } + } return true; } @@ -206,16 +225,16 @@ static const ServiceBooking* selectPendingServiceBookings(util::Map currentAvailableTechnicians, int numberOfTechnicians, util::Map& currentAvailableTechniciansMap) { bool hasTechnicians = false; - int currentIndex = 1; - std::cout << std::left + int currentIndex = 1; + std::cout << std::left << std::setw(6) << "Index" << std::setw(15) << "Technician ID" << std::setw(20) << "Name" - << std::endl; + << std::endl; for (int iterator = 0; iterator < numberOfTechnicians; iterator++) - { + { const User* currentTechnician = currentAvailableTechnicians.getValueAt(iterator); if (currentTechnician->getState() == util::State::INACTIVE) - { - continue; - } + { + continue; + } hasTechnicians = true; - std::cout << std::left + std::cout << std::left << std::setw(6) << currentIndex << std::setw(15) << currentTechnician->getId() << std::setw(20) << currentTechnician->getName() - << std::endl; + << std::endl; currentAvailableTechniciansMap.insert(currentIndex++, currentTechnician); - } + } if (!hasTechnicians) - { + { std::cout << "No technicians currently available."; - } + } } /* @@ -267,18 +286,18 @@ Returns: - const User*: Pointer to the selected technician, or nullptr if invalid */ static const User* selectTechnician(util::Map& currentAvailableTechniciansMap) -{ + { int userInputIndex; util::read(userInputIndex); if (currentAvailableTechniciansMap.find(userInputIndex) != -1) - { + { return currentAvailableTechniciansMap.getValueAt(userInputIndex); - } + } else - { + { std::cout << "Enter a valid index."; return nullptr; - } + } } /* @@ -308,7 +327,7 @@ static std::string selectInvoiceFromUserForPayment(const util::MapgetStatus() == util::PaymentStatus::PENDING) - { +{ const User* currentTechnician = currentInvoice->getBooking()->getAssignedTechnician(); std::cout << std::left << std::setw(6) << currentIndex @@ -327,7 +346,7 @@ static std::string selectInvoiceFromUserForPayment(const util::MapgetId(); - } + } else { std::cout << "Invalid choice.\n"; return ""; - } + } } /* @@ -360,20 +379,20 @@ static util::PaymentMode selectPaymentMode() std::cout << "Enter the payment Mode\n1.OFFLINE\n2.ONLINE\nChoice: "; util::read(choice); if (choice == 1) - { + { std::cout << "Offline mode selected.\n"; return util::PaymentMode::OFFLINE; } else if (choice == 2) - { + { std::cout << "Online mode selected.\n"; return util::PaymentMode::ONLINE; - } + } else { std::cout << "Invalid choice, Offline mode selected.\n"; return util::PaymentMode::OFFLINE; - } + } } /* @@ -390,18 +409,18 @@ Throws: static void displayInvoices(util::Map currentUserInvoices) { if (currentUserInvoices.getSize() == 0) - { + { std::cout << "No invoices found for this account." << std::endl; util::pressEnter(); - return; - } + return; + } else - { + { for (int index = 0; index < currentUserInvoices.getSize(); index++) - { + { const Invoice* currentInvoice = currentUserInvoices.getValueAt(index); if (currentInvoice) - { + { const User* currentTechnician = currentInvoice->getBooking()->getAssignedTechnician(); std::cout << "\nInvoice Details\n"; std::cout << "Booking ID: " << currentInvoice->getBookingId() << std::endl; @@ -423,25 +442,25 @@ static void displayInvoices(util::Map currentUserIn << std::setw(20) << "ItemName" << std::setw(10) << "Quantity" << std::setw(10) << "Price" - << std::endl; + << std::endl; std::cout << std::string(40, '-') << std::endl; for (int iterator = 0; iterator < inventoryItemsInInvoice.getSize(); iterator++) - { + { InventoryItem* currentItem = inventoryItemsInInvoice.getValueAt(iterator); std::cout << std::left << std::setw(20) << currentItem->getPartName() << std::setw(10) << currentItem->getQuantity() << std::setw(10) << currentItem->getPrice() << std::endl; - } - } + } +} else - { + { throw std::runtime_error("Null invoice encountered while displaying invoices."); util::pressEnter(); - } - } - } + } + } + } } /* @@ -454,7 +473,7 @@ Returns: - std::string: ID of the selected job card, or empty string if none selected */ static std::string selectJobCardToComplete(util::Map& assignedJobCards, util::Map& incompleteJobCards) -{ + { int currentIndex = 1; int choice; bool hasIncompleteJobCard = false; @@ -466,10 +485,10 @@ static std::string selectJobCardToComplete(util::MapgetStatus() == util::ServiceJobStatus::STARTED)) - { + { std::cout << std::left << std::setw(6) << currentIndex << std::setw(12) << currentJobCard->getBookingId() << std::setw(12) << currentJobCard->getId() @@ -478,24 +497,529 @@ static std::string selectJobCardToComplete(util::MapgetId(); - } - else - { + } + else + { std::cout << "Invalid choice.\n"; - return ""; - } + return ""; + } +} + +/* +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& notifications - list of notifications +Return type: const Notification* - pointer to the selected notification +*/ +inline const Notification* selectNotification(const util::Vector& notifications) +{ + if (notifications.getSize() == 0) + { + std::cout << "No notifications available." << std::endl; + return nullptr; + } + util::Map indexedNotifications; + 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 index = 0; index < notifications.getSize(); index++) + { + const Notification* currentNotification = notifications[index]; + 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; + indexedNotifications.insert(currentIndex, currentNotification); + currentIndex++; + } + } + int selectedIndex; + std::cout << "Select notification: "; + util::read(selectedIndex); + if (!indexedNotifications.containsKey(selectedIndex)) + { + std::cout << "Invalid selection." << std::endl; + return nullptr; + } + return indexedNotifications[selectedIndex]; +} + +/* +Function: displayNotification +Description: Displays detailed information about a single notification, including ID, title, timestamp, and message. +Parameters: + - notification: Pointer to the Notification object to be displayed. +Returns: + - void +*/ +inline void displayNotification(const Notification* notification) +{ + util::clear(); + if (!notification) + { + std::cout << "Notification not found." << std::endl; + return; + } + std::cout << "Notification Details" << std::endl; + std::cout << "ID : " << notification->getId() << std::endl; + std::cout << "Title : " << notification->getTitle() << std::endl; + std::cout << "Timestamp : " << notification->getCreatedAt().toString() << std::endl; + std::cout << "Message : " << notification->getMessage() << std::endl; +} + +/* +Function: viewAndDeleteNotification +Description: Allows the user to view a notification and then delete it from the system using the controller. +Parameters: + - controller: Reference to the Controller object used to manage notifications. +Returns: + - void +*/ +inline void viewAndDeleteNotification(Controller& controller) +{ + util::clear(); + auto notifications = controller.getNotifications(); + const Notification* selectedNotification = selectNotification(notifications); + if (!selectedNotification) + { + std::cout << "Failed to display notification!"; + util::pressEnter(); + return; + } + displayNotification(selectedNotification); + controller.deleteNotification(selectedNotification->getId()); + util::pressEnter(); +} + +/* +Function: changePassword +Description: Helper function to change password +Parameter: controller: Reference to the Controller object used to manage notifications. +Return type: void +*/ +inline void changePasswordHelper(Controller& controller) +{ + util::clear(); + std::string newPassword; + while (true) + { + util::clear(); + std::cout << "Enter new password: "; + util::read(newPassword); + if (!util::isPasswordValid(newPassword)) + { + std::cout << "Error: Password is not strong enough!\n"; + util::pressEnter(); + continue; + } + controller.changePassword(newPassword); + std::cout << "Password changed successfully\n"; + util::pressEnter(); + break; + } +} + +/* +Function: filterActiveUsers +Description: Filters out inactive users and returns a map of active users. +Parameter: const util::Map& listOfUsers - all users +Return type: util::Map +*/ +inline util::Map filterActiveUsers(const util::Map& listOfUsers) +{ + util::Map activeUsers; + int inventorySize = listOfUsers.getSize(); + for (int index = 0; index < inventorySize; index++) + { + const User* user = listOfUsers.getValueAt(index); + if (user != nullptr && user->getState() != util::State::INACTIVE) + { + activeUsers.insert(user->getId(), user); + } + } + return activeUsers; +} + +/* +Function: displayAllActiveUsers +Description: Displays all active users in a tabular format with index, ID, username, and type. +Parameter: util::Map& activeUsers - active users list + int activeUserCount - number of active users +Return type: void +*/ +inline void displayAllActiveUsers(util::Map& activeUsers, int activeUserCount) +{ + std::cout << std::left << std::setw(10) << "Index" + << std::setw(15) << "User ID" + << std::setw(25) << "Username" + << std::setw(25) << "User Type" + << std::endl; + for (int iterator = 0; iterator < activeUserCount; iterator++) + { + const User* user = activeUsers.getValueAt(iterator); + if (user != nullptr) + { + std::cout << std::left << std::setw(10) << (iterator + 1) + << std::setw(15) << user->getId() + << std::setw(25) << user->getUserName() + << std::setw(25) << util::getUserTypeString(user->getUserType()) + << std::endl; + } + else + { + std::cout << "No users found.\n"; + util::pressEnter(); + return; + } + } +} + +/* +Function: selectServiceFromServices +Description: Displays active services and allows the customer to select one by index. +Parameter: const util::Map& services - list of services +Return type: const Service* - selected service +*/ +inline const Service* selectServiceFromServices(const util::Map& services) +{ + util::Map activeServicesMap; + int currentIndex = 1; + int userInputIndex; + std::cout << std::left + << std::setw(10) << "Index" + << std::setw(15) << "Service ID" + << std::setw(25) << "Service Name" + << std::setw(15) << "Estimated Cost" + << std::endl; + for (int index = 0; index < services.getSize(); index++) + { + const Service* currentService = services.getValueAt(index); + if (currentService == nullptr) + { + throw std::runtime_error("Warning: Encountered a null service\n"); + continue; + } + if (currentService->getState() != util::State::ACTIVE) + { + continue; + } + activeServicesMap.insert(currentIndex, currentService); + double partsCost = util::calculatePartsCost(currentService); + std::cout << std::left + << std::setw(10) << currentIndex + << std::setw(15) << currentService->getId() + << std::setw(25) << currentService->getName() + << std::setw(15) << (currentService->getLaborCost() + partsCost) + << std::endl; + currentIndex++; + } + if (activeServicesMap.getSize() == 0) + { + std::cout << "No active services available." << std::endl; + return nullptr; + } + std::cout << "Enter service index: "; + util::read(userInputIndex); + if (activeServicesMap.find(userInputIndex) == -1) + { + std::cout << "Invalid service index." << std::endl; + return nullptr; + } + return activeServicesMap[userInputIndex]; +} + +/* +Function: selectComboPackageFromPackages +Description: Displays active combo packages and allows the customer to select one by index. +Parameter: const util::Map& comboPackages - list of combo packages +Return type: const ComboPackage* - selected combo package +*/ +inline const ComboPackage* selectComboPackageFromPackages(const util::Map& comboPackages) +{ + util::Map activeComboPackages; + int currentIndex = 1; + int userInputIndex; + std::cout << std::left + << std::setw(10) << "Index" + << std::setw(15) << "Combo Package ID" + << std::setw(15) << "Combo Package Name" + << std::setw(15) << "Estimate Cost" + << std::endl; + for (int index = 0; index < comboPackages.getSize(); index++) + { + const ComboPackage* currentComboPackage = comboPackages.getValueAt(index); + if (currentComboPackage->getState() != util::State::ACTIVE) + { + continue; + } + activeComboPackages.insert(currentIndex, currentComboPackage); + std::cout << std::left + << std::setw(10) << currentIndex + << std::setw(15) << currentComboPackage->getId() + << std::setw(25) << currentComboPackage->getPackageName() + << std::setw(15) << util::calculateComboServiceEstimatedCost(currentComboPackage) + << std::endl; + currentIndex++; + } + if (activeComboPackages.getSize() == 0) + { + std::cout << "No active combo packages available." << std::endl; + return nullptr; + } + std::cout << "Enter combo package index: "; + util::read(userInputIndex); + if (activeComboPackages.find(userInputIndex) == -1) + { + std::cout << "Invalid combo package index." << std::endl; + return nullptr; + } + return activeComboPackages[userInputIndex]; +} + +/* +Function: sendLowStockAlertsToAdmins (static helper) +Description: Sends low stock alert notifications to all admin users for a given inventory item. +Parameters: + - inventoryManagementService: InventoryManagementService&, service used to send notifications + - inventoryItem: const InventoryItem*, pointer to the low-stock inventory item + - adminUsers: const util::Vector&, list of admin users to notify +Returns: + - None +*/ + +/* +Function: getNotificationPreference (static helper) +Description: Helper function to configure notification preferences for a specific service. +Parameters: + - serviceName: Name of the service for which notifications are being configured. +Returns: + - bool: True if notifications are enabled, False if disabled. +*/ +inline bool getNotificationPreference(const std::string& serviceName) +{ + int choice; + while (true) + { + util::clear(); + std::cout << " Configure Notification Preferences\n"; + std::cout << "\n" << serviceName << " Notifications\n"; + std::cout << "1. Enable Notifications\n"; + std::cout << "2. Disable Notifications\n"; + std::cout << "Enter your choice: "; + util::read(choice); + if (choice == 1) + { + return true; + } + if (choice == 2) + { + return false; + } + std::cout << "\nInvalid choice. Please enter 1 or 2.\n"; + util::pressEnter(); + } +} + +/* +Function: filterActiveItems +Description: Filters out inactive inventory items and returns a map + containing only active items. +Parameter: const util::Map& inventoryItems - + map of all inventory items +Return type: util::Map +*/ +inline util::Map filterActiveItems(const util::Map& inventoryItems) +{ + util::Map activeItems; + int inventorySize = inventoryItems.getSize(); + for (int index = 0; index < inventorySize; index++) + { + const InventoryItem* item = inventoryItems.getValueAt(index); + if (item != nullptr && item->getState() != util::State::INACTIVE) + { + activeItems.insert(item->getId(), item); + } + } + return activeItems; +} + +/* +Function: displayInventoryWithItems +Description: Displays inventory items in a tabular format with index, ID, + part name, quantity, and price. +Parameter: util::Map& inventoryItems - + map of inventory items to display +Return type: void +*/ +inline void displayInventoryWithItems(util::Map& inventoryItems) +{ + int inventorySize = inventoryItems.getSize(); + std::cout << std::left << std::setw(10) << "Index" + << std::setw(15) << "Item ID" + << std::setw(25) << "Part Name" + << std::setw(10) << "Quantity" + << std::setw(10) << "Price" + << std::endl; + for (int iterator = 0; iterator < inventorySize; iterator++) + { + const InventoryItem* item = inventoryItems.getValueAt(iterator); + if (item != nullptr) + { + std::cout << std::left << std::setw(10) << (iterator + 1) + << std::setw(15) << item->getId() + << std::setw(25) << item->getPartName() + << std::setw(10) << item->getQuantity() + << std::setw(10) << item->getPrice() + << std::endl; + } + } +} + +/* +Function: addQuantityToItem +Description: Allows the admin to select an active inventory item and + increase its stock quantity. +Parameter: util::Map& inventoryItems - + map of inventory items + Controller& m_controller - controller instance to update stock +Return type: void +*/ +inline void addQuantityToItem(util::Map& inventoryItems, Controller& m_controller) +{ + int itemIndex; + int quantity; + auto activeItems = filterActiveItems(inventoryItems); + int activeSize = activeItems.getSize(); + if (activeSize == 0) + { + std::cout << "No active items available in Inventory" << std::endl; + return; + } + displayInventoryWithItems(activeItems); + std::cout << "Enter the index of the item to update: "; + util::read(itemIndex); + if (itemIndex < 1 || itemIndex > activeSize) + { + std::cout << "Invalid index selected." << std::endl; + return; + } + std::cout << "Enter quantity to add: "; + util::read(quantity); + if (quantity < 0) + { + std::cout << "The quantity should be Greater than 0." << std::endl; + return; + } + const InventoryItem* selectedItem = activeItems.getValueAt(itemIndex - 1); + if (selectedItem != nullptr) + { + std::string selectedItemId = selectedItem->getId(); + m_controller.addInventoryItemStock(selectedItemId, quantity); + std::cout << "Updated " << selectedItem->getPartName() + << " stock. New quantity: " << selectedItem->getQuantity() + << std::endl; + } + else + { + std::cout << "Error: Selected item could not be found." << std::endl; + } +} + +/* +Function: displayComboPackagesWithIndex +Description: Displays combo packages with index, ID, name, and discount percentage. +Parameter: util::Map& currentComboPackageIndexMap - combo packages map +Return type: void +*/ +inline void displayComboPackagesWithIndex(util::Map& currentComboPackageIndexMap) +{ + for (int iterator = 0; iterator < currentComboPackageIndexMap.getSize(); iterator++) + { + const ComboPackage* currentComboPackage = currentComboPackageIndexMap.getValueAt(iterator); + if (currentComboPackage == nullptr) + { + throw std::runtime_error("Error accessing the combopackage.\n"); + } + if (iterator == 0) + { + std::cout << std::left + << std::setw(8) << "Index" + << std::setw(10) << "ID" + << std::setw(20) << "Package Name" + << std::setw(15) << "Discount (%)" + << "\n"; + } + std::cout << std::left + << std::setw(8) << currentComboPackageIndexMap.getKeyAt(iterator) + << std::setw(10) << currentComboPackage->getId() + << std::setw(20) << currentComboPackage->getPackageName() + << std::setw(15) << currentComboPackage->getDiscountPercentage() + << "\n"; + } +} + +/* +Function: selectComboPackage +Description: Allows the admin to select an active combo package by index. +Parameter: util::Map& currentComboPackages - combo packages list +Return type: std::string - ID of the selected combo package +*/ +inline std::string selectComboPackage(util::Map& currentComboPackages) +{ + util::Map currentComboPackageIndexMap; + if (currentComboPackages.getSize() == 0) + { + throw std::runtime_error("No combo packages are available.\n"); + } + int currentIndex = 1, choice, selectedIndex; + for (int iterator = 0; iterator < currentComboPackages.getSize(); iterator++) + { + if (currentComboPackages.getValueAt(iterator)->getState() == util::State::INACTIVE) + { + continue; + } + currentComboPackageIndexMap.insert(currentIndex++, currentComboPackages.getValueAt(iterator)); + } + if (currentComboPackageIndexMap.getSize() == 0) + { + throw std::runtime_error("No combo packages currently active."); + } + displayComboPackagesWithIndex(currentComboPackageIndexMap); + std::cout << "Enter your choice(Index): "; + util::read(choice); + selectedIndex = currentComboPackageIndexMap.find(choice); + if (selectedIndex != -1) + { + std::string selectedComboPackageID = currentComboPackageIndexMap.getValueAt(selectedIndex)->getId(); + return selectedComboPackageID; + } + else + { + std::cout << "Enter a valid choice.\n"; + return ""; + } } \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/TechnicianMenu.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/TechnicianMenu.cpp index 1779ff5..7aaddcc 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/TechnicianMenu.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/TechnicianMenu.cpp @@ -1,39 +1,84 @@ -#include -#include "TechnicianMenu.h" +/* +File: TechnicianMenu.cpp +Description: Implementation file containing the method definitions of the + TechnicianMenu class, including menu handling, job completion, + notification viewing, password management, and logout logic. +Author: Trenser +Date:19-May-2026 +*/ +#include "Enums.h" #include "InputHelper.h" +#include "JobCard.h" #include "MenuHelper.h" #include "OutputHelper.h" -#include "JobCard.h" -#include "Enums.h" #include "Service.h" +#include "TechnicianMenu.h" +#include "Validator.h" +/* +Function: showMenu +Description: Displays the technician menu in a loop until the user chooses to logout. + Handles exceptions and ensures smooth user interaction. +Parameters: + - None +Returns: + - void +*/ void TechnicianMenu::showMenu() { - bool isMenuActive = true; - while (isMenuActive) - { - try - { - int choice; - util::clear(); - std::cout << "" << std::endl; - util::read(choice); - if (!handleOperation(choice)) - { - isMenuActive = false; - } - } - catch (const std::exception& e) - { - std::cout << "Exception: " << e.what() << std::endl; - util::pressEnter(); - } - } + while (true) + { + try + { + int choice; + util::clear(); + std::cout << "Technician Menu" + << "\n1. Mark Job as Completed" + << "\n2. View Notifications" + << "\n3. Change Password" + << "\n4. Logout" + << "\nEnter a choice: "; + util::read(choice); + if (!handleOperation(choice)) + { + break; + } + } + catch (const std::exception& e) + { + std::cout << "Exception: " << e.what() << std::endl; + util::pressEnter(); + } + } } +/* +Function: handleOperation +Description: Executes the corresponding technician operation based on the selected menu choice. +Parameter: int choice - selected menu option +Return type: bool - true if menu continues, false if logout +*/ bool TechnicianMenu::handleOperation(int choice) { - return false; + switch (choice) + { + case 1: + completeJob(); + break; + case 2: + viewNotifications(); + break; + case 3: + changePassword(); + break; + case 4: + logout(); + return false; + default: + std::cout << "Enter a valid choice!" << std::endl; + util::pressEnter(); + } + return true; } /* @@ -63,6 +108,38 @@ void TechnicianMenu::completeJob() util::pressEnter(); } +/* +Function: viewNotifications +Description: Displays notifications for the technician and allows deletion of notifications. +Parameters: + - None +Returns: + - void +*/ void TechnicianMenu::viewNotifications() { + viewAndDeleteNotification(m_controller); +} + +/* +Function: logout +Description: Logs out the currently authenticated technician user. +Parameter: None +Return type: void +*/ +void TechnicianMenu::logout() +{ + m_controller.logout(); +} + +/* +Function: changePassword +Description: Allows the technician to change their password after validation. +Parameter: None +Return type: void +*/ + +void TechnicianMenu::changePassword() +{ + changePasswordHelper(m_controller); } \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/TechnicianMenu.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/TechnicianMenu.h index c366d9b..3c7e9ed 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/TechnicianMenu.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/TechnicianMenu.h @@ -1,3 +1,12 @@ +/* +File: TechnicianMenu.h +Description: Header file declaring the TechnicianMenu class, which provides + technician operations such as job completion, notification viewing, + password management, and logout functionality. +Author: Trenser +Date:19-May-2026 +*/ + #pragma once #include "Controller.h" @@ -10,4 +19,6 @@ public: void showMenu(); void completeJob(); void viewNotifications(); + void logout(); + void changePassword(); }; diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/UserInterface.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/UserInterface.cpp index 122f9a8..d1c48ba 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/UserInterface.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/UserInterface.cpp @@ -1,9 +1,30 @@ -#include "UserInterface.h" +/* +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 "Enums.h" #include "InputHelper.h" #include "OutputHelper.h" +#include "User.h" +#include "UserInterface.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(); + m_controller.runSystemChecks(); bool isMenuActive = true; while (isMenuActive) { @@ -24,8 +45,15 @@ 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) @@ -46,12 +74,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(); } diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/UserInterface.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/UserInterface.h index da3862e..501cfce 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/UserInterface.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/UserInterface.h @@ -1,3 +1,13 @@ +/* +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"